什么是与`__ASM__Volatile(&Quot;";:&Quot;Memory&Quot;)`等价的C++11原子API
代码库具有定义为
__asm__ volatile("" ::: "memory")
的COMPILER_BARRIER
宏。宏的目的是防止编译器跨障碍对读写进行重新排序。请注意,这显然是编译器障碍,不是处理器级内存障碍。
实际上,这是相当可移植的,因为在汇编模板中没有实际的汇编指令,只有volatile
和memory
装配器。因此,只要编译器支持GCCS扩展ASM语法,它就应该工作得很好。不过,如果可能的话,我很好奇在C++11原子API中表达这一点的正确方式是什么。
以下内容似乎是正确的想法:atomic_signal_fence(memory_order_acq_rel);
。
我的理由是:
- 在
<atomic>
接口中,只有atomic_signal_fence
和atomic_thread_fence
不需要操作所针对的内存地址。 atomic_thread_fence
影响内存排序,这不是编译器障碍所需要的。- ASM扩展版本中的
memory
存取器不区分读取和写入,因此我们似乎同时需要获取和释放语义,因此似乎至少需要memory_order_acq_rel
。 memory_order_seq_cst
似乎没有必要,因为我们不需要线程之间的总顺序-我们只对当前线程中的指令顺序感兴趣。
__asm__ volatile("" ::: "memory")
的等价物?如果是,atomic_signal_fence
是正确的API吗?如果是,这里需要/合适的内存顺序参数是什么?
或者,我是不是陷入了困境,有更好的方法来解决这个问题?
解决方案
__asm__ volatile("" ::: "memory")
甚至不是一个完整的编译器障碍;它只强制对其地址可能可由ASM块访问的对象进行加载/存储排序,而不包括编译器可以跟踪其地址不会泄漏的局部变量。例如,memset(password, 0, len);
后跟__asm__ volatile("" ::: "memory");
可能无法实际清零password[]
使用的内存。
atomic_signal_fence
没有任何完美的等价物。最接近的做法可能是将对象的地址存储到外部链接volatile
指针对象中(注意使指针而不是指向类型的volatile
合格),然后atomic_signal_fence
必须假定它可能是从信号处理程序访问的。
相关文章