static-key和__builtin_expect有什么区别?

大宝剑*_*大宝剑 1 linux kernel linux-kernel

我读了linux内核文件,这个文件描述了static-key:http://lxr.linux.no/linux+v3.11.1/Documentation/static-keys.txt

那么,static-key和__builtin_expect有什么区别?它们都暗示我们可以使用它们来实现likyly()不太可能().

The*_*ist 5

  • __builtin_expect在代码中引入了一个真正的测试和分支指令,需要由CPU进行评估,而来自更可能的路径的指令继续被预先提取到CPU流水线中.

  • static_key_*引入了一个NOP占用代码中足够空间的指令,以后可以在运行时修补以添加空间jmp <label>.这可用于适应调试打印,对常规工作情况无影响,即代码未被调试.

Linux内核文档中static-keys,

gcc(v4.5)添加了一个新的'asm goto'语句,允许分支到标签:
gcc.gnu.org/ml/gcc-patches/2009-07/msg01556.html

使用'asm goto',我们可以创建默认情况下采用或不采用的分支,而无需检查内存.然后,在运行时,我们可以修改分支站点以更改分支方向.

例如,如果我们有一个默认禁用的简单分支:

if (static_key_false(&key))
        printk("I am the true branch\n");
Run Code Online (Sandbox Code Playgroud)

因此,默认情况下不会发出'printk'.生成的代码将由直线代码路径中的单个原子"无操作"指令(x86上的5个字节)组成.当分支被"翻转"时,我们将在直线代码路径中使用"跳转"指令修补"无操作"到外线真分支.因此,改变分支方向是昂贵的,但分支选择基本上是"免费的".这是此优化的基本权衡.

这种低级修补机制称为"跳转标签修补",是静态密钥的基础.