What is the difference between gcc __sync_bool_compare_and_swap and cmpxchg?
To use CAS, GCC provides useful functions such as
:
__sync_bool_compare_and_swap
But we can also use ASM code like CMPXCHG
bool ret;
__asm__ __volatile__(
"lock cmpxchg16b %1;\n"
"sete %0;\n"
:"=m"(ret),"+m" (*(volatile pointer_t *) (addr))
:"a" (old_value.ptr), "d" (old_value.tag), "b" (new_value.ptr), "c" (new_value.tag));
return ret;
I greped the source code for gcc 4.6.3 and found that __sync_bool_compare_and_swap was implemented with it
typedef int (__kernel_cmpxchg_t) (int oldval, int newval, int *ptr);
#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *) 0xffff0fc0)
It seems that 0xffff0fc0 is the address of some kernel helper function
But in gcc 4.1.2, there is no code like this __kernel_cmpxchg_t and I can’t find an implementation of __sync_bool_compare_and_swap either.
So what’s the difference between __sync_bool_compare_and_swap and cmpxchg?
Is __sync_bool_compare_and_swap implemented by cmpxchg?
There are also kernel helper functions__kernel_cmpxchg_t, is it implemented by cmpxchg?
Thanks!
Solution
I think __kernel_cmpxchg is a fallback provided by Linux on some architectures that don’t have CAS native hardware support. For example. ARMv5 or something similar.
Typically, GCC extends the _sync* built-in function inline. Unless you’re really interested in GCC internals, an easier way to understand what it does is to make a simple C example and look at the ASM generated by the compiler.
Consider
#include <stdbool.h>
bool my_cmpchg(int *ptr, int oldval, int newval)
{
return __sync_bool_compare_and_swap(ptr, oldval, newval);
}
Compile on a x86_64 Linux machine with GCC 4.4 to generate the following asm:
my_cmpchg:
. LFB0:
.cfi_startproc
movl %esi, %eax
lock cmpxchgl %edx, (%rdi)
sete %al
ret
.cfi_endproc