Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1666967
  • 博文数量: 174
  • 博客积分: 5493
  • 博客等级: 上校
  • 技术积分: 5802
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-05 15:13
个人简介

炼狱,是为追逐光芒

文章分类

全部博文(174)

文章存档

2017年(1)

2016年(3)

2015年(9)

2014年(5)

2013年(23)

2012年(56)

2011年(45)

2010年(32)

分类: LINUX

2011-12-22 11:58:49

在Linux kernel的源代码中,经常能见到if(likely(x))或if(unlikely(x))之类的用法,其确切含义需要说明一下,以便更好的理解kernel的源代码。
likely与unlikely这两个宏在linux/compiler.h中的定义如下:
  1. #define likely(x) __builtin_expect(!!(x),1)
  2. #define unlikely(x) __builtin_expect(!!(x),0)
很明显,需要先弄清楚这个__builtin_expect()函数的意义。
__builtin_expect()是gcc的一个内建函数,其原型如下:
long __builtin_expect (long exp, long c);
该函数由GCC本身提供,用于优化代码。其中参数exp为任一表达式,c必须为常量值,其意义是在exp==c时,该函数返回非0值,意即希望exp==c。
回到likely和unlikely,likely实际是希望表达式x==1,即表达式x成立,并且在代码实际执行中,表达式x在绝大多数情况下是成立的,相反,unlikely是希望表达式在绝大多数情况下不成立,
如果有下列代码:
if(unlikely(a > b) {
    foo();
}
这段代码的意思是,在绝大多数情况下a > b这个表达式是不成立的,不成立时执行函数foo().

  1. (框内这段理解是有误的,可以直接跳过去不看,或者看GFree_Wind的评论,对比理解)
  2. 另外有一点要注意的是,由于likely定义时用的常量是1,unlikely用的常量是0,这正好符合c/c++语言中bool变量的实际值,而_builtin_expect()函数对exp与c进行严格相等的比较的,
  3. 因此使用likely和unlikely时,其参数应该只使用逻辑表达式,因为逻辑表达式的值只有0或1。除非真要判断某个变量的值是1或0时,才会将其它类型的参数传给likely或unlikely。这一点可能很多人会不小心用错。

使用这两个宏定义的好处是优化条件判断。

这篇文章为转载,当时只是作为备忘录转载,抱歉忘了出处,这里最后一段是有误的,GFree_Wind 指出的问题,理解是正确的,特此更正本文,对阅读过本文的朋友表示歉意,希望尚没有因此给您带来麻烦,这也提醒我,以后转载文章都先认真,仔细,完整分析作文原意,再转载相关,在这里提醒批评下自己做事的不严谨,最后谢谢GFree_Wind,为保证原创作者原文完整性,我只将错误部分(即框内部分)灰色掉
阅读(4343) | 评论(12) | 转发(4) |
给主人留下些什么吧!~~

leon_yu2011-12-26 11:30:24

GFree_Wind: 给你一个官方的likely的文档链接:
http://kernelnewbies.org/FAQ/LikelyUnlikely

这个说的不错.....
谢谢,我注意到最后一句话
How should I use it ?
You should use it only in cases when the likeliest branch is very very very likely, or when the unlikeliest branch is very very very unlikely.
是中国人写的吗,感觉有点中式英语的味道啊,呵呵

GFree_Wind2011-12-26 11:07:25

leon_yu: 当时调代码比较忙,likely()又不是我调试重点,所以了解大意后,就没多花时间,我忘记出处,不过标题有注明转载,当然你的建议我采纳,加链接比较好。个人心里.....
给你一个官方的likely的文档链接:
http://kernelnewbies.org/FAQ/LikelyUnlikely

这个说的不错

leon_yu2011-12-26 10:25:15

GFree_Wind: 其实你的文章里面也是!!(x)的形式。

不用客气,讨论才有意思嘛。谁都可能有疏忽。

不过有一点要提醒你一下,转载文章,要注明原作者和原链接,表示对原作者的.....
当时调代码比较忙,likely()又不是我调试重点,所以了解大意后,就没多花时间,我忘记出处,不过标题有注明转载,当然你的建议我采纳,加链接比较好。个人心里,对所有原创并无私奉献者都充满敬意

GFree_Wind2011-12-26 10:15:05

leon_yu: 上周调代码是用到unlikely(),第一次遇到这个函数,Google了解了下该函数大意,转载这篇文章作为备忘录,当时没有深究,刚才仔细看了下这个函数的实现,在我用的.....
其实你的文章里面也是!!(x)的形式。

不用客气,讨论才有意思嘛。谁都可能有疏忽。

不过有一点要提醒你一下,转载文章,要注明原作者和原链接,表示对原作者的尊重。

leon_yu2011-12-26 10:00:29

GFree_Wind: 因此使用likely和unlikely时,其参数应该只使用逻辑表达式,因为逻辑表达式的值只有0或1。除非真要判断某个变量的值是1或0时,才会将其它类型的参数传给likely或.....
上周调代码是用到unlikely(),第一次遇到这个函数,Google了解了下该函数大意,转载这篇文章作为备忘录,当时没有深究,刚才仔细看了下这个函数的实现,在我用的2.6.10内核里其最终实现是# define __builtin_expect(x, expected_value)  (x),那么likely(x)实际上就是(!!(x)),用“!!”来做做否定之否定,这也是内核常用的一个技巧,是我疏忽了,谢谢你提醒