一个代码库有一个 COMPILER_BARRIER
宏定义为 __asm__ volatile("" ::: "memory")
.宏的目的是防止编译器跨屏障重新排序读写。请注意,这显然是编译器屏障,不是处理器级内存屏障。
事实上,这是相当可移植的,因为在 AssemblerTemplate 中没有实际的汇编指令,只有 volatile
和 memory
破坏。因此,只要编译器支持 GCC 的 Extended Asm 语法,它就应该可以正常工作。不过,我很好奇如果可能的话,在 C++11 原子 API 中表达这一点的正确方法是什么。
以下似乎是正确的想法:atomic_signal_fence(memory_order_acq_rel);
.
我的推理是:
- 属于
<atomic>
API,仅atomic_signal_fence
和atomic_thread_fence
不需要用于操作的内存地址。 -
atomic_thread_fence
影响内存排序,我们不需要编译器屏障。 memory
Extended Asm 版本中的 clobber 不区分读和写,所以看起来我们需要获取和释放语义,所以memory_order_acq_rel
似乎至少是必需的。-
memory_order_seq_cst
似乎没有必要,因为我们不需要跨线程的总顺序 - 我们只对当前线程内的指令排序感兴趣。
是否可以表达等同于__asm__ volatile("" ::: "memory")
与 C++11 原子 API 完全兼容?如果是这样,是 atomic_signal_fence
使用正确的 API?如果是这样,什么内存顺序参数在这里是合适的/需要的?
或者,我是不是陷入困境,有更好的方法来解决这个问题?
最佳答案
__asm__ volatile(""::::"memory")
甚至不是一个完整的编译器障碍;它只强制将加载/存储排序到其地址可能被 asm block 访问的对象,这将不包括编译器可以跟踪地址不泄漏的局部变量。例如,memset(password, 0, len);
后跟 __asm__ volatile(""::::"memory");
可能无法将所使用的内存实际归零密码[]
。
这可以通过将此类对象的地址作为输入传递给 asm block 来解决,但我没有看到与 atomic_signal_fence
有任何完美的等价物。您可能做的最接近的事情是将对象的地址存储到外部链接 volatile
指针对象中(小心制作指针,而不是指向类型,volatile
-qualified),然后 atomic_signal_fence
将不得不假设它可以从信号处理程序访问。
关于c++ - 什么是 C++11 原子 API 等同于 `` `__asm__ volatile ("":::: "memory")`` `,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38580321/