本文转载自:http://blog.csdn.net/npy_lp/article/details/7175517

内核源码:Linux-2.6.38.8.tar.bz2

参考文档:http://gcc.gnu.org/onlinedocs/gcc-4.6.2/gcc/Other-Builtins.html#Other-Builtins

linux内核中likely和unlikely函数有两种(只能两者选一)实现方式,它们的实现原理稍有不同,但作用是相同的,下面将结合linux-2.6.38.8版本的内核代码来进行讲解。

1、对__builtin_expect的封装

它们的源代码如下:

  1. /* linux-2.6.38.8/include/linux/compiler.h */
  2. # define likely(x)  __builtin_expect(!!(x), 1)
  3. # define unlikely(x)    __builtin_expect(!!(x), 0)

__builtin_expect 是GCC的内置函数,用来对选择语句的判断条件进行优化,常用于一个判断条件经常成立(如likely)或经常不成立(如unlikely)的情况。

__builtin_expect的函数原型为long  __builtin_expect (long exp, long c),返回值为完整表达式exp的值,它的作用是期望表达式exp的值等于c(注意,如果exp == c条件成立的机会占绝大多数,那么性能将会得到提升,否则性能反而会下降)。

在普通的应用程序中也可以使用__builtin_expect,如下面的例子:

  1. #include <stdio.h>
  2. int main(void)
  3. {
  4. int a;
  5. scanf("%d", &a);
  6. if(__builtin_expect(a, 4))
  7. printf("if: a = %d\n", a);
  8. else
  9. printf("else: a = %d\n", a);
  10. return 0;
  11. }

分别输入整数0到4来进行5次测试,它们的输出分别为:

  1. else: a = 0
  2. if: a = 1
  3. if: a = 2
  4. if: a = 3
  5. if: a = 4

注意,在上例中只有输入整数0的时候才执行else后的打印语句,也就是说__builtin_expect(a, 4)函数的值就是表达式a的值。

记住,它们只是用来提升性能的优化手段,并不会改变原来表达式的值。

2、使用__branch_check__函数

它们的源代码如下:

  1. /* linux-2.6.38.8/include/linux/compiler.h */
  2. # ifndef likely
  3. #  define likely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 1))
  4. # endif
  5. # ifndef unlikely
  6. #  define unlikely(x)   (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0))
  7. # endif

(1)、先使用内置函数__builtin_constant_p忽略表达式x为常量的情况

__builtin_constant_p也是GCC的内置函数,函数原型为int  __builtin_constant_p(exp),用于判断表达式exp在编译时是否是一个常量,如果是则函数的值为整数1,否则为0,如下面的例子:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define VALUE 5
  4. int main(void)
  5. {
  6. char *ptr = NULL;
  7. int num, count;
  8. ptr = malloc(20);
  9. num = __builtin_constant_p(ptr) ? 20 : 20 + 10;
  10. printf("num = %d\n", num);
  11. free(ptr);
  12. count = __builtin_constant_p(VALUE) ? 20 + VALUE : 10;
  13. printf("count = %d\n", count);
  14. return 0;
  15. }

例子的输出结果:

  1. num = 30
  2. count = 25

例子中的ptr为指针变量,所以__builtin_constant_p(ptr)的值为0,num的值为30。

(2)、函数__branch_check__的实现

  1. /* linux-2.6.38.8/include/linux/compiler.h */
  2. #define __branch_check__(x, expect) ({                  \
  3. int ______r;                    \
  4. static struct ftrace_branch_data        \
  5. __attribute__((__aligned__(4)))     \
  6. __attribute__((section("_ftrace_annotated_branch"))) \
  7. ______f = {             \
  8. .func = __func__,           \
  9. .file = __FILE__,           \
  10. .line = __LINE__,           \
  11. };                      \
  12. ______r = likely_notrace(x);            \
  13. ftrace_likely_update(&______f, ______r, expect); \
  14. ______r;                    \
  15. })

使用它来检查判断条件并记录likely判断的预测信息,之后根据预测信息进行相应的优化以提升性能。

函数__branch_check__的返回值为______r的值,也就是参数x的值。

最新文章

  1. linux mysql自动备份 和 数据恢复
  2. Delphi7 客户端调用WebService(天气预报)
  3. Struts2(二):工作原理
  4. iOS开发中的一些细节BUG的解决
  5. css修改,类似elememt.style样式修改
  6. JavaScript常用标签和方法总结
  7. HDU 4358 Boring counting 树状数组+思路
  8. int组成时间值
  9. (转)PHP中的 抽象类(abstract class)和 接口(interface)
  10. The iOS Design Cheat Sheet 界面设计速参
  11. eclipse下配置安装ssm图文教程(web版)
  12. Java中参数传递问题
  13. 【HTTP协议】---TCP三次握手和四次挥手
  14. 三、thymeleaf模板引擎构建前台html, 后台使用 ModelAndView 和 Model 模型
  15. EasyUI在window中使用kindeditor 4.1.10在IE9中不能回显、获得焦点编辑的问题
  16. 完美实现 Windows 下网络通信
  17. Java多线程——Lock&amp;Condition
  18. BZOJ4350: 括号序列再战猪猪侠【区间DP】
  19. [Elixir004]通过环境变量(Environment Variables)来管理config
  20. 【HDU 5283】Senior&#39;s Fish

热门文章

  1. jmeter录制接口以及并发测试
  2. [配置Cordova环境] [Alfred使用手册]
  3. MySQL实现了四种通信协议
  4. Scrapy学习-4-Items类&amp;Pipelines类
  5. ajax 分页(jquery分页插件pagination) 小例1
  6. Fragment的广播消息接收
  7. 一个强大的Android模拟器Genymotion
  8. Codeforces 713C Sonya and Problem Wihtout a Legend(DP)
  9. 配置maven从私服上下载构件
  10. C/C++动态二维数组的内存分配和释放