天天看點

spin_lock與spin_lock_irqsaveq差別

個人總結:

中斷上下文,即由中斷引發的中斷處理函數的執行過程,由于不是線程,沒有tast_struct記錄它的狀态,是以是不可重入的,是以一旦這個上下文被中斷打斷,無法恢複。是以如果要用spin lock,一定要使用spin_lock_irqsave的禁止中斷的版本。

而線程環境,由于有task_struct記錄所有資源,以及執行記錄,是以是可以被中斷的。

假如上述二者情況在同一個CPU,如果使用的是同一個spin lock,而線程環境在擷取spin lock之後被中斷,則中斷上下文使用禁中斷的方式一直去擷取spin lock,會卡死該CPU。

轉自:http://blog.csdn.net/zhanglei4214/article/details/6837697

在Linux核心中何時使用spin_lock,何時使用spin_lock_irqsave很容易混淆。首先看一下代碼是如何實作的。

spin_lock的調用關系

     spin_lock 

            |

           + ----->  raw_spin_lock 

|

+------>  _raw_spin_lock

                         |

                        +--------> __raw_spin_lock

[cpp]  view plain copy

  1. static inline void __raw_spin_lock(raw_spinlock_t *lock)  
  2. {  
  3.         preempt_disable();  
  4.         spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);  
  5.         LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);  
  6. }  

spin_lock_irq的調用關系

    spin_lock_irq

                |

               +-------> raw_spin_lock_irq

                                           |

                                          +---------> _raw_spin_lock_irq

                                                                      |

                                                                      +------------> __raw_spin_lock_irq

[cpp]  view plain copy

  1. static inline void __raw_spin_lock_irq(raw_spinlock_t *lock)  
  2. {  
  3.         local_irq_disable();  
  4.         preempt_disable();  
  5.         spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);  
  6.         LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);  
  7. }  

可以看出來他們兩者隻有一個差别:是否調用local_irq_disable()函數, 即是否禁止本地中斷。

在任何情況下使用spin_lock_irq都是安全的。因為它既禁止本地中斷,又禁止核心搶占。

spin_lock比spin_lock_irq速度快,但是它并不是任何情況下都是安全的。

舉個例子:程序A中調用了spin_lock(&lock)然後進入臨界區,此時來了一個中斷(interrupt),

該中斷也運作在和程序A相同的CPU上,并且在該中斷處理程式中恰巧也會spin_lock(&lock)

試圖擷取同一個鎖。由于是在同一個CPU上被中斷,程序A會被設定為TASK_INTERRUPT狀态,

中斷處理程式無法獲得鎖,會不停的忙等,由于程序A被設定為中斷狀态,schedule()程序排程就

無法再排程程序A運作,這樣就導緻了死鎖!

但是如果該中斷處理程式運作在不同的CPU上就不會觸發死鎖。 因為在不同的CPU上出現中斷不會導緻

程序A的狀态被設為TASK_INTERRUPT,隻是換出。當中斷處理程式忙等被換出後,程序A還是有機會

獲得CPU,執行并退出臨界區。

是以在使用spin_lock時要明确知道該鎖不會在中斷處理程式中使用。