本文转载自: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的值。

详解likely和unlikely函数【转】的更多相关文章

  1. SQL 中详解round(),floor(),ceiling()函数的用法和区别?

    SQL 中详解round(),floor(),ceiling()函数的用法和区别? 原创 2013年06月09日 14:00:21   摘自:http://blog.csdn.net/yueliang ...

  2. 第7.25节 Python案例详解:使用property函数定义与实例变量同名的属性会怎样?

    第7.25节 Python案例详解:使用property函数定义与实例变量同名的属性会怎样? 一.    案例说明 我们上节提到了,使用property函数定义的属性不要与类内已经定义的普通实例变量重 ...

  3. 第7.24节 Python案例详解:使用property函数定义属性简化属性访问代码实现

    第7.24节 Python案例详解:使用property函数定义属性简化属性访问代码实现 一.    案例说明 本节将通过一个案例介绍怎么使用property定义快捷的属性访问.案例中使用Rectan ...

  4. 详解wait和waitpid函数

    #include <sys/types.h> /* 提供类型pid_t的定义 */ #include <sys/wait.h> pid_t wait(int *status) ...

  5. Linux 信号详解一(signal函数)

    信号列表 SIGABRT 进程停止运行 SIGALRM 警告钟 SIGFPE 算述运算例外 SIGHUP 系统挂断 SIGILL 非法指令 SIGINT 终端中断 SIGKILL 停止进程(此信号不能 ...

  6. (译)详解javascript立即执行函数表达式(IIFE)

    写在前面 这是一篇译文,原文:Immediately-Invoked Function Expression (IIFE) 原文是一篇很经典的讲解IIFE的文章,很适合收藏.本文虽然是译文,但是直译的 ...

  7. 《Windows驱动开发技术详解》之派遣函数

    驱动程序的主要功能是负责处理I/O请求,其中大部分I/O请求是在派遣函数中处理的.用户模式下所有对驱动程序的I/O请求,全部由操作系统转化为一个叫做IRP的数据结构,不同的IRP数据会被“派遣”到不同 ...

  8. [二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例 如何定义函数式接口

    函数式接口详细定义 package java.lang; import java.lang.annotation.*; /** * An informative annotation type use ...

  9. 详解MySQL中concat函数的用法(连接字符串)

    MySQL中concat函数 使用方法: CONCAT(str1,str2,…) 返回结果为连接参数产生的字符串.如有任何一个参数为NULL ,则返回值为 NULL. 注意: 如果所有参数均为非二进制 ...

  10. 详解javascript立即执行函数表达式(IIFE)

    立即执行函数,就是在定义函数的时候直接执行,这里不是申明函数而是一个函数表达式 1.问题 在javascript中,每一个函数在被调用的时候都会创建一个执行上下文,在函数内部定义的变量和函数只能在该函 ...

随机推荐

  1. 洛谷 [P2148] E&G

    SG函数的应用 首先每一组都是独立的,所以我们可以求出每一组的SG值异或出来. 那么怎么求每一组的SG值呢,网上的题解都是打表找规律,但其实这个规律是可以证明的 先看规律: x为奇数,y为奇数:SG= ...

  2. VirtualBox 5.0.10 中 Fedora 23 在安装了增强工具后无法自动调节虚拟机分辨率的问题(改)

    VirtualBox 5.0.10 中安装 Fedora 23,即使在安装了增强工具后,仍然会发现虚拟机无法根据 VirtualBox 的运行窗口大小自动进行分辨率调节.究其原因,主要是因为 Fedo ...

  3. 解决三星 BIOS 模式没有 Fast Bios Mode选项 U盘动项问题

    今天想分下盘,进入biso竟然没有网上说 Fast Bios Mode选项,最后自己误打误撞竟然设置成功了,太不可思议了官方这么说:开机按F2进入BIOS设置,找到Boot选项下Boot Device ...

  4. jquery的固定定位效果

    今天做了个固定定位的效果.比如对导航需要进行固定定位效果: 当没有滚动到导航下面,导航正常显示. 当滚动到导航下面,导航就固定到顶部. 这个效果使用了jquery的方法实现,具体思路为: 1)首先获取 ...

  5. Hive入门及常用指令

    基础命令show databases; # 查看某个数据库use 数据库; # 进入某个数据库show tables; # 展示所有表desc 表名; # 显示表结构show partitions 表 ...

  6. hadoop学习 的yarn

    Yarn的产生 mapReduc1.0 1单点故障 2扩展效率低 3资源利用率高 降低运维成本 方便数据共享 多计算框架支持 MapReduce Spark Storm Yarn的架构图 Yarn模块 ...

  7. shell mysql 直接创建表

    shell 直接创建表 #!/bin/bash mysql -hdatabases -uroot -p^xxxxasdasdadd <<EOF Create Database If Not ...

  8. UI标签库专题二:JEECG智能开发平台Column(列) 子标签

    UI标签库专题二:JEECG智能开发平台Column(列) 子标签  1.1. Column(列) 子标签 1.1.1. 演示样例 <t:dgCol title="年龄" ...

  9. SpringBoot学习之启动报错【This application has no explicit mapping for /error.....】

    今天做SpringBoot小例子,在请求controller层的时候出现如下问题. Whitelabel Error Page This application has no explicit map ...

  10. C语言连接MySQL(codeblocks)

    #include <stdio.h> #include <winsock2.h> #include <mysql.h> /*数据库连接用宏*/ #define HO ...