我正在阅读Paul E. McKenney的“记忆障碍” http://www.rdrop.com/users/paulmck/scalability/paper/whymb.2010.07.23a.pdf 一切都被详细解释,当我看到一切都清楚时,我会遇到一句话,这会使一切都变得愚蠢,让我觉得我一无所知。让我举个例子
void foo(void)
{
a = 1; #1
b = 1; #2
}
void bar(void)
{
while (b == 0) continue; #3
assert(a == 1); #4
}
假设这两个函数在不同的处理器上运行。 现在可能发生的事情是第二个处理器在存储到b#2之后可以看到存储到#1,因为第一个处理器队列存储到“a”并继续存储b指令。好的,没关系,我们在#1和#2之间的行中添加了一个写入栅栏,但是这段代码仍然可能失败,因为第二个处理器可能会对invalidate消息进行排队,所以我们再添加一个内存栅栏(这次读取栅栏) #4和#4之间的界限。
void foo(void)
{
a = 1; #1
write_memory_barrier();
b = 1; #2
}
void bar(void)
{
while (b == 0) continue; #3
read_memory_barrier();
assert(a == 1); #4
}
这强制第二个处理器处理所有排队的消息(使a无效)并通过向#4上的第一个处理器发送读MESI消息再次读取它。好。接下来文章说
因此,许多CPU架构 提供较弱的记忆障碍 仅执行一个或多个的指令 这两个中的另一个。大致说来, “读取内存屏障”仅标记了 使队列无效并“写入内存” 屏障“仅标记存储缓冲区。 一个完整的记忆障碍 做到了。
很好,很清楚,但在那之后,我看到了这一点
这样做的效果就是阅读 内存屏障订单仅加载 执行它的CPU,以便所有 读取存储器之前的负载 障碍似乎已经完成 在读取之后的任何加载之前 记忆障碍。同样,写一个 内存屏障订单只有商店, 再次在执行它的CPU上,和 再次使所有商店前面的 写内存屏障会出现 在任何商店之前完成 遵循写入内存屏障。
所以
读取存储器屏障之前的所有负载都将 似乎在任何负载跟随之前已经完成 读取内存屏障
混合了以前解释过的所有内容。这是什么意思?功能“bar”中的哪个负载必须在加载“a”#4之前完成?我理解断言在这个函数中没有内存障碍就会失败,因为处理器可能会读取一个旧值,因为它仍然无法使对象“a”所在的高速缓存行无效。
细节上的解释会非常有帮助,我试着整天都在理解它。
首先十分感谢。