首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >函数调用是内存屏障吗?

函数调用是内存屏障吗?
EN

Stack Overflow用户
提问于 2011-04-17 11:36:46
回答 5查看 5.6K关注 0票数 22

考虑一下这个C代码:

代码语言:javascript
复制
extern volatile int hardware_reg;

void f(const void *src, size_t len)
{
    void *dst = <something>;

    hardware_reg = 1;    
    memcpy(dst, src, len);    
    hardware_reg = 0;
}

memcpy()调用必须发生在两个赋值之间。一般来说,由于编译器可能不知道被调用的函数将做什么,所以它不能在分配之前或之后重新排序对函数的调用。但是,在这种情况下,编译器知道函数将做什么(甚至可以插入内联内置替代程序),并且可以推断memcpy()永远无法访问hardware_reg。在这里,在我看来,如果编译器想要移动memcpy()调用,它就不会遇到麻烦。

因此,问题是:单独的函数调用是否足以发出防止重新排序的内存屏障,或者是在调用memcpy()之前和之后需要的显式内存屏障?

如果我误会了,请纠正我。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2011-04-17 23:36:39

编译器不能在memcpy()之前或hardware_reg = 0之后重新排序--这是volatile将确保的--至少在编译器发出的指令流中是这样的。函数调用不一定是“内存屏障”,但它是序列点。

C99标准提到了volatile (5.1.2.3/5“程序执行”):

在序列点的

中,易失性对象是稳定的,因为以前的访问已经完成,而后续的访问还没有发生。

因此,在memcpy()表示的序列点,必须发生写入1的易失性访问,而不能发生写入0的易失性访问。

然而,有两件事我想指出:

  1. 取决于<something>是什么,如果对目标缓冲区不做任何其他操作,编译器可能能够完全删除memcpy()操作。这就是微软提出SecureZeroMemory()函数的原因。away.
  2. volatile不一定意味着内存障碍(这是硬件问题,而不仅仅是代码排序问题),因此如果您在多进程计算机或某些类型的硬件上运行,可能需要显式调用内存屏障(可能是Linux上的wmb() )。

从MSVC 8 (VS 2005)开始,Microsoft记录了volatile关键字暗示了适当的内存屏障,因此可能不需要单独的特定内存屏障调用:。

代码语言:javascript
复制
- [http://msdn.microsoft.com/en-us/library/12a04hfd.aspx](http://msdn.microsoft.com/en-us/library/12a04hfd.aspx)

此外,在优化时,编译器必须保持对易失性对象的引用以及对其他全局对象的引用之间的顺序。特别地,

代码语言:javascript
复制
- A write to a volatile object (volatile write) has Release   semantics; 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 (volatile read) has Acquire semantics;   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.
票数 10
EN

Stack Overflow用户

发布于 2011-04-17 11:45:06

据我所知你的推理

编译器在移动memcpy调用时不会遇到麻烦

是对的。语言定义没有回答您的问题,只能参考特定的编译器来解决。

很抱歉没有更多有用的信息。

票数 4
EN

Stack Overflow用户

发布于 2011-04-17 11:51:14

我的假设是,编译器永远不会重新排序易失性赋值,因为它必须假设它们必须在代码中发生的位置执行

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5693274

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档