【问题标题】:Why do read and write barrier for x86 in glibc not use __volatile asm?为什么 glibc 中 x86 的读写屏障不使用 __volatile asm?
【发布时间】:2020-09-29 09:02:14
【问题描述】:

我正在学习glibc(版本是2.32)。至于内存屏障,x86的读、写和全屏障如下:

#define atomic_full_barrier() \
    __asm __volatile (LOCK_PREFIX "orl $0, (%%" SP_REG ")" ::: "memory")
#define atomic_read_barrier() __asm ("" ::: "memory")
#define atomic_write_barrier() __asm ("" ::: "memory")

cppreferencethis answer 说,volatile 告诉编译器不要优化和重新排序这条指令。

为什么读写屏障不使用__asm __volatile,而完全屏障使用它?

【问题讨论】:

    标签: c gcc glibc inline-assembly memory-barriers


    【解决方案1】:

    没有输出操作数的asm 语句隐含为volatile (GCC manual)。
    所以它们实际上都是volatile,这是它们不被优化器删除的必要条件。

    (非volatile asm 被假定为一个没有副作用的纯函数,仅在需要产生输出时运行。只有当优化器决定需要运行 asm 语句时,才会破坏 clobbers) .

    不同的作者选择或多或少明确。如果你git blame,我希望你会看到这些是在不同的时间和/或不同的人写的。

    【讨论】:

    • 非常感谢您的快速回答。为什么没有输出操作数的asm 语句隐含volatile?如果这条语句没有副作用和输出操作数,编译器可以丢弃它吗?
    • 我对@9​​87654331@ 的效果有点困惑。 GCC manual 表示,如果 GCC 的优化器确定不需要输出变量,它们有时会丢弃 asm 语句。是不是意味着volatile 只阻止优化器丢弃输出不需要的语句,但不阻止它们丢弃没有副作用的语句?
    • @ZiheLiu:如果它没有输出并且不是volatile,编译器将总是能够丢弃它。就像调用纯函数而不将返回值分配给任何东西一样。在设计语法时,强制人们为这种情况写volatile 可能会更好,但这使其与 GNU C“基本”asm 语句一致(无约束)。但是,您几乎不应该将基本 asm 用于任何事情 (gcc.gnu.org/wiki/ConvertBasicAsmToExtended)
    • 如果是volatile但没有副作用,编译器可以丢弃它吗?换句话说,如果它没有输出并且不是volatile,但有副作用(例如更改输入内存或寄存器),编译器可以丢弃它吗?
    • @ZiheLiu:编译器只知道你通过 volatile 告诉他们什么,以及约束。缺少volatile 意味着它除了编写输出操作数之外没有任何必要的副作用。使用volatile 有效地告诉编译器有副作用。 (实际上,它告诉编译器该语句必须运行与 C 抽象机器运行它的次数一样多,而不是重新排序 wrt。任何其他 volatile 访问,包括 volatile int 或任何加载和存储。)
    猜你喜欢
    • 2013-08-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多