Index: alpha/include/atomic.h =================================================================== RCS file: /usr/cvs/src/sys/alpha/include/atomic.h,v retrieving revision 1.23 diff -u -r1.23 atomic.h --- alpha/include/atomic.h 15 Sep 2005 19:31:22 -0000 1.23 +++ alpha/include/atomic.h 26 Sep 2005 21:05:43 -0000 @@ -365,6 +365,27 @@ return (atomic_cmpset_64(p, cmpval, newval)); } +/* + * Atomically add the value of v to the integer pointed to by p and return + * the previous value of *p. + */ +static __inline u_int +atomic_fetchadd_32(volatile u_int32_t *p, u_int32_t v) +{ + u_int32_t value, temp; + +#ifdef __GNUCLIKE_ASM + __asm __volatile ( + "1:\tldl_l %0, %1\n\t" /* load old value */ + "addl %0, %3, %2\n\t" /* calculate new value */ + "stl_c %2, %1\n\t" /* attempt to store */ + "beq %2, 1b\n" /* spin if failed */ + : "=&r" (value), "=m" (*p), "=r" (temp) + : "r" (v), "m" (*p)); +#endif + return (value); +} + /* Operations on chars. */ #define atomic_set_char atomic_set_8 #define atomic_set_acq_char atomic_set_acq_8 @@ -412,6 +433,7 @@ #define atomic_load_acq_int atomic_load_acq_32 #define atomic_store_rel_int atomic_store_rel_32 #define atomic_readandclear_int atomic_readandclear_32 +#define atomic_fetchadd_int atomic_fetchadd_32 /* Operations on longs. */ #define atomic_set_long atomic_set_64 Index: amd64/include/atomic.h =================================================================== RCS file: /usr/cvs/src/sys/amd64/include/atomic.h,v retrieving revision 1.38 diff -u -r1.38 atomic.h --- amd64/include/atomic.h 15 Sep 2005 19:31:22 -0000 1.38 +++ amd64/include/atomic.h 26 Sep 2005 21:05:43 -0000 @@ -73,6 +73,7 @@ int atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src); int atomic_cmpset_long(volatile u_long *dst, u_long exp, u_long src); +u_int atomic_fetchadd_int(volatile u_int *p, u_int v); #define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p); \ @@ -154,6 +155,25 @@ return (res); } +/* + * Atomically add the value of v to the integer pointed to by p and return + * the previous value of *p. + */ +static __inline u_int +atomic_fetchadd_int(volatile u_int *p, u_int v) +{ + + __asm __volatile ( + " " __XSTRING(MPLOCKED) " " + " xaddl %0, %1 ; " + "# atomic_fetchadd_int" + : "+r" (v), /* 0 (result) */ + "=m" (*p) /* 1 */ + : "m" (*p)); /* 2 */ + + return (v); +} + #if defined(_KERNEL) && !defined(SMP) /* @@ -375,6 +395,7 @@ #define atomic_cmpset_acq_32 atomic_cmpset_acq_int #define atomic_cmpset_rel_32 atomic_cmpset_rel_int #define atomic_readandclear_32 atomic_readandclear_int +#define atomic_fetchadd_32 atomic_fetchadd_int /* Operations on 64-bit quad words. */ #define atomic_set_64 atomic_set_long Index: arm/include/atomic.h =================================================================== RCS file: /usr/cvs/src/sys/arm/include/atomic.h,v retrieving revision 1.10 diff -u -r1.10 atomic.h --- arm/include/atomic.h 27 Jul 2005 20:01:44 -0000 1.10 +++ arm/include/atomic.h 26 Sep 2005 20:58:58 -0000 @@ -262,6 +262,17 @@ return (__swp(0, p)); } +static __inline uint32_t +atomic_fetchadd_32(volatile uint32_t *p, uint32_t v) +{ + uint32_t value; + + do { + value = *p; + } while (!atomic_cmpset_32(p, value, value + v)); + return (value); +} + #undef __with_interrupts_disabled #endif /* _LOCORE */ @@ -291,5 +302,6 @@ #define atomic_store_ptr atomic_store_32 #define atomic_cmpset_ptr atomic_cmpset_32 #define atomic_set_ptr atomic_set_32 +#define atomic_fetchadd_int atomic_fetchadd_32 #endif /* _MACHINE_ATOMIC_H_ */ Index: i386/include/atomic.h =================================================================== RCS file: /usr/cvs/src/sys/i386/include/atomic.h,v retrieving revision 1.40 diff -u -r1.40 atomic.h --- i386/include/atomic.h 15 Sep 2005 19:31:22 -0000 1.40 +++ i386/include/atomic.h 26 Sep 2005 21:05:43 -0000 @@ -72,6 +72,7 @@ void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v) int atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src); +u_int atomic_fetchadd_int(volatile u_int *p, u_int v); #define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \ u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p); \ @@ -163,6 +164,25 @@ #endif /* defined(CPU_DISABLE_CMPXCHG) */ +/* + * Atomically add the value of v to the integer pointed to by p and return + * the previous value of *p. + */ +static __inline u_int +atomic_fetchadd_int(volatile u_int *p, u_int v) +{ + + __asm __volatile ( + " " __XSTRING(MPLOCKED) " " + " xaddl %0, %1 ; " + "# atomic_fetchadd_int" + : "+r" (v), /* 0 (result) */ + "=m" (*p) /* 1 */ + : "m" (*p)); /* 2 */ + + return (v); +} + #if defined(_KERNEL) && !defined(SMP) /* @@ -392,6 +412,7 @@ #define atomic_cmpset_acq_32 atomic_cmpset_acq_int #define atomic_cmpset_rel_32 atomic_cmpset_rel_int #define atomic_readandclear_32 atomic_readandclear_int +#define atomic_fetchadd_32 atomic_fetchadd_int /* Operations on pointers. */ #define atomic_set_ptr atomic_set_int Index: ia64/include/atomic.h =================================================================== RCS file: /usr/cvs/src/sys/ia64/include/atomic.h,v retrieving revision 1.9 diff -u -r1.9 atomic.h --- ia64/include/atomic.h 15 Jul 2005 18:17:58 -0000 1.9 +++ ia64/include/atomic.h 26 Sep 2005 21:05:43 -0000 @@ -342,4 +342,23 @@ #define atomic_readandclear_int atomic_readandclear_32 #define atomic_readandclear_long atomic_readandclear_64 +/* + * Atomically add the value of v to the integer pointed to by p and return + * the previous value of *p. + * + * XXX: Should we use the fetchadd instruction here? + */ +static __inline uint32_t +atomic_fetchadd_32(volatile uint32_t *p, uint32_t v) +{ + uint32_t value; + + do { + value = *p; + } while (!atomic_cmpset_32(p, value, value + v)); + return (value); +} + +#define atomic_fetchadd_int atomic_fetchadd_32 + #endif /* ! _MACHINE_ATOMIC_H_ */ Index: powerpc/include/atomic.h =================================================================== RCS file: /usr/cvs/src/sys/powerpc/include/atomic.h,v retrieving revision 1.13 diff -u -r1.13 atomic.h --- powerpc/include/atomic.h 15 Sep 2005 19:31:22 -0000 1.13 +++ powerpc/include/atomic.h 26 Sep 2005 20:58:58 -0000 @@ -444,4 +444,17 @@ #define atomic_cmpset_acq_ptr atomic_cmpset_acq_32 #define atomic_cmpset_rel_ptr atomic_cmpset_rel_32 +static __inline uint32_t +atomic_fetchadd_32(volatile uint32_t *p, uint32_t v) +{ + uint32_t value; + + do { + value = *p; + } while (!atomic_cmpset_32(p, value, value + v)); + return (value); +} + +#define atomic_fetchadd_int atomic_fetchadd_32 + #endif /* ! _MACHINE_ATOMIC_H_ */ Index: sparc64/include/atomic.h =================================================================== RCS file: /usr/cvs/src/sys/sparc64/include/atomic.h,v retrieving revision 1.9 diff -u -r1.9 atomic.h --- sparc64/include/atomic.h 15 Jul 2005 18:17:58 -0000 1.9 +++ sparc64/include/atomic.h 26 Sep 2005 20:58:58 -0000 @@ -277,6 +277,9 @@ ATOMIC_GEN(ptr, uintptr_t *, uintptr_t, uintptr_t, 64); +#define atomic_fetchadd_int atomic_add_int +#define atomic_fetchadd_32 atomic_add_32 + #undef ATOMIC_GEN #undef atomic_cas #undef atomic_cas_acq