assembly x86上的收购-发布

xhv8bpkk  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(187)

在英特尔手册第3卷中,有一个使用早期存储进行加载重新排序的示例。
最初为x = y = 0

核心1

mov [x], 1
mov r2, [y]

核心2

mov [y], 1
mov r1, [x]

所以r1 = r2 = 0是可能的。问题是要求获取-释放是否禁止这种情况?在x86上存储是一个释放存储,所以我认为没有。例如:

核心1

release(mov [x], 1)
mov r2, [y]

核心2

mov [y], 1
acquire(mov r1, [x])

在这种情况下,如果acquire(mov r1, [x])负载观察到0,则只能得出结论,根据C11标准内存模型规范release(mov [x], 1)acquire(mov r1, [x])不同步,并且它不提供任何可能禁止在内核2上重新排序mov [y], 1acquire(mov r1, [x])的保证

jutyujz0

jutyujz01#

正确的获取/释放语义不能阻止StoreLoad重新排序,即在加载之前执行存储,并交换它们的顺序。这种重新排序在x86上的普通加载和存储指令中是允许的。
如果你想在C11中避免这样的重新排序,你需要在存储和加载上都使用memory_order_seq_cst。在x86汇编中,你需要在这两条指令之间使用一个屏障。mfence可以达到这个目的,但是任何lock ed的读-修改-写指令也可以。包括xchg,即使没有lock前缀,它也会这样做。因此,如果您查看为memory_order_seq_cst操作生成的程序集,您将看到中间存在一些这样的障碍。(对于某些reasons,如lock add [rsp], 0xchg(位于某些寄存器和内存之间,其内容并不重要),实际上可能比mfence性能更高,因此有些编译器会这样做,尽管看起来很奇怪。)

相关问题