Compiler Barrier
In multithreaded programming, it’s not uncommon to encounter situations where one wants to poll on a global flag until it becomes the desired value. The straightforward way is to write something like:
1 | while (flag != expected) ; |
The problem with it is that after turning on optimization, it may become a infinite loop, for the compiler can’t see the variable is change in the
loop body. One way to work around it is to use cpu_relax()
, namely memory
clobber in assembly, which tells the compiler to relinquish the
assumption that x
is kept intact, and reload it each iteration. In addition, the compiler is smart enough to only flush global visible variables.
Let’s illustrate it by view the generated assembly code for the following C code. Assembly is obtained using clang -S -O test.c
.
1 |
|
In this case, y
is a local variable, so it’s kept in %eax
without being flushed to memory.
1 | ... |
In this case, y
is static variable, whose storage if static, so its value needs to be flushed and re-read around the barrier.
1 | ... |