Q1 #define barrier() __asm__ __volatile__("": : :"memory")宏的作用?
A:这个宏定义于blob-2.0.5-pre2/include/blob/util.h中,在blob-2.0.5-pre2/src/blob/intel16.c中多次用到。经过Oldlinux.org论坛中的高人指点,我在ULK2的5.3.2节中找到了对这个宏的解释:The macro, however, forbids the complier to reshuffle the instructions.即该宏禁止了编译器对(汇编语言)指令的重新排列。当使用带优化功能的编译器时,你不能指望指令会严格按照它们在源程序中出现的顺序来执行。例如,编译器可能会为了优化CPU中寄存器的使用而重新排列(reorder)汇编语言指令,这将大大提高程序的运行速度。
然而当面对同步问题时,则需要避免指令的重新排序。此时需要使用存储器屏障原语(memory barrier premitive)来保证位于该原语之前的指令在位于该原语之后的指令开始执行之前执行完毕。
而对28F320C3 Flash存储器的正确访问是依赖于发送到CUI的命令代码序列的先后次序(时序)正确,因此需要使用存储器屏障原语,而barrier()宏正是存储器屏障原语的具体实现。
汇编语言指令真的会被有优化功能的编译器重新排序吗?不妨来测试一下。
以flash.c文件中的读取28F320C3 Flash的Device Identification Code的函数read_device_id为例
u16 read_device_id(u32 *blockstart)
{
u16 *p = (u16 *)blockstart;
u16 result;
*p = READ_CONFIG;
barrier();
result = *(p + 1);
barrier();
*blockstart = READ_ARRAY;
barrier();
return result;
}
测试平台为Red Hat Linux 9,编译器选用arm-elf-gcc,编译时使用命令:
arm-elf-gcc -O2 -c -o flash.o flash.c
然后反汇编生成的目标文件flash.o,使用命令:
arm-elf-objdump -d flash.o > barrier.txt
接下来注释掉read_device_id中的所有barrier()宏调用,重新编译flash.c:
arm-elf-gcc -O2 -c -o flash.o flash.c
然后反汇编生成的目标文件flash.o,使用命令:
arm-elf-objdump -d flash.o > nobarrier.txt
最后使用diff命令来比较两次反汇编输出的结果:
diff -bB nobarrier.txt barrier.txt > diff.txt
这样diff.txt文件中得到了不使用barrier()宏时和使用时,编译器所产生的汇编语言指令的不同:
9,16c9,16
< 8: e3a03090 mov r3, #144 ; 0x90
< c: e1c030b0 strh r3, [r0]
< 10: e24cb004 sub r11, r12, #4 ; 0x4
< 14: e1d030f2 ldrsh r3, [r0, #2]
< 18: e3a020ff mov r2, #255 ; 0xff
< 1c: e5802000 str r2, [r0]
< 20: e1a03803 mov r3, r3, lsl #16
< 24: e1a00823 mov r0, r3, lsr #16
---
> 8: e24cb004 sub r11, r12, #4 ; 0x4
> c: e3a03090 mov r3, #144 ; 0x90
> 10: e1c030b0 strh r3, [r0]
> 14: e1d020f2 ldrsh r2, [r0, #2]
> 18: e3a030ff mov r3, #255 ; 0xff
> 1c: e5803000 str r3, [r0]
> 20: e1a02802 mov r2, r2, lsl #16
> 24: e1a00822 mov r0, r2, lsr #16
红色的汇编指令是不使用barrier()宏时由arm-elf-gcc所产生的汇编语言指令,对比之下可以发现编译器确实有重新排序汇编语言指令的现象。
参考资料:
Intel Advanced+ Boot Block Flash Memory(C3) datasheet
blob-2.0.5-pre2/src/blob/intel16.c source code
Understanding the Linux Kernel 2rd Edition
ARM System Developer's Guide:Designing and Optimizing System Software