【问题标题】:Is this memory barrier implemented correctly?这个内存屏障是否正确实施?
【发布时间】:2013-01-18 17:02:53
【问题描述】:

我正在阅读旧版 C++ 代码,其中内存屏障定义如下。主要操作系统是 linux 和 vxworks。编译器是 gcc(WindRiver's gcc)。

#if((KCompilerGNU)||(kCompilerWindRiver))
   #define MEMORY_BARRIER   __asm__ volatile("nop\n");
#else
   #define MEMORY_BARRIER   __asm nop;
#endif

但我没有看到无操作操作如何产生内存屏障?或者它只是一个错误的实现?

【问题讨论】:

  • 您可能对内存屏障有错误的解释。你可能认为它的意思是 fence。写它的人可能意味着它是一种填充物。即用于填充代码以对齐特定边界。
  • 遗留代码在很多地方使用它作为内存栅栏的目的,你可以清楚地分辨出来。顺便说一句,nop 如何作为对齐目的?
  • 它是一种填充物。如果您知道您的代码是 15 个字节并且需要在更多内容之前将其填充到 16 个字节(在 x86 上),有时人们会插入一个 nop。这里:stackoverflow.com/questions/234906/…

标签: c++ memory-barriers


【解决方案1】:

这是一个编译器屏障,而不是一个完整的硬件内存屏障。也就是说,它旨在成为编译器无法优化的不透明调用,但在内存重新排序方面对硬件没有任何影响1。如果所讨论的编译器确实将 asm 块视为不透明的(例如,gcc asm 块有特定的规则来准确定义可以跨块更改的内容等),则它可能为此目的而正确定义。

如果您知道此代码所针对的硬件具有从不重新排序内存操作的强大内存模型,则将其称为完整内存屏障(通常会抑制编译器和硬件重新排序)可能是合适的。


1 也就是说,如果程序是单线程的或机器没有表现出有趣的重新排序(例如,一个简单的有序的、非推测的 CPU 或单 CPU 系统)。

【讨论】:

  • 但是我们不应该使用asm volatile("" ::: "memory");作为编译器屏障吗?
  • 当然,在 gcc 或支持 gcc asm 语法的编译器上,但我不知道 #else 案例实际针对的是哪些编译器。据我所知,#else 案例不是针对 gcc,而是一些其他编译器根本不查看 asm 块内部,并且始终将其插入源代码中的位置。如果我按照自己的方式,#ifs 将明确涵盖所有编译器,最后的 #ifelse 会失败并显示“不支持的编译器”警告。我不确定 Wind River 的 gcc asm 语法与 gcc 有何不同。您应该检查 volatile 是否足够,或者是否需要破坏列表。
  • 我会调查的。谢谢!
  • FWIW,在我看来,最近的 gcc 文档暗示仅 volatile 是不够的 - 正如您所建议的,您需要 volatile 和 [memory] ​​在 clobber 列表中。如果这段代码是旧的,它可能在过去工作过,但可能不再工作,等等。当然,如果你的硬件进行任何重新排序,编译器的障碍无论如何都是高度怀疑的。
  • 所以这需要“内存”来阻止 CPU 重新排序诸如读/写之类的事情?没有标准的 C++ 命令吗?
猜你喜欢
  • 2014-04-15
  • 1970-01-01
  • 2015-10-04
  • 1970-01-01
  • 2014-01-20
  • 2010-12-30
  • 2010-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多