菜鳥nginx源碼剖析數據結構篇(十) 自旋鎖ngx_spinlock[轉]

菜鳥nginx源碼剖析數據結構篇(十) 自旋鎖ngx_spinlocknginx

 

  • Author:Echo Chen(陳斌)數據結構

  • Email:chenb19870707@gmail.comapp

  • Blog:Blog.csdn.net/chen19870707函數

  • Date:Nov 11th, 2014ui

              自旋鎖(Spinlock)是一種 Linux 內核中普遍運用的底層同步機制。自旋鎖是一種工做於多處理器環境的特殊的鎖,在單處理環境中自旋鎖的操做被替換爲空操做。當某個處理器上的內核執行線程申請自旋鎖時,若是鎖可用,則得到鎖,而後執行臨界區操做,最後釋放鎖;若是鎖已被佔用,線程並不會轉入睡眠狀態,而是忙等待該鎖,一旦鎖被釋放,則第一個感知此信息的線程將得到鎖。atom

    1.源代碼位置

     

    源文件:http://trac.nginx.org/nginx/browser/nginx/src/core/ngx_spinlock.cspa

     

    2.相關結構定義

    原子鎖結構 ngx_atomic_t:.net

       1: typedef unsigned long               ngx_atomic_uint_t;
       2: typedef volatile ngx_atomic_uint_t  ngx_atomic_t;

    原子鎖值類型 ngx_atomic_int_t:線程

       1: typedef long                        ngx_atomic_int_t;

    原子的比較和交換,若是lock和old相等,則set寫入lockcode

       1: #define ngx_atomic_cmp_set(lock, old, set)                                    \
       2:     __sync_bool_compare_and_swap(lock, old, set)

    說明:

    bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...) 
           type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)

    這兩個函數是GCC提供原子的比較和交換,若是*ptr == oldval,就將newval寫入*ptr。

     

     

    進程主動讓出執行權,ngx_sched_yeld

       1: #define ngx_sched_yield()  sched_yield()

    3.源代碼剖析

       1: void
       2: ngx_spinlock(ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin)
       3: {
       4:  
       5: #if (NGX_HAVE_ATOMIC_OPS)
       6:  
       7:     ngx_uint_t  i, n;
       8:  
       9:  
      10:     for ( ;; ) {
      11:  
      12:         //*lock == 0,沒有上鎖則上鎖,則調用ngx_atomic_cmp_set上鎖,設置*lock=value,而後返回 
      13:         if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) {
      14:             return;
      15:         }
      16:         
      17:         // 多核
      18:         if (ngx_ncpu > 1) {
      19:             
      20:             //若是 spin 爲 80,則第一次等待 1 個 ngx_cpu_pause() 操做,而後再次查看鎖是否可用。接下來每輪分別等待 2個、4 個、8 個、16 個、32 個、64 個 ngx_cpu_pause() 操做後再試。
      21:               //這中間過程當中若是出現鎖被釋放從而能夠使用的狀況,則循環會被停止,spinlock 函數會返回值。若是重試仍沒有成功,則執行 ngx_sched_yield,而後再重複上面的操做。
      22:             for (n = 1; n < spin; n <<= 1) {
      23:  
      24:                 for (i = 0; i < n; i++) {
      25:                     ngx_cpu_pause();
      26:                 }
      27:                 
      28:                 //檢查是否上鎖,若是 *lock == 0,則迅速上鎖返回
      29:                 if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) {
      30:                     return;
      31:                 }
      32:             }
      33:         }
      34:         
      35:         //讓出CPU執行權
      36:         ngx_sched_yield();
      37:     }
      38:  
      39: #else
      40:  
      41: #if (NGX_THREADS)
      42:  
      43: #error ngx_spinlock() or ngx_atomic_cmp_set() are not defined !
      44:  
      45: #endif
      46:  
      47: #endif
      48:  
      49: }

     

  • 4.參考資料

     

    1.http://blog.csdn.net/poechant/article/details/8062969

    2.《深刻理解Nginx》

相關文章
相關標籤/搜索