LikelyUnlikely

来源:互联网 发布:知乎 b站冠名上海男篮 编辑:程序博客网 时间:2024/05/18 18:55

在内核中常会见到下面这样的代码。

bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx);if (unlikely(!bvl)) {  mempool_free(bio, bio_pool);  bio = NULL;  goto out;} 



这个likely()和unlikely()其实是宏定义。原始定义在
include/linux/compiler.h中,如下:


#define likely(x)       __builtin_expect(!!(x), 1)#define unlikely(x)     __builtin_expect(!!(x), 0)

__builtin_expect是GCC内建的函数。下面引用linuxform中的一篇讲GCC扩展文章

的一部分(原我找到的也是引用的文章,此处给出链接),里面解释得很清楚。


——————————————————-* __builtin_expect(EXP, C)内建函数 __builtin_expect 用于为编译器提供分支预测信息,其返回值是整数表达式 EXP
的值,C 的值必须是编译时常数。例如:++++ include/linux/compiler.h13: #define likely(x)       __builtin_expect((x),1)14: #define unlikely(x)     __builtin_expect((x),0)++++ kernel/sched.c564:         if (unlikely(in_interrupt())) {565:                 printk(”Scheduling in interruptn”);566:                 BUG();567:         }这个内建函数的语义是 EXP 的预期值是 C,编译器可以根据这个信息适当地重排语句块的顺序,使程序在预期的情况下有更高的执行效率。上面的例子表示处于中断上下文是很少发生的,第 565-566 行的目标码可能会放在较远的位置,以保证经常执行的目标码更紧凑。——————————————————-



总结,这个宏主要是优化的作用。如果英文好的话可以看文章一开始给出的

在kernelnewbies中的链接,那里有更详细的解说。


细心的人应该留意到有一点不同,likely()一开始偶给的定义为__builtin_expect(!!(x),1)。


后来的文章解说中成了__builtin_expect((x),1)。


这应该是后来的版本更改所至。就是新近版本的内核已经更改成__builtin_expect(!!(x),1).


加上个“!!”有什么好处哩。我想是因为使代码强壮与兼容的原因。因为不能保证x表达式的结果一定是1或0,有可能是非0数。加了“!!”,结果就一定是在1和0范围内了。