内核中的likely()和unlikely()

最近在看内核代码时,在条件判断中出现了likely和unlike,比如在seq_read中有如下代码片段:

复制代码
1         if (err < 0)
2             break;
3         if (unlikely(err))
4             m->count = 0;
5         if (unlikely(!m->count)) {
6             p = m->op->next(m, p, &pos);
7             m->index = pos;
8             continue;
9         }
复制代码

那么其作用是什么?
1 在linux/compiler.h中找到了定义

复制代码
1 /*
2  * Generic compiler-dependent macros required for kernel
3  * build go below this comment. Actual compiler/compiler version
4  * specific implementations come from the above header files
5  */
6 通用的编译器宏指令, 注:__builtin_expect由compiler在编译阶段理解并优化成指令流水,该语句并不是包含在某一头文件中
7 #define likely(x)    __builtin_expect(!!(x), 1)
8 #define unlikely(x)    __builtin_expect(!!(x), 0)
复制代码

这里输入的参数x必须为整数,一般为条件表达式,返回为0或者1两种结果,使用likely时表示后面的判断成功概率大,使用unlikely时,表示后面的判断成功概率小,gcc解释如下:

這是使用 GCC 內的特殊 Function, 可以查 GCC Document

– Built-in Function: long __builtin_expect (long EXP, long C)
You may use `__builtin_expect’ to provide the compiler with branch
prediction information. In general, you should prefer to use
actual profile feedback for this (`-fprofile-arcs’), as
programmers are notoriously bad at predicting how their programs
actually perform. However, there are applications in which this
data is hard to collect.

The passing in value is the value of EXP, which should be an integral
expression. The value of C must be a compile-time constant. The
semantics of the built-in are that it is expected that EXP == C.
For example:

if (__builtin_expect (x, 0))
foo ();

would indicate that we do not expect to call `foo’, since we
expect `x’ to be zero. Since you are limited to integral
expressions for EXP, you should use constructions such as

if (__builtin_expect (ptr != NULL, 1))
error ();

when testing pointer or floating-point values.

2 测试
2.1 测试unlikely

[kedar@ashwamedha ~]$ cat abc.c
int
testfun(int x)
{
        if(__builtin_expect(x, 0)) {
                              ^^^--- We instruct the compiler, "else" block is more probable
                x = 5;
                x = x * x;
        } else {
                x = 6;
        }
        return x;
}
 
[kedar@ashwamedha ~]$ gcc -O2 -c abc.c
[kedar@ashwamedha ~]$ objdump  -d abc.o
 
abc.o:     file format elf32-i386
 
Disassembly of section .text:
 
00000000 :
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   8b 45 08                mov    0x8(%ebp),%eax
   6:   85 c0                   test   %eax,%eax
   8:   75 07                   jne    11 < testfun+0x11 >
                                ^^^ --- The compiler branches the "if" block and keeps "else" sequential
   a:   b8 06 00 00 00          mov    $0x6,%eax
f:   c9                      leave
  10:   c3                      ret
  11:   b8 19 00 00 00          mov    $0x19,%eax
  16:   eb f7                   jmp    f < testfun+0xf >
2.2 测试likey
[kedar@ashwamedha ~]$ cat abc.c
int
testfun(int x)
{
        if(__builtin_expect(x, 1)) {
                              ^^^ --- We instruct the compiler, "if" block is more probable
                x = 5;
                x = x * x;
        } else {
                x = 6;
        }
        return x;
}
                                                                                                    
[kedar@ashwamedha ~]$ gcc -O2 -c abc.c
[kedar@ashwamedha ~]$ objdump  -d abc.o
                                                                                                    
abc.o:     file format elf32-i386
                                                                                                    
Disassembly of section .text:
                                                                                                    
00000000 :
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   8b 45 08                mov    0x8(%ebp),%eax
   6:   85 c0                   test   %eax,%eax
   8:   74 07                   je     11 < testfun+0x11 >
                                ^^^ --- The compiler branches the "else" block and keeps "if" sequential 
   a:   b8 19 00 00 00          mov    $0x19,%eax
   f:   c9                      leave
  10:   c3                      ret
  11:   b8 06 00 00 00          mov    $0x6,%eax
  16:   eb f7                   jmp    f < testfun+0xf >
但是在本机测试时,代码流未发生改变
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值