详解likely和unlikely函数
内核源码:linux-2.6.38.8.tar.bz2
在Linux内核中likely和unlikely函数有两种(只能两者选⼀)实现⽅式,它们的实现原理稍有不同,但作⽤是相同的,下⾯将结合linux-2.6.38.8版本的内核代码来进⾏讲解。
1、对__builtin_expect的封装
它们的源代码如下:
库函数printf详解
/* linux-2.6.38.8/include/linux/compiler.h */
# define likely(x) __builtin_expect(!!(x), 1)
# 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,如下⾯的例⼦:
#include <stdio.h>
int main(void)
{
int a;
scanf("%d", &a);
if(__builtin_expect(a, 4))
printf("if: a = %d\n", a);
else
printf("else: a = %d\n", a);
return 0;
}
分别输⼊整数0到4来进⾏5次测试,它们的输出分别为:
else: a = 0
if: a = 1
if: a = 2
if: a = 3
if: a = 4
注意,在上例中只有输⼊整数0的时候才执⾏else后的打印语句,也就是说__builtin_expect(a, 4)函数的值就是表达式a的值。
记住,它们只是⽤来提升性能的优化⼿段,并不会改变原来表达式的值。
2、使⽤__branch_check__函数
它们的源代码如下:
/* linux-2.6.38.8/include/linux/compiler.h */
# ifndef likely
#  define likely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 1))
# endif
# ifndef unlikely
#  define unlikely(x) (__builtin_constant_p(x) ? !!(x) : __branch_check__(x, 0))
# endif
(1)、先使⽤内置函数__builtin_constant_p忽略表达式x为常量的情况
__builtin_constant_p也是GCC的内置函数,函数原型为int  __builtin_constant_p(exp),⽤于判断表达式exp在编译时是否是⼀个常量,如果是则函数的值为整数1,否则为0,如下⾯的例⼦:
#include <stdio.h>
#include <stdlib.h>
#define VALUE 5
int main(void)
{
char *ptr = NULL;
int num, count;
ptr = malloc(20);
num = __builtin_constant_p(ptr) ? 20 : 20 + 10;
printf("num = %d\n", num);
free(ptr);
count = __builtin_constant_p(VALUE) ? 20 + VALUE : 10;
printf("count = %d\n", count);
return 0;
}
例⼦的输出结果:
num = 30
count = 25
例⼦中的ptr为指针变量,所以__builtin_constant_p(ptr)的值为0,num的值为30。
(2)、函数__branch_check__的实现
/* linux-2.6.38.8/include/linux/compiler.h */
#define __branch_check__(x, expect) ({    \
int ______r;    \
static struct ftrace_branch_data  \
__attribute__((__aligned__(4)))  \
__attribute__((section("_ftrace_annotated_branch"))) \
______f = {    \
.func = __func__,  \
.file = __FILE__,  \
.line = __LINE__,  \
};      \
______r = likely_notrace(x);  \
ftrace_likely_update(&______f, ______r, expect); \
______r;    \
})
使⽤它来检查判断条件并记录likely判断的预测信息,之后根据预测信息进⾏相应的优化以提升性能。    函数__branch_check__的返回值为______r的值,也就是参数x的值。