x86:这里需要内存屏障吗?
x86: Are memory barriers needed here?
在 WB 内存中,a = b = 0
P1:
a = 1
SFENCE
b = 1
P2:
WHILE (b == 0) {}
LFENCE
ASSERT (a == 0)
据我了解,这里不需要 SFENCE
或 LFENCE
。
也就是说,因为对于这种内存类型,x86 确保:
- 无法使用较旧的读取重新排序读取
- 商店不能用旧商店重新订购
- 商店是可传递可见的
lfence
和 sfence
asm 指令是无操作的,除非您使用 NT 存储(或从 WC 内存(例如视频 RAM)加载 NT)。 (实际上,movntdqa
loads might only be ordered by mfence
on paper,而不是 lfence
。在那种情况下,我不知道你什么时候会使用 lfence
。它与 sfence
一起添加到 ISA + mfence
与 NT 存储同时,在 movntdqa
之前,可能只是为了完整性/以防万一需要它。)
关于这一点有时会有混淆,因为 lfence
和 sfence
的 C/C++ 内在函数也是编译器障碍。在 C/C++ 中 是 所需要的,但是可以使用 GNU C asm("":::"memory");
或(为了放松-atomic
操作1) std::atomic_signal_fence(std::memory_order_acq_rel)
。限制 compile-time reordering 而不让编译器发出任何无用的 asm 屏障指令。
运行-时间重新排序已经被 x86 内存模型阻止,除了 StoreLoad reordering which requires mfence
to block. lfence
+ sfence
don't add up to mfence
. See Does it make any sense instruction LFENCE in processors x86/x86_64? 和关于这些指令的各种其他 SO 问答。
这就是为什么 std::atomic_thread_fence(std::memory_order_acq_rel)
also compiles to zero instructions on x86,但对弱序架构的障碍。
lfence
也是 Intel 微架构上的序列化指令(但可能不是 AMD?)。一直以来都是如此,但英特尔最近正式做出了这一保证,因此 Spectre 缓解技术可以安全地使用它,而不是更不方便的 cpuid
.
- 脚注 1:
gcc 上的 atomic_signal_fence
也可能是普通非 atomic
变量的编译器障碍;这是我最后一次检查 gcc(而 atomic_thread_fence
不是),但这可能只是一个实现细节,因为没有涉及任何 atomic
变量。当有 atomic
个变量时,编译器知道这些变量可能会提供排序,让其他线程在没有 UB 的情况下访问非原子变量,因此需要排序。
在 WB 内存中,a = b = 0
P1:
a = 1
SFENCE
b = 1
P2:
WHILE (b == 0) {}
LFENCE
ASSERT (a == 0)
据我了解,这里不需要 SFENCE
或 LFENCE
。
也就是说,因为对于这种内存类型,x86 确保:
- 无法使用较旧的读取重新排序读取
- 商店不能用旧商店重新订购
- 商店是可传递可见的
lfence
和 sfence
asm 指令是无操作的,除非您使用 NT 存储(或从 WC 内存(例如视频 RAM)加载 NT)。 (实际上,movntdqa
loads might only be ordered by mfence
on paper,而不是 lfence
。在那种情况下,我不知道你什么时候会使用 lfence
。它与 sfence
一起添加到 ISA + mfence
与 NT 存储同时,在 movntdqa
之前,可能只是为了完整性/以防万一需要它。)
关于这一点有时会有混淆,因为 lfence
和 sfence
的 C/C++ 内在函数也是编译器障碍。在 C/C++ 中 是 所需要的,但是可以使用 GNU C asm("":::"memory");
或(为了放松-atomic
操作1) std::atomic_signal_fence(std::memory_order_acq_rel)
。限制 compile-time reordering 而不让编译器发出任何无用的 asm 屏障指令。
运行-时间重新排序已经被 x86 内存模型阻止,除了 StoreLoad reordering which requires mfence
to block. lfence
+ sfence
don't add up to mfence
. See Does it make any sense instruction LFENCE in processors x86/x86_64? 和关于这些指令的各种其他 SO 问答。
这就是为什么 std::atomic_thread_fence(std::memory_order_acq_rel)
also compiles to zero instructions on x86,但对弱序架构的障碍。
lfence
也是 Intel 微架构上的序列化指令(但可能不是 AMD?)。一直以来都是如此,但英特尔最近正式做出了这一保证,因此 Spectre 缓解技术可以安全地使用它,而不是更不方便的 cpuid
.
- 脚注 1:
atomic_signal_fence
也可能是普通非 atomic
变量的编译器障碍;这是我最后一次检查 gcc(而 atomic_thread_fence
不是),但这可能只是一个实现细节,因为没有涉及任何 atomic
变量。当有 atomic
个变量时,编译器知道这些变量可能会提供排序,让其他线程在没有 UB 的情况下访问非原子变量,因此需要排序。