x86_64和ARM上的原子CAS操作总是使用std :: memory_order_seq_cst吗?

Ale*_*lex 4 c++ x86 arm compare-and-swap c++11

正如安东尼·威廉斯说:

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  
Run Code Online (Sandbox Code Playgroud)

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)
Run Code Online (Sandbox Code Playgroud)

在x86/x86_64平台上进行任何原子CAS操作,像这样的例子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上它是一样的吗?

问:应该的顺序std::memory_order_relaxedCAS块存储器总线上的x86或ARM?

答案:x86上compare_exchange_weak(),任何std::memory_orders(偶数std::memory_order_relaxed)的操作总是转换为LOCK CMPXCHG 带有锁的总线,实际上是原子的,并且具有相同的成本XCHG- " cmpxchg就像xchg指令一样昂贵".

(加法:XCHG等于LOCK XCHG,但CMPXCHG不等于LOCK CMPXCHG(实际上是原子)

ARM和PowerPC上,对于不同的std :: memory_orders ,任何`compare_exchange_weak()都有不同的锁处理器指令,通过LL/SC.

x86(CAS除外),ARM和PowerPC的处理器内存屏障说明:http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html

bri*_*and 5

您不应该担心编译器将给定的C11构造映射到哪些指令,因为它不会捕获所有内容.相反,您需要开发有关C11内存模型保证的代码.如上面的注释所述,只要不违反C11内存模型,您的编译器或未来的编译器就可以自由地重新排序宽松的内存操作.通过像CDSChecker这样的工具运行代码也是值得的,以查看内存模型下允许的行为.

  • 在这种情况下,您可以查看以下内容:http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html. (2认同)