MS特定的易失性是否会阻止硬件指令重新排序

时间:2016-08-11 18:31:45

标签: c++ multithreading visual-c++ volatile memory-fences

来自documentation

  

Microsoft特定

     

当使用/ volatile:ms编译器选项时 - 默认情况下   ARM以外的体系结构是目标 - 编译器生成额外的   用于维护对volatile中的volatile对象的引用的排序的代码   除了维持对其他全局的引用的排序   对象。特别是:

     
      
  • 对volatile对象的写入(也称为volatile write)具有Release语义;也就是说,对全局或静态对象的引用
      在写入指令中的易失性对象之前发生的   序列将在编译后的volatile写入之前发生   二进制。
  •   
  • 读取volatile对象(也称为volatile read)具有Acquire语义;也就是说,对全局或静态对象的引用
      在指令中读取易失性存储器后发生的情况   序列将在编译二进制文件中的volatile读取之后发生。
  •   
     

这使得volatile对象可用于内存锁定和释放   在多线程应用程序中。

它确实保证volatile阻止编译器执行编译时指令重新排序(因为它明确指出该指令 序列将与编译二进制文件中的相同。)

但是众所周知,还有像硬件重新排序这样的东西(比如CPU可以自己重新排序指令)。 volatile也会阻止它吗?我知道同步原语(例如互斥体)可以,但MS特定的volatile呢?

1 个答案:

答案 0 :(得分:7)

关于MS特定的易失性行为的MSDN文档会一直回到VS2003。所以它在C ++ 11中存在std::atomic之前已经存在了很长一段时间。

因此,MS特定的volatile似乎是过去获得/释放语义的方式。但现在它基本上已经过时了,他们留下了一个脚注,让你远离MS-volatile而支持std::atomic/volatile:iso进行线程间通信。

至于他们为何排除ARM,微软直到最近才开始接收ARM。除了ARM之外,它们还支持x86,x64和Itanium(已经死了)。

在x86和x64上,大多数加载和存储已经具有获取/释放语义(例如非临时存储等)。因此,只要编译器不对任何内容重新排序,处理器就不会 * ,因此将保留获取/释放语义。 /volatile:ms标志告诉编译器不要重新排序任何内容,以便可以在x86和x64上实现获取/释放语义。

由于Microsoft的ARM支持相对较新,并且MS特定的volatile(/volatile:ms)已过时而支持std::atomic,因此他们可能决定放弃经典的volatile语义而不是更新它们来处理ARM也是如此(由于缺乏硬件支持,这可能意味着在任何地方增加内存屏障)。

*处理器仍将执行它想要的任何重新排序,但它将保留程序的获取/释放语义,因为x86 / x64需要它。 (减去像nt-stores或clflush这样的特殊情况)如何在不违反内存排序的情况下执行此操作是另一个主题。