阳光烂灿的日子

--记录所有碎碎念

LikelyUnlikely

| Comments

更好的解释请看Kernelnewbies

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

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.h

13: #define likely(x) __builtin_expect((x),1)

14: #define unlikely(x) __builtin_expect((x),0)

++++ kernel/sched.c

564: 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范围内了。

Comments

Copyright © 2017 - lerosua - Powered by Octopress