English 中文(简体)
功能是否是现代平台的有效记忆屏障?
原标题:Is function call an effective memory barrier for modern platforms?

在我审查的一个代码库里, 我发现了以下的智商。

void notify(struct actor_t act) {
    write(act.pipe, "M", 1);
}
// thread A sending data to thread B
void send(byte *data) {
    global.data = data;
    notify(threadB);
}
// in thread B event loop
read(this.sock, &cmd, 1);
switch (cmd) {
    case  M : use_data(global.data);break;
    ...
}

“等等”,我对我的团队的一名资深成员,即提交人说,“这里没有记忆屏障!你不能保证global.data将从缓存冲到主内存。如果线A和线B将在两个不同的处理器中运行,这个办法可能失败。”

资深程序员笑着, 并缓慢地解释, 好像解释他的五岁男孩如何系鞋带: “听着,小男孩,我们在这里看到许多与线条有关的虫子, 在高负荷测试中,

"但书上写着..."

“安静 ”, 他迅速给我闭嘴, “也许理论上说,它没有保证,但实际上,你使用的函数调用实际上是一个记忆屏障。 编译者不会重新排序指令 global. data= data , 因为它不能知道是否有人在调用该指令时使用, 而 x86 架构将确保其他CPU在B 读取管子指令时会看到这块全球数据。 放心吧, 我们有足够的真实的世界问题需要担心。 我们不需要在假理论问题上投入额外的精力。

"我向我儿子保证,你将理解 将真正的问题与我-需要- 需要- 需要-

这在实际中是否真的不是一个问题(X86、x64和ARM)?

这和我学到的一模一样 但他的胡子长着 长得很聪明

额外的点数,如果你能给我看一个代码 证明他错了!

最佳回答

内存屏障并不仅仅是为了防止指令重新排序。 即使指令没有重新排序, 它仍然会在缓存一致性方面造成问题。 至于重新排序 - 它取决于您的编译者和设置。 ICC 在重新排序方面特别呈递性。 MSVC w/ 整个程序优化也可以是 。

如果您的共享数据变量被宣布为 volatile , 大部分汇编者即使不在 spec 中, 也会生成一个内存变量, 围绕变量读写, 防止重新排序 。 < enger> 这不是使用 volatile 的正确方法, 也不是它的意义所在 。

(如果我还有选票的话,我会加1,请回答你的问题。 )

问题回答

在实践中,函数调用是一个 < 强度 > compiler 屏障, 意思是汇编者不会将全球内存存存取移动到调用中。 提醒此功能是编译者知道的功能, 例如内嵌函数( 牢记 IPO! ) 等 。

因此在理论上,一个处理器内存屏障(除了一个编译器屏障之外)在理论上是有必要的。然而,既然你重新拨打电话读写来改变全球状态,我敢肯定,内核在某处会设置内存屏障。 虽然没有这样的保证,但理论上你需要这些屏障。

基本规则是 : 汇编者必须使全球状态 < em> 出现 < / em > 与您编码时完全相同, 但如果它能证明给定的函数不使用全局变量, 那么它可以任意执行算法 。

结果显示,传统汇编者总是将功能从另一个编译单位 < / em> 视为记忆屏障, 因为他们看不到这些功能的内涵。 越来越多的现代汇编者正在发展“ 完整程序 ” 或“ 链接时间 ” 优化策略, 打破这些障碍, 且“ 坚固” / “ 坚固” 将导致写得不好的代码失败, 尽管它已经工作多年了。

如果该函数在一个共享的库中,那么它将无法在库中看到,如果该函数是由 C 标准定义的,那么它就不需要 -- -- 它已经知道该函数会做什么 -- -- 所以你也必须小心那些函数。请注意,一个编译者将not 识别一个内核呼叫,但插入某个编译者无法识别的东西(内线组装器或组装器文件的函数调用)本身将产生一个内存屏障。

在您的情况下, notify 将会是一个黑盒, 编译者无法在内部看到( 库函数), 否则它会包含一个可识别的内存屏障, 所以您很可能是安全的 。

在实践中,您必须写下错误的代码, 才能在此上面掉下来 。

实际上,他是正确的,在这个具体案件中隐含着记忆障碍。

但关键在于,如果它的出现是“值得商榷的”, 代码已经太复杂和模糊了。

真正的家伙们,用哑音或其他合适的结构。 这是处理线条和写可维持的代码的唯一安全方法。

也许你会看到其他错误, 比如如果发送() 被调用不止一次, 代码是无法预测的。





相关问题
Fastest method for running a binary search on a file in C?

For example, let s say I want to find a particular word or number in a file. The contents are in sorted order (obviously). Since I want to run a binary search on the file, it seems like a real waste ...

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

Tips for debugging a made-for-linux application on windows?

I m trying to find the source of a bug I have found in an open-source application. I have managed to get a build up and running on my Windows machine, but I m having trouble finding the spot in the ...

Trying to split by two delimiters and it doesn t work - C

I wrote below code to readin line by line from stdin ex. city=Boston;city=New York;city=Chicago and then split each line by ; delimiter and print each record. Then in yet another loop I try to ...

Good, free, easy-to-use C graphics libraries? [closed]

I was wondering if there were any good free graphics libraries for C that are easy to use? It s for plotting 2d and 3d graphs and then saving to a file. It s on a Linux system and there s no gnuplot ...

Encoding, decoding an integer to a char array

Please note that this is not homework and i did search before starting this new thread. I got Store an int in a char array? I was looking for an answer but didn t get any satisfactory answer in the ...

热门标签