Memory barrier, is a type of barrier and a class of instruction which causes a CPU or compiler to enforce an ordering constraint on memory operations issued before and after the barrier instruction.
之所以需要Memory barrier就是因为CPU Out-of-order execution 和 compiler reordering optimizations。
Compiler memory barrier
These barriers prevent a compiler from reordering instructions, they do not prevent reordering by CPU.
The GNU inline assembler statement
asm volatile("" ::: "memory");
or even
__asm__ __volatile__ ("" ::: "memory");
forbids GCC compiler to reorder read and write commands around it.
Intel ECC compiler uses "full compiler fence"
__memory_barrier()
intrinsics.
Microsoft Visual C++ Compiler:[8]
_ReadWriteBarrier()
Hardware memory barrier
Many architectures with SMP support have special hardware instruction for flushing reads and writes.
x86, x86-64
lfence (asm), void_mm_lfence(void)
sfence (asm), void_mm_sfence(void) [9]
mfence (asm), void_mm_mfence(void) [10]
ARMv7
dmb (asm)
对硬件memory barrier的更多理解
两个地方可能除外:
MESI协议
M: Modified,已修改
E: Exclusive,排他
S: Shared,共享
I: Invalid,无效
IA32 的CPU实现了MESI协议来保证Cache coherence。 CPU的总线监测单元,始终监视着总线上所有的内存写操作,以便随时调整自己的Cache状态。
-> Modified。 本CPU写,则直接写到Cache,不产生总线事物;其它CPU写,则不涉及本CPU的Cache,其它CPU读,则本CPU需要把Cache line中的数据提供给它,而不是让它去读内存。
-> Exclusive。只有本CPU有该内存的Cache,而且和内存一致。 本CPU的写操作会导致转到Modified状态。
-> Shared。 多个CPU都对该内存有Cache,而且内容一致。任何一个CPU写自己的这个Cache都必须通知其它的CPU。
-> Invalid。 一旦Cache line进入这个状态,CPU读数据就必须发出总线事物,从内存读。
DMA写策略
1. Write through策略。 这种情形比较简单。
-> 本CPU写内存,是write through的,因此无论什么时候DMA读内存,读到的都是正确数据。
-> DMA写内存,如果DMA要写的内存被本CPU缓存了,那么必须Invalidate这个Cache line。下次CPU读它,就
直接从内存读。
2. Write back策略。 这种情形相当复杂。
-> DMA读内存。被本CPU总线监视单元发现,而且本地Cache中有Modified数据,本CPU就截获DMA的内存读操作,
把自己Cache Line中的数据返回给它。
-> DMA写内存。而且所写的位置在本CPU的Cache中,这又分两种情况:
http://en.wikipedia.org/wiki/Memory_ordering#Compiler_memory_barrier