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