likely,unlikely宏與GCC內建函數__builtin_expect()

來源:互聯網
上載者:User


先羅嗦幾句
最近在讀linux 2.6 核心,雖然以前已經看了很多相關的知識,>也看了2,3遍,但讀2.6核心仍然感到很吃力。面對2.6如此龐大的核心,信心真的不是很足,而且好像 也沒有很好的、有協助的論壇來一起探討,哎!現在正在邊看>,邊看最新的核心,自>出版以來,核心已經有了很多的變化,好難讀啊!如果這樣讀 下去算不算“皓首窮經”呢,不得而知了!
言歸正傳
在讀linux/kernel/fork.c的時候遇到了unlikely宏定義,一路追蹤,最後找到了GCC內建函數__builtin_expect(),查閱GCC手冊,發現其定義如下:
long __builtin_expect (long exp, long c) [Built-in Function]
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 return 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.
大致是說,由於大部分程式員在分支預測方面做得很糟糕,所以GCC提供了這個內建函數來協助程式員處理分支預測,最佳化程式。其第一個參數exp為一個整型 運算式,這個內建函數的傳回值也是這個exp,而c為一個編譯期常量,這個函數的語義是:你期望exp運算式的值等於常量c,從而GCC為你最佳化程式,將 符合這個條件的分支放在合適的地方。
因為這個程式只提供了整型運算式,所以如果你要最佳化其他類型的運算式,可以採用指標的形式。
unlikely的定義如下:
#define unlikely(x) __builtin_expect(!!(x), 0)
也就是說我們期望運算式x的值為0,從而如果我們用
…….
if(unlikely(x)){
bar();
}
來測試條件的話,我們就不期望bar()函數執行,所以該宏的名字用unlikely也就是不太可能來表示。
likely宏與次類似.
說到底__builtin_expect函數就是為了最佳化可能性大的分支程式。

+++++++++++++++++++++

[bob]
其實, 我總結一下上面的話的意思:
if() 語句你照用, 跟以前一樣, 只是 如果你覺得if()是1 的可能性非常大的時候, 就在運算式的外面加一個likely() , 如果可能性非常小(比如幾率非常小),就用unlikely() 包裹上。 
看kernel代碼的時候, 看到很多這樣的例子, 舉一個:
if (likely(cpu == this_cpu)) { //注意likely和unlikely的用法
  //這裡用likely說明,cpu=this_cpu的可能性非常大  
  if (!(clone_flags & CLONE_VM)) {
  /*
  * The VM isn't cloned, so we're in a good position to
  * do child-runs-first in anticipation of an exec. This
  * usually avoids a lot of COW overhead.
  */
  if (unlikely(!current->array))
  __activate_task(p, rq);
  else {
  p->prio = current->prio;
  p->normal_prio = current->normal_prio;
  list_add_tail(&p->run_list, &current->run_list);
  p->array = current->array;
  p->array->nr_active++;
  inc_nr_running(p, rq);
  }
  set_need_resched();
  } else
  /* Run child last */
  __activate_task(p, rq);
  /*
  * We skip the following code due to cpu == this_cpu
  *
  * task_rq_unlock(rq, &flags);
  * this_rq = task_rq_lock(current, &flags);
  */
  this_rq = rq;
  } else {


---

kernel 代碼,有許多看起來多餘的東西,其實不多餘
kernel裡面的代碼, 有的時候看起來,很繁瑣, 冗餘, 但是仔細一看 ,還真的不錯。 
在代碼裡面老能看到 BUG_ON() , WARN_ON() 這樣的宏 , 類似 我們日常編程裡面的斷言(assert) 。 
---> bug.h
QUOTE:
extern void __WARN_ON(const char *func, const char *file, const int line);
#ifdef CONFIG_BUG
#ifndef HAVE_ARCH_BUG
#define BUG() do { /
  printk("BUG: failure at %s:%d/%s()!/n", __FILE__, __LINE__, __FUNCTION__); /
  panic("BUG!"); /
} while (0)
#endif
#ifndef HAVE_ARCH_BUG_ON
#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while(0)
#endif
#ifndef HAVE_ARCH_WARN_ON
#define WARN_ON(condition) do { /
  if (unlikely((condition)!=0)) /
  __WARN_ON(__FUNCTION__, __FILE__, __LINE__); /
} while (0)
#endif
#else /* !CONFIG_BUG */
#ifndef HAVE_ARCH_BUG
#define BUG()
#endif
#ifndef HAVE_ARCH_BUG_ON
#define BUG_ON(condition) do { if (condition) ; } while(0)
#endif
#ifndef HAVE_ARCH_WARN_ON
#define WARN_ON(condition) do { if (condition) ; } while(0)
#endif
#endif
kernel 別的代碼裡面用到例子:
  BUG_ON(unlikely(atomic_read(&(kioctx)->users) 
[Copy to clipboard]

[ - ]
CODE:
#include 
#include 
#define likely(x) __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)
#define BUG_ON(condition) do /
  { if (unlikely((condition)!=0)) /
  printf("BUG: failure at %s:%d/%s()!/n", __FILE__, __LINE__, __FUNCTION__); /
  } while(0)
int main(void)
{
  int i = 7;
  BUG_ON(i!=10);
  return 0;
}
輸出如下: 
BUG: failure at warn.c:18/main()!


 


轉自:http://hi.baidu.com/zkheartboy/blog/item/92cc373f9b90dfe955e72315.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.