什么是C++ 11原子API相当于```__asm__ volatile("":::"memory")```

acm*_*acm 8 c++ portability atomicity barrier c++11

代码库有一个COMPILER_BARRIER定义为的宏__asm__ volatile("" ::: "memory").宏的目的是防止编译器跨屏障重新排序读取和写入.请注意,这显然是编译器障碍,而不是处理器级别的内存障碍.

因此,这是相当便携的,因为AssemblerTemplate中没有实际的汇编指令,只有volatilememoryclobber.因此,只要编译器遵循GCC扩展Asm语法,它就可以正常工作.尽管如此,我很好奇如果可能的话,在C++ 11 atomics API中表达它的正确方法是什么.

以下似乎可能是正确的想法:atomic_signal_fence(memory_order_acq_rel);.

我的理由是:

  • <atomic>API中,仅需要atomic_signal_fence并且atomic_thread_fence不需要用于操作的存储器地址.
  • atomic_thread_fence 影响内存排序,我们不需要编译器障碍.
  • memoryExtended Asm版本中的clobber不区分读取和写入,因此看起来我们需要获取和释放语义,因此memory_order_acq_rel似乎至少需要.
  • memory_order_seq_cst 似乎没必要,因为我们不需要跨线程的总顺序 - 我们只对当前线程中的指令排序感兴趣.

是否有可能__asm__ volatile("" ::: "memory")用C++ 11 atomics API 表达完全可移植的等价物?如果是这样,是否atomic_signal_fence使用正确的API?如果是这样,这里适当/需要什么内存顺序参数?

或者,我在这里的杂草中,有一个更好的方法来解决这个问题吗?

R..*_*R.. 3

__asm__ volatile("" ::: "memory")甚至不是一个完整的编译器障碍;它仅强制对地址可被 asm 块访问的对象进行加载/存储排序,其中不包括编译器可以跟踪地址不会泄漏的局部变量。例如,memset(password, 0, len);后跟__asm__ volatile("" ::: "memory");可能无法实际将 所使用的内存清零password[]

这可以通过将此类对象的地址作为输入传递给 asm 块来解决,但我没有看到任何与atomic_signal_fence. 您可能做的最接近的操作是将对象的地址存储到外部链接volatile指针对象中(注意使指针,而不是指向类型,volatile限定),然后atomic_signal_fence必须假设可以从信号处理程序。