我正在考虑通过gcc查看为原子操作生成的一些程序集。我尝试了以下短序列:
int x1;
int x2;
int foo;
void test()
{
__atomic_store_n( &x1, 1, __ATOMIC_SEQ_CST );
if( __atomic_load_n( &x2 ,__ATOMIC_SEQ_CST ))
return;
foo = 4;
}
看看Herb Sutter关于代码生成的原子武器谈话,他提到X86手册要求使用 xchg
对于原子商店和一个简单的 mov
用于原子读取。所以我期待的是:
test():
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $1, %eax
xchg %eax, x1(%rip)
movl x2(%rip), %eax
testl %eax, %eax
setne %al
testb %al, %al
je .L2
jmp .L1
.L2:
movl $4, foo(%rip)
.L1:
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
由于锁定,内存栅栏是隐含的 xchg
指令。
但是,如果我使用编译它 gcc -march=core2 -S test.cc
我得到以下内容:
test():
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $1, %eax
movl %eax, x1(%rip)
mfence
movl x2(%rip), %eax
testl %eax, %eax
setne %al
testb %al, %al
je .L2
jmp .L1
.L2:
movl $4, foo(%rip)
.L1:
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
所以不要使用 xchg
操作gcc这里用的是 mov + mfence
组合。这个代码生成的原因是什么,与Herb Sutter根据x86架构规定的代码生成不同?