这是在x86/x86_64中实现顺序一致性的四种方法:

  • LOAD(无围栏)和STORE + MFENCE
  • LOAD(无围栏)和LOCK XCHG
  • MFENCE + LOAD和存储(无围栏)
  • LOCK XADD(0)和STORE(无围栏)

  • 就像这里写的:http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html



    注意:还有C/C++ 11到x86的替代映射,它不是锁定(或隔离)Seq Cst存储区,而是锁定/设置Seq Cst负载:



    GCC 4.8.2(x86_64中的GDB)C++11-std::memory_order_seq_cst使用first(1)方法,即LOAD(无围栏)和STORE + MFENCE:
    std::atomic<int> a;
    int temp = 0;
    a.store(temp, std::memory_order_seq_cst);
    0x4613e8  <+0x0058>         mov    0x38(%rsp),%eax
    0x4613ec  <+0x005c>         mov    %eax,0x20(%rsp)
    0x4613f0  <+0x0060>         mfence
    

    众所周知,MFENCE = LFENCE + SFENCE。然后,我们可以将此代码重写为:LOAD(without fence) and STORE+LFENCE+SFENCE
    问题:
  • 为什么我们在加载之前不需要在这里使用LFENCE,而在存储之后需要使用LFENCE(因为LFENCE仅在加载之前才有意义!)?
  • 为什么GCC不对std::memory_order_seq_cst使用以下方法:LOAD(无围栏)和STORE + SFENCE?
  • 最佳答案

    x86唯一的重新排序(用于正常的内存访问)是,它可能会重新排序存储后的负载。

    SFENCE保证栅栏之前的所有商店在栅栏之后的所有商店之前完成。 LFENCE保证栅栏之前的所有负载在栅栏之后的所有负载之前完成。对于普通的内存访问,默认情况下已经提供了单个SFENCE或LFENCE操作的顺序保证。基本上,LFENCE和SFENCE本身仅对x86的较弱内存访问模式有用。

    LFENCE,SFENCE或LFENCE + SFENCE都不能防止对存储紧随其后的存储进行重新排序。 MFENCE确实如此。

    相关引用是《 Intel x86体系结构手册》。

    10-01 16:05