Q1 # What is the role of the define barrier () _ ASM _ volatile _ ("": "Memory") Macro?
A: This macro is defined in the blob-2.0.5-pre2/include/BLOB/util. h and is used multiple times in the blob-2.0.5-pre2/src/BLOB/intel16.c. According to expert guidance from the oldlinux.org forum, I found the macro explanation in section 5.3.2 of ulk2: the macro, however, forbids the complier to reshuffle the instructions. that is, the macro prohibits the compiler from re-arranging the (assembly language) commands. When using compilers with optimization functions, you cannot expect that the commands will be executed strictly in the order they appear in the source program. For example, the compiler may re-arrange assembly language commands to optimize the usage of registers in the CPU, which will greatly increase the running speed of the program.
However, in the face of synchronization problems, it is necessary to avoid re-sorting of commands. In this case, you need to use the memory barrier premitive to ensure that the commands before the primitive are executed before the commands after the primitive start.
The correct access to 28f320c3 flash memory depends on the order (sequence) of the command code sequence sent to Cui. Therefore, you need to use the memory barrier primitive, while barrier () macro is the specific implementation of the memory barrier primitive.
Will assembly language commands be re-ordered by compilers with optimized functions? Let's test it.
Take the read_device_id function for reading the device identification code of 28f320c3 flash in the Flash. c file as an example.
2010read_device_id (u32 * blockstart)
{
2010* P = (2010*) blockstart;
2017-11-result;
* P = read_config;
Barrier ();
Result = * (p + 1 );
Barrier ();
* Blockstart = read_array;
Barrier ();
Return result;
}
The test platform is Red Hat Linux 9. the compiler uses arm-elf-GCC and the command is used for compiling:
Arm-elf-gcc-O2-c-o flash. O flash. c
Decompile the generated target file flash. O and run the following command:
Arm-elf-objdump-D flash. O> barrier.txt
Next, comment out all barrier () macro calls in read_device_id and re-compile flash. C:
Arm-elf-gcc-O2-c-o flash. O flash. c
Decompile the generated target file flash. O and run the following command:
Arm-elf-objdump-D flash. O> nobarrier.txt
Finally, use the diff command to compare the output results of the two disassembly tasks:
Diff-BB nobarrier.txt barrier.txt> diff.txt
When the barrier () macro is not used and used in this diff.txt file, the compiler produces different assembly language commands:
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: e1a012003 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
The red assembly commands are assembly language commands generated by arm-elf-GCC without the barrier () Macro. In contrast, we can find that the compiler indeed re-sorts assembly language commands.
References:
Intel advanced + boot block flash memory (C3) Datasheet
The 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