Implement atomic_fetchadd_long() for all architectures and document it.

Reviewed by:	attilio, jhb, jeff, kris (as a part of the uidinfo_waitfree.patch)
This commit is contained in:
Pawel Jakub Dawidek 2008-03-16 21:20:50 +00:00
parent 3de1800850
commit 6eb4157ffc
7 changed files with 46 additions and 1 deletions

View File

@ -211,7 +211,8 @@ return tmp;
The
.Fn atomic_fetchadd
functions are only implemented for the types
.Dq Li int
.Dq Li int ,
.Dq Li long
and
.Dq Li 32
and do not have any variants with memory barriers at this time.

View File

@ -74,6 +74,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);
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);
u_long atomic_fetchadd_long(volatile u_long *p, u_long v);
#define ATOMIC_STORE_LOAD(TYPE, LOP, SOP) \
u_##TYPE atomic_load_acq_##TYPE(volatile u_##TYPE *p); \
@ -174,6 +175,25 @@ atomic_fetchadd_int(volatile u_int *p, u_int v)
return (v);
}
/*
* Atomically add the value of v to the long integer pointed to by p and return
* the previous value of *p.
*/
static __inline u_long
atomic_fetchadd_long(volatile u_long *p, u_long v)
{
__asm __volatile(
" " MPLOCKED " "
" xaddq %0, %1 ; "
"# atomic_fetchadd_long"
: "+r" (v), /* 0 (result) */
"=m" (*p) /* 1 */
: "m" (*p)); /* 2 */
return (v);
}
#if defined(_KERNEL) && !defined(SMP)
/*

View File

@ -278,6 +278,13 @@ atomic_cmpset_long(volatile u_long *dst, u_long exp, u_long src)
(u_int)src));
}
static __inline u_long
atomic_fetchadd_long(volatile u_long *p, u_long v)
{
return (atomic_fetchadd_int((volatile u_int *)p, (u_int)v));
}
/* Read the current value and store a zero in the destination. */
#ifdef __GNUCLIKE_ASM

View File

@ -371,4 +371,15 @@ atomic_fetchadd_32(volatile uint32_t *p, uint32_t v)
#define atomic_fetchadd_int atomic_fetchadd_32
static __inline u_long
atomic_fetchadd_long(volatile u_long *p, u_long v)
{
u_long value;
do {
value = *p;
} while (!atomic_cmpset_64(p, value, value + v));
return (value);
}
#endif /* ! _MACHINE_ATOMIC_H_ */

View File

@ -502,5 +502,7 @@ atomic_fetchadd_32(volatile uint32_t *p, uint32_t v)
}
#define atomic_fetchadd_int atomic_fetchadd_32
#define atomic_fetchadd_long(p, v) \
(u_long)atomic_fetchadd_32((volatile u_int *)(p), (u_int)(v))
#endif /* ! _MACHINE_ATOMIC_H_ */

View File

@ -279,6 +279,8 @@ ATOMIC_GEN(ptr, uintptr_t *, uintptr_t, uintptr_t, 64);
#define atomic_fetchadd_int atomic_add_int
#define atomic_fetchadd_32 atomic_add_32
#define atomic_fetchadd_long(p, v) \
(u_long)atomic_add_int((volatile u_int *)(p), (u_int)(v))
#undef ATOMIC_GEN
#undef atomic_cas

View File

@ -279,6 +279,8 @@ ATOMIC_GEN(ptr, uintptr_t *, uintptr_t, uintptr_t, 64);
#define atomic_fetchadd_int atomic_add_int
#define atomic_fetchadd_32 atomic_add_32
#define atomic_fetchadd_long(p, v) \
(u_long)atomic_add_int((volatile u_int *)(p), (u_int)(v))
#undef ATOMIC_GEN
#undef atomic_cas