MS 特定的 volatile 是否会阻止硬件指令重新排序
Does MS-specific volatile prevent hardware instructions reordering
Microsoft Specific
When the /volatile:ms compiler option is used—by default when
architectures other than ARM are targeted—the compiler generates extra
code to maintain ordering among references to volatile objects in
addition to maintaining ordering to references to other global
objects.In particular:
- A write to a volatile object (also known as volatile write) has Release semantics; that is, a reference to a global or static object
that occurs before a write to a volatile object in the instruction
sequence will occur before that volatile write in the compiled
binary.
- A read of a volatile object (also known as volatile read) has Acquire semantics; that is, a reference to a global or static object
that occurs after a read of volatile memory in the instruction
sequence will occur after that volatile read in the compiled binary.
This enables volatile objects to be used for memory locks and releases
in multithreaded applications.
它肯定保证 volatile
阻止编译器进行编译时指令重新排序(因为它明确声明指令
序列将与编译后的二进制文件中的 ).
相同
但众所周知,还有硬件重新排序之类的东西(例如 CPU 能够按照自己的意愿重新排序指令)。 volatile
也能阻止它吗?我知道同步原语(例如互斥锁)可以,但是 MS 特定的 volatile
?
有关 MS 特定易失性行为的 MSDN 文档一直追溯到 VS2003。所以它已经存在了一段时间——远早于 C++11 中 std::atomic
的存在。
所以 MS 特定的 volatile 似乎是过去实现 acquire/release 语义的方式。但现在它基本上已经过时了,他们留下了一个脚注,让你远离 MS-volatile,转而使用 std::atomic
和 /volatile:iso
进行线程间通信。
至于他们为什么将 ARM 排除在外,Microsoft 直到最近才选择 ARM。除了 ARM,它们还支持 x86、x64 和 Itanium(已死)。
在 x86 和 x64 上,大多数加载和存储已经具有 acquire/release 语义(非临时存储等例外)。因此,只要编译器不重新排序任何东西,处理器就不会 *,因此会保留 acquire/release 语义。 /volatile:ms
标志告诉编译器不要重新排序任何东西,以便可以在 x86 和 x64 上实现 acquire/release 语义。
由于 Microsoft 的 ARM 支持相对较新,并且 MS 特定的 volatile (/volatile:ms
) 已过时以支持 std::atomic
,他们可能决定放弃经典的 volatile 语义而不是将它们更新为也可以在 ARM 上工作(这可能意味着在缺乏硬件支持的情况下到处添加内存屏障)。
*处理器仍将执行它想要的任何重新排序,但它将保留程序的 acquire/release 语义,因为这是 x86/x64 所要求的。 (减去 nt-stores 或 clflush 等例外情况)它如何在不违反内存顺序的情况下做到这一点是另一个话题。
Microsoft Specific
When the /volatile:ms compiler option is used—by default when architectures other than ARM are targeted—the compiler generates extra code to maintain ordering among references to volatile objects in addition to maintaining ordering to references to other global objects.In particular:
- A write to a volatile object (also known as volatile write) has Release semantics; that is, a reference to a global or static object
that occurs before a write to a volatile object in the instruction
sequence will occur before that volatile write in the compiled
binary.- A read of a volatile object (also known as volatile read) has Acquire semantics; that is, a reference to a global or static object
that occurs after a read of volatile memory in the instruction
sequence will occur after that volatile read in the compiled binary.This enables volatile objects to be used for memory locks and releases in multithreaded applications.
它肯定保证 volatile
阻止编译器进行编译时指令重新排序(因为它明确声明指令
序列将与编译后的二进制文件中的 ).
但众所周知,还有硬件重新排序之类的东西(例如 CPU 能够按照自己的意愿重新排序指令)。 volatile
也能阻止它吗?我知道同步原语(例如互斥锁)可以,但是 MS 特定的 volatile
?
有关 MS 特定易失性行为的 MSDN 文档一直追溯到 VS2003。所以它已经存在了一段时间——远早于 C++11 中 std::atomic
的存在。
所以 MS 特定的 volatile 似乎是过去实现 acquire/release 语义的方式。但现在它基本上已经过时了,他们留下了一个脚注,让你远离 MS-volatile,转而使用 std::atomic
和 /volatile:iso
进行线程间通信。
至于他们为什么将 ARM 排除在外,Microsoft 直到最近才选择 ARM。除了 ARM,它们还支持 x86、x64 和 Itanium(已死)。
在 x86 和 x64 上,大多数加载和存储已经具有 acquire/release 语义(非临时存储等例外)。因此,只要编译器不重新排序任何东西,处理器就不会 *,因此会保留 acquire/release 语义。 /volatile:ms
标志告诉编译器不要重新排序任何东西,以便可以在 x86 和 x64 上实现 acquire/release 语义。
由于 Microsoft 的 ARM 支持相对较新,并且 MS 特定的 volatile (/volatile:ms
) 已过时以支持 std::atomic
,他们可能决定放弃经典的 volatile 语义而不是将它们更新为也可以在 ARM 上工作(这可能意味着在缺乏硬件支持的情况下到处添加内存屏障)。
*处理器仍将执行它想要的任何重新排序,但它将保留程序的 acquire/release 语义,因为这是 x86/x64 所要求的。 (减去 nt-stores 或 clflush 等例外情况)它如何在不违反内存顺序的情况下做到这一点是另一个话题。