_ReadWriteBarrier 如何向上传播调用树?

Posted

技术标签:

【中文标题】_ReadWriteBarrier 如何向上传播调用树?【英文标题】:How does _ReadWriteBarrier propagate up the call tree? 【发布时间】:2010-01-28 17:19:12 【问题描述】:

我正在查看 documentation 中的这段文字,用于 Visual C++ 的 _ReadWriteBarrier 内在函数:

在过去的 Visual C++ 版本中 编译器,_ReadWriteBarrier 和 _WriteBarrier 函数仅在本地强制执行,不影响 函数调用树。在视觉 C++ 2005 及更高版本,这些函数 一直强制执行 树。

我了解障碍在函数中的作用,但“调用树向上”似乎暗示函数foo() 调用函数bar() 可以知道bar() 是否包含障碍。在 VC2005 中实际改变了什么来实现这一点...调用约定/ABI,编译器完成的一些全局分析,还是什么?

【问题讨论】:

【参考方案1】:

MS 文档从来都不是很好,这个就是一个很好的例子。 _ReadWriteBarrier 有 2 个部分:

    告诉 CPU 做一个内存屏障(即 mfence), 告诉编译器不要围绕障碍进行优化。

我怀疑调用树部分指的是#2。即:

int x = 0;

void foo()

   x = 7;
   _ReadWriteBarrier();
   x = 8;

没有障碍,x=7 可以被编译器完全删除。有了屏障,它就留下来了。 现在,调用 foo 的函数怎么样?

void bar()

   x = 3;  // optimized away?
   foo();
   x = 4;

我认为过去 x=3 可能已被优化掉(编译器很难判断是否允许这样做),但现在它会正确保留 x=3 指令。

我认为。

【讨论】:

这也是我对 MS 文档的理解。但是编译器怎么可能实现这种行为呢?如果答案仅仅是所有非内联函数调用都是编译器重新排序栅栏,那么为什么对早期版本的 VC 的引用没有实现呢? 我真的不知道。它可以用链接器解释的属性标记每个函数。这可能就像他们在编译期间如何在 lib 中或至少在对象字典中进行名称修改或复杂数据库一样简单......但是,通常在过去,编译器总是假设他们无法看到的函数的最坏情况,因此不会围绕它进行优化。也许随着他们变得更聪明,他们需要公开更多信息。

以上是关于_ReadWriteBarrier 如何向上传播调用树?的主要内容,如果未能解决你的问题,请参考以下文章

内存屏障是如何工作的?

使用MySQL 8.0递归CTE查找层次结构表中的直接后代并传播给父级

Dart:让流中抛出的异常传播并在调用者中捕获它

请解释Spring事务传播传播行为

。如何在多个jtextpanes上传播我的文字?

spring事务的7种传播行为