当我浏览内核源代码时,我发现下面的宏,我无法理解它在做什么。
#define barrer() __asm__ __volatile__("":::"memory")
请有人澄清一下。
答案 0 :(得分:2)
这是一个编译器内存屏障,用于阻止编译器重新排序指令,如果我们看一下它所说的Wikipedia article on Memory ordering:
这些障碍阻止编译器重新排序指令,它们不会阻止CPU重新排序
GNU内联汇编语句
asm volatile("" ::: "memory");
甚至
__asm__ __volatile__ ("" ::: "memory");
禁止GCC编译器重新排序它周围的读写命令。
您可以在Clobber List的GCC-Inline-Assembly-HOWTO部分找到有关其工作原理的详细信息,并引用:
[...]如果我们的指令以不可预测的方式修改内存,则将“memory”添加到修饰寄存器列表中。这将导致GCC不通过汇编指令将寄存器值保存在寄存器中。如果受影响的内存未在asm的输入或输出中列出,我们还必须添加volatile关键字。 [...]
答案 1 :(得分:2)
这是gcc内联汇编。然而,那里没有实际的装配(第一个空字符串),只有指定的副作用是相关的。
这就是“记忆”咒语。它告诉编译器程序集访问内存(而不仅仅是寄存器),因此编译器不能重新排序它自己的内存访问,以防止读取旧值或覆盖新值。
因此,正如宏名称所示,它作为语言级别的编译器级别内存屏障。仅当涉及SMP机器中的DMA或其他处理器时,防止基于硬件的存储器访问重新排序是不够的。
__volatile__
确保内联汇编没有针对其他volatile语句进行优化或重新排序。由于gcc假定内联汇编而没有输出是易失性的,因此并不是绝对必要的。
这就是实施。其他内存屏障原语及其文档可以在Linux内核源代码的Documentation/memory-barriers.txt中找到。
答案 2 :(得分:0)
这个宏不会在C的语言级别上“执行”任何操作,但它确实会阻止编译器围绕此障碍重新排序代码。
如果您对生成的代码在并发执行上下文中的行为方式有平台知识,那么只要您可以阻止编译器更改指令的顺序,您就可以生成正确的程序。此障碍是此类特定于平台的并发代码中的构建块。
作为一个例子,您可能想要编写某种无锁队列,并且您依赖于您的体系结构(x86?)已经附带强或者内存模型的事实,因此您的天真存储和加载暗示充分同步,提供发出的代码遵循源代码顺序。将平台保证与此编译器屏障配对允许您最终得到正确的机器代码(尽管从C的角度来看当然是未定义的行为)。