I found below macro when i am going through kernel source code and I am unable to understand what it is doing.
#define barrer() __asm__ __volatile__("":::"memory")
Please some one clarify this.
I found below macro when i am going through kernel source code and I am unable to understand what it is doing.
#define barrer() __asm__ __volatile__("":::"memory")
Please some one clarify this.
This is a compiler memory barrier used to prevent the compiler from reordering instructions, if we look at the Wikipedia article on Memory ordering it says:
These barriers prevent a compiler from reordering instructions, they do not prevent reordering by CPU
The GNU inline assembler statement
asm volatile("" ::: "memory");
or even
__asm__ __volatile__ ("" ::: "memory");
forbids GCC compiler to reorder read and write commands around it.
You can find details of how this works in the Clobber List section of the GCC-Inline-Assembly-HOWTO and I quote:
[...]If our instruction modifies memory in an unpredictable fashion, add "memory" to the list of clobbered registers. This will cause GCC to not keep memory values cached in registers across the assembler instruction. We also have to add the volatile keyword if the memory affected is not listed in the inputs or outputs of the asm. [...]
It's gcc inline assembly. However there is no actual assembly in there (the first empty string) and only the specified side effects are relevant.
That is the "memory" clobber. It tells the compiler that the assembly accesses memory (and not just registers) and so the compiler must not reorder its own memory accesses across it to prevent reading old values or overwriting new values.
Thus it acts, as the macro name tells, as a compiler level memory barrier on the language level. It is not sufficient to prevent hardware based memory access reordering which would be necessary when DMA or other processors in a SMP machine would be involved.
The __volatile__
makes sure that the inline assembly is not optimized away or reordered with respect to other volatile statements. It is not strictly necessary since gcc assumes inline assembly without output to be volatile.
That is the implementation. Other memory barrier primitives and their documentation can be found in Documentation/memory-barriers.txt in the Linux kernel sources.
This macro doesn't "do" anything on a language level of C, but it does prevent the compiler from reordering code around this barrier.
If you have platform knowledge on how your generated code behaves in concurrent execution contexts, then you may be able to produce a correct program as long as you can prevent the compiler from changing the order of your instructions. This barrier is a building block in such platform-specific, concurrent code.
As an example, you might want to write some kind of lock-free queue, and you're relying on the fact that your architecture (x86?) already comes with a strongly orderered memory model, so your naive stores and loads imply sufficient synchronization, provided the emitted code follows the source code order. Pairing the platform guarantees with this compiler barrier allows you to end up with correct machine code (although it's of course undefined behaviour from the perspective of C).