这种情况下,cpu 0和cpu 1执行的指令和动作描述如下:
由于增加了memory barrier,保证了a、b这两个变量的访问顺序,从而保证了程序逻辑。
三、linux kernel的API
linux kernel的memory barrier相关的API列表如下:
barrier()这个接口和编译器有关,对于gcc而言,其代码如下:
#define barrier() __asm__ __volatile__("": : :"memory")
这里的__volatile__主要是用来防止编译器优化的。而这里的优化是针对代码块而言的,使用嵌入式汇编的代码分成三块:
1、嵌入式汇编之前的c代码块
2、嵌入式汇编代码块
3、嵌入式汇编之后的c代码块
这里__volatile__就是告诉编译器:不要因为性能优化而将这些代码重排,我需要清清爽爽的保持这三块代码块的顺序(代码块内部是否重排不是这里的__volatile__管辖范围了)。
barrier中的嵌入式汇编中的clobber list没有描述汇编代码对寄存器的修改情况,只是有一个memory的标记。我们知道,clober list是gcc和gas的接口,用于gas通知gcc它对寄存器和memory的修改情况。因此,这里的memory就是告知gcc,在汇编代码中,我修改了memory中的内容,嵌入式汇编之前的c代码块和嵌入式汇编之后的c代码块看到的memory是不一样的,对memory的访问不能依赖于嵌入式汇编之前的c代码块中寄存器的内容,需要重新加载。
优化屏障是和编译器相关的,而内存屏障是和CPU architecture相关的,当然,我们选择ARM为例来描述内存屏障。