As 安东尼·威廉姆斯说
some_atomic.load(std::memory_order_acquire)只是简单的加载指令,而some_atomic.store(std::memory_order_release)则是简单的存储指令。
众所周知,在x86的操作中,load()和store()内存屏障memory_order_consume, memory_order_acquire, memory_order_release, memory_order_acq_rel不需要处理器指令。
但是在ARMv8上,我们知道对于load()和store():http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-1-of-2 http://channel9.msdn.com/Shows/Going+Deep/Cpp-and-Beyond-2012-Herb-Sutter-atomic-Weapons-2-of-2都有内存屏障
关于CPU的不同体系结构:http://g.oswego.edu/dl/jmm/cookbook.html
其次,对于x86上的CAS操作,在反汇编代码(MSVS2012 x86_64)中,具有不同内存屏障的这两行是相同的:
a.compare_exchange_weak(temp, 4, std::memory_order_seq_cst, std::memory_order_seq_cst);
000000013FE71A2D mov ebx,dword ptr [temp]
000000013FE71A31 mov eax,ebx
000000013FE71A33 mov ecx,4
000000013FE71A38 lock cmpxchg dword ptr [temp],ecx
a.compare_exchange_weak(temp, 5, std::memory_order_relaxed, std::memory_order_relaxed);
000000013FE71A4D mov ecx,5
000000013FE71A52 mov eax,ebx
000000013FE71A54 lock cmpxchg dword ptr [temp],ecx GCC 4.8.1 x86_64 - GDB编写的反汇编代码
a.compare_exchange_weak(temp, 4, std::memory_order_seq_cst, std::memory_order_seq_cst);
a.compare_exchange_weak(temp, 5, std::memory_order_relaxed, std::memory_order_relaxed);
0x4613b7 <+0x0027> mov 0x2c(%rsp),%eax
0x4613bb <+0x002b> mov $0x4,%edx
0x4613c0 <+0x0030> lock cmpxchg %edx,0x20(%rsp)
0x4613c6 <+0x0036> mov %eax,0x2c(%rsp)
0x4613ca <+0x003a> lock cmpxchg %edx,0x20(%rsp)是任何原子CAS操作的x86/x86_64平台上,像这个atomic_val.compare_exchange_weak(temp, 1, std::memory_order_relaxed, std::memory_order_relaxed);这样的示例总是满足于排序std::memory_order_seq_cst
如果x86上的任何CAS操作总是以顺序一致性(std::memory_order_seq_cst)运行,而不考虑障碍,那么在ARMv8上也是一样的吗?
问题:,CAS的std::memory_order_relaxed顺序应该在x86或ARM上阻塞内存总线吗?
compare_exchange_weak()回答:使用任何std::memory_orders(偶数std::memory_order_relaxed) 的 On x86操作总是转换为std::memory_orders 有了锁总线,才是真正的原子,并且与XCHG - 指令“具有相等的开销。
(添加:XCHG等于LOCK XCHG,但CMPXCHG不等于LOCK CMPXCHG(实际上是原子的)
在ARM和PowerPC for any`compare_exchange_weak()中,是不同的锁处理器指令(通过LL/SC )。
处理器存储器.屏障.x86(非化学文摘社)、ARM和PowerPC的说明:http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
发布于 2013-09-03 05:46:53
您不应该担心编译器将给定的C11构造映射到哪些指令,因为这并不能捕获所有内容。相反,您需要开发有关C11内存模型的保证的代码。如上所述,您的编译器或未来的编译器可以自由地重新排序轻松的内存操作,只要它不违反C11内存模型。通过像CDSChecker这样的工具运行代码也是值得的,以查看在内存模型下允许哪些行为。
发布于 2013-09-03 05:05:04
x86保证加载后的负载是有序的,存储是按顺序排列的。考虑到CAS需要加载和存储,所有操作都必须围绕它进行排序。
但是,值得注意的是,在存在带有memory_order_relaxed的多个atomics的情况下,编译器可以重新排序它们。它不能用memory_order_seq_cst做到这一点。
发布于 2015-09-04 08:00:25
我认为编译器会发出lock cmpxchg,即使对于memory_order_relaxed也是如此,因为这是确保compare+exchange本身实际上是原子的唯一方法。正如artless_noise在评论中所说的,其他体系结构可以使用加载链接/存储条件来实现compare_exchange_weak(...)。
memory_order_relaxed仍然应该让编译器从循环中提升其他变量的存储,否则在编译时重新排序内存访问。
如果有一种方法可以在x86上实现,而这也不是一个完整的内存屏障,那么一个好的编译器就会将它用于memory_order_relaxed。
https://stackoverflow.com/questions/18577584
复制相似问题