我在 i686 架构中使用 cmpxchg(比较和交换)进行 32 位比较和交换,如下所示。
(编者注:原来的 32 位示例有错误,但问题不在于它。我相信这个版本是安全的,而且作为奖励,它也可以正确编译 x86-64。另请注意,为此不需要或不建议使用内联汇编;__atomic_compare_exchange_n或年龄较大的__sync_bool_compare_and_swap
为。。。工作int32_t
or int64_t
在 i486 和 x86-64 上。但这个问题是关于使用内联汇编来做的,以防万一你仍然想要这样做。)
// note that this function doesn't return the updated oldVal
static int CAS(int *ptr, int oldVal, int newVal)
{
unsigned char ret;
__asm__ __volatile__ (
" lock\n"
" cmpxchgl %[newval], %[mem]\n"
" sete %0\n"
: "=q" (ret), [mem] "+m" (*ptr), "+a" (oldVal)
: [newval]"r" (newVal)
: "memory"); // barrier for compiler reordering around this
return ret; // ZF result, 1 on success else 0
}
对于 64 位比较和交换,x86_64 架构的等效项是什么
static int CAS(long *ptr, long oldVal, long newVal)
{
unsigned char ret;
// ?
return ret;
}
The x86_64
指令集有cmpxchgq (q
对于四字)用于 8 字节(64 位)比较和交换的指令。
还有一个cmpxchg8b
该指令适用于 8 字节数量,但设置起来更复杂,需要您使用edx:eax
and ecx:ebx
而不是更自然的 64 位rax
。几乎可以肯定,这种情况存在的原因与 Intel 很早之前就需要 64 位比较和交换操作有关x86_64
伴随着。它仍然以 64 位模式存在,但不再是唯一的选择。
但是,正如所说,cmpxchgq
对于 64 位代码来说可能是更好的选择。
如果您需要 cmpxchg 一个 16 字节对象,则使用 64 位版本cmpxchg8b
is cmpxchg16b。最早的 AMD64 CPU 中缺少它,因此编译器不会为它生成它std::atomic::compare_exchange在 16B 对象上,除非您启用-mcx16
(对于海湾合作委员会)。不过,汇编程序会对其进行汇编,但请注意,您的二进制文件无法在最早的 K8 CPU 上运行。 (这仅适用于cmpxchg16b
,不cmpxchg8b
在 64 位模式下,或cmpxchgq
).
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)