(Untested, may contain typos):
inline long
val_compare_and_swap(volatile long *ptr, long old, long _new) {
long prev;
asm volatile("lock;"
#if defined(__amd64__)
"cmpxchgq %1, %2;"
#else
"cmpxchgl %1, %2;"
#endif
: "=a"(prev)
: "q"(_new), "m"(*ptr), "a"(old)
: "memory");
return prev;
}
inline int
bool_compare_and_swap(volatile long *ptr, long old, long _new) {
return val_compare_and_swap(ptr, old, new) == old;
}
inline long
fetch_and_add(volatile long *ptr, long value) {
long prev;
do {
prev = *ptr;
} until (bool_compare_and_swap(ptr, prev, prev + value));
return prev;
}
If you need a compare_and_swap that operates on a two-words value rather than just one, see e.g. http://src.chromium.org/svn/trunk/src/third_party/tcmalloc/chromium/src/base/atomicops-internals-x86.h.