Linux 如何理解limus测试“5 in”;一种形式化的内核内存排序模型";?
在文章“”中,介绍了以下违反直觉的记忆模型石蕊测试:Linux 如何理解limus测试“5 in”;一种形式化的内核内存排序模型";?,linux,riscv,memory-barriers,memory-model,Linux,Riscv,Memory Barriers,Memory Model,在文章“”中,介绍了以下违反直觉的记忆模型石蕊测试: P0(int *a, int *b) { WRITE_ONCE(*a, 1); //1 smp_wmb(); WRITE_ONCE(*b, 1); //2 } P1(int *a, int *b) { int r1; WRITE_ONCE(*b, 2); //3 smp_mb(); r1 = READ_ONCE(*a); //4 } exists (b=2 /\ 1:r1=0) 观察结
P0(int *a, int *b)
{
WRITE_ONCE(*a, 1); //1
smp_wmb();
WRITE_ONCE(*b, 1); //2
}
P1(int *a, int *b)
{
int r1;
WRITE_ONCE(*b, 2); //3
smp_mb();
r1 = READ_ONCE(*a); //4
}
exists
(b=2 /\ 1:r1=0)
观察结果b==2
表明3)在2)之后完成。由于2)在1)之后排序,因此观察值r1==0
永远不可能。给出的解释是,b==2
的观察值并不意味着3)在2)之后排序。相反,一个hart之前发出的内存写入可能会覆盖另一个hart之后发出的内存写入。的第71-72页显示了一种可能发生这种情况的机制
在当前的硬件中真的会发生这种情况吗?例如,RISC-V的its(第88页)中有以下“负载值公理”:
每个加载i的每个字节返回存储写入该字节的值,该值是以下存储中全局内存顺序的最新值:
这是否禁止观察到较早的书写可以覆盖较晚的书写?经过大量阅读,以下是我目前对该问题的理解 与RISC-V的RVWMO模型不同,Linux内核的强模型包含“写传播”的概念。强模型定义说明:(强调矿山) 当CPU提交指定目标地址的读取请求时 内存子系统在目标地址的 一致性顺序)已传播到CPU并返回值的 由该文件存储 这与RVWMO的负载值公理形成对比,RVWMO的内存只返回全局内存顺序中的最新写入。换句话说,RVWMO假设每个内存写入都会立即同时传播到所有CPU 相应地,
smp\u wmb()
和smp\u mb()
之间存在显著差异。smp\u wmb()
是一个弱屏障,而smp\u mb()
是一个强屏障。弱势垒只是告诉内存,在势垒之后写入的内容应该始终在所有在势垒之前写入的内容之后传播。一个强大的屏障实际上会一直等到以前的写操作传播到所有CPU和“一致点”
下面是我对石蕊测试过程中发生的事情的看法:
b
的最终值是2
a
。由于P0的写入尚未达到P1,因此它将获得初始值0
b==1
,因为只写一次(*b,2)代码>以一致性顺序出现在后面
现在为什么用
smp\u mb()
替换smp\u wmb()
会消除观察到的结果?因为在这种情况下,P0实际上会等到其第一次写入已传播到P1,然后再发送第二次写入。现在r1==0
意味着P0中的屏障仍未完成,但P1中的屏障确保P1中的写入已到达所有cpu和一致点。因此,P0中的第二次写入必须晚于P1中的写入到达一致点。因此,我们不能有b==2
一个内存模型,其中一些内核可以在存储变得全局可见之前看到它,这是一个弱有序的模型,而不是强有序的模型。例如,电源具有此属性。(也就是说,它不是多拷贝原子的)。有关C++11std::atomic
问题,请参阅,其中提供了有关IRIW重新排序在某些电源硬件上如何实际发生的答案。(与您的litmus测试不同,但写传播很重要,并且acq/rel比seq_cst弱)这里的“强模型”是Linux内核特有的术语。它与消除某些约束的“弱模型”形成对比。请看:“hart”是“core”的错误翻译,就像在CPU core中一样?“hart”是“hardware thread”的缩写,好的,显然这个词是为RISC-V补足的。我从未在任何其他计算机体系结构讨论中使用过它。我想用一个简短的词来表示“逻辑核心”是很有用的。