3

为了使用 cas,gcc 提供了一些有用的函数,例如
__sync_bool_compare_and_swap

但我们也可以使用像 cmpxchg 这样的 asm 代码

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;

我grep了gcc 4.6.3的源码,发现__sync_bool_compare_and_swap是实现使用

typedef int (__kernel_cmpxchg_t) (int oldval, int newval, int *ptr); 
#define __kernel_cmpxchg (*(__kernel_cmpxchg_t *) 0xffff0fc0)

似乎 0xffff0fc0 是一些内核辅助函数的地址

但是在gcc 4.1.2中,没有像__kernel_cmpxchg_t这样的代码,也找不到__sync_bool_compare_and_swap的实现。

那么 __sync_bool_compare_and_swap 和 cmpxchg 有什么区别?

__sync_bool_compare_and_swap 是由 cmpxchg 实现的吗?

并且使用内核辅助函数 __kernel_cmpxchg_t,它是由 cmpxchg 实现的吗?

谢谢!

4

1 回答 1

4

我认为 __kernel_cmpxchg 是 Linux 在某些不具备对 CAS 的本机硬件支持的架构上提供的后备方案。例如 ARMv5 或类似的东西。

通常,GCC 内联扩展了_sync * 内置函数。除非您真的对 GCC 内部结构感兴趣,否则了解它的作用的更简单方法是制作一个简单的 C 示例并查看编译器生成的 ASM。

考虑


#include <stdbool.h>

bool my_cmpchg(int *ptr, int oldval, int newval)
{
    return __sync_bool_compare_and_swap(ptr, oldval, newval);
}

在使用 GCC 4.4 的 x86_64 Linux 机器上编译它会生成以下 asm:


my_cmpchg:
.LFB0:
    .cfi_startproc
    movl    %esi, %eax
    lock cmpxchgl   %edx, (%rdi)
    sete    %al
    ret
    .cfi_endproc
于 2012-03-21T07:42:46.350 回答