dsp*_*pjm 7 linux memory smp linux-kernel memory-barriers
内核源代码Documentation/memory-barriers.txt中有一个例子,如下所示:
Run Code Online (Sandbox Code Playgroud)CPU 1 CPU 2 ======================= ======================= { B = 7; X = 9; Y = 8; C = &Y } STORE A = 1 STORE B = 2 <write barrier> STORE C = &B LOAD X STORE D = 4 LOAD C (gets &B) LOAD *C (reads B)在没有干预的情况下,CPU 2可以以一些有效的随机顺序感知CPU 1上的事件,尽管CPU 1发出了写屏障:
Run Code Online (Sandbox Code Playgroud)+-------+ : : : : | | +------+ +-------+ | Sequence of update | |------>| B=2 |----- --->| Y->8 | | of perception on | | : +------+ \ +-------+ | CPU 2 | CPU 1 | : | A=1 | \ --->| C->&Y | V | | +------+ | +-------+ | | wwwwwwwwwwwwwwww | : : | | +------+ | : : | | : | C=&B |--- | : : +-------+ | | : +------+ \ | +-------+ | | | |------>| D=4 | ----------->| C->&B |------>| | | | +------+ | +-------+ | | +-------+ : : | : : | | | : : | | | : : | CPU 2 | | +-------+ | | Apparently incorrect ---> | | B->7 |------>| | perception of B (!) | +-------+ | | | : : | | | +-------+ | | The load of X holds ---> \ | X->9 |------>| | up the maintenance \ +-------+ | | of coherence of B ----->| B->2 | +-------+ +-------+ : :
我不明白,因为我们有写屏障,所以,任何商店必须在执行C =&B时生效,这意味着B将等于2.对于CPU 2,当B得到值时,B应为2 C,这是&B,为什么它会将B视为7.我真的很困惑.
关键缺失点是对序列的错误假设:
LOAD C (gets &B)
LOAD *C (reads B)
Run Code Online (Sandbox Code Playgroud)
第一次加载必须在第二次加载之前.弱有序的架构可以"好像"发生以下情况:
LOAD B (reads B)
LOAD C (reads &B)
if( C!=&B )
LOAD *C
else
Congratulate self on having already loaded *C
Run Code Online (Sandbox Code Playgroud)
例如,推测性的"LOAD B"可能发生,因为B与早期感兴趣的其他变量或硬件预取的B在同一个高速缓存行上.
从标题为"关于记忆障碍可能不被假设的文件?"的部分开头:
通过完成内存屏障指令,无法保证在内存屏障之前指定的任何内存访问都将完成 ; 屏障可以被认为是在CPU的访问队列中画一条线,访问相应类型的可能不会交叉.
和
有没有保证,一个CPU会看到的效果,从第二个CPU的访问正确的顺序,甚至如果第二CPU采用的是记忆障碍,除非第一CPU 也采用了匹配内存屏障(见"SMP障碍配对"小节).
什么样的内存障碍(当然是以非常简单的方式)确保编译器和CPU内硬件都不会在屏障上重新排序加载(或存储)操作时进行任何巧妙的尝试,并且CPU正确地感知到对由系统的其他部分制作的内存.当负载(或存储)带有其他含义时,这是必要的,例如在访问锁定之前锁定锁定.在这种情况下,让编译器/ CPU通过重新排序来提高访问效率对于我们程序的正确操作是危险的.
阅读本文时,我们需要牢记两件事:
事实#2是一个CPU能够以不同方式感知数据的原因之一.虽然缓存系统旨在提供一般情况下的良好性能和一致性,但在特定情况下可能需要一些帮助,如文档中所示.
通常,如文档所示,涉及多个CPU的系统中的障碍应该配对,以迫使系统同步两个(或所有参与的)CPU的感知.想象一种情况,其中一个CPU完成加载或存储并更新主存储器,但新数据尚未传输到第二个CPU的缓存,导致两个CPU之间缺乏连贯性.
我希望这有帮助.我建议再次阅读memory-barriers.txt,特别是题为"CPU缓存的影响"一节.