3

假設有一個端口映射I/O設備,它在IRQ線上任意生成中斷。該器件的待處理中斷可以通過一個調用特定寄存器的outb來清除。Linux IRQ處理程序中的固有爭用條件

此外,假設後續的中斷處理程序是通過request_irq分配給相關的IRQ線:

irqreturn_t handler(int irq, void *data) 
{ 
     /* clear pending IRQ on device */ 
     outb(0, CLEAR_IRQ_REGISTER_ADDR); 

     /* device may generate another IRQ at this point, 
     * but this handler function has not yet returned */ 

     /* signal kernel that IRQ has been handled */ 
     return IRQ_HANDLED; 
} 

是否有這個IRQ處理程序中固有的競爭條件?例如,如果設備在「清除IRQ」outb呼叫之後但在handler函數返回IRQ_HANDLED之前生成另一箇中斷,會發生什麼情況?

我能想到的三種情形:

  1. IRQ線凍結,不能再是由於設備和Linux內核之間的僵局處理。
  2. Linux內核在返回後立即再次執行handler,以處理第二個中斷。
  3. Linux內核中斷handler第二次調用handler

回答

5

情況2是正確的。中斷處理程序在本地CPU上禁用中斷的情況下運行。所以從你的處理程序返回後,中斷控制器會看到另一箇中斷髮生,你的處理程序將再次被調用。

雖然可能發生的情況是,如果您的速度不夠快,並且您仍在處理第一個中斷時發生多箇中斷,您可能會錯過一些中斷。這不應該發生在你的情況下,因爲你必須清除掛起的中斷。

Andy的回答是關於另一個問題。您最終必須鎖定對設備和資源的訪問權限,因爲您的處理程序可以在不同的CPU上同時運行。

+0

假設我返回'IRQ_NONE'而不是'IRQ_HANDLED':處理程序是否仍會被再次調用,或者這種情況會導致死鎖? –

+1

如果不共享或共享,並且所有處理程序都返回'IRQ_NONE',則它將被再次調用,但可能會被虛假的IRQ處理邏輯禁用一段時間。 –

1

在SMP系統上顯然有可能進行比賽。因爲其中大多數中斷實現LAPIC控制器,所以CPU的中斷是本地的。因此,您必須通過關鍵部分同步算法來保護您的數據和設備訪問。由於中斷上下文大多數適合在這裏是spin_lock_irqsave()

+0

你是說第3種情況的結果是:在第一次調用返回之前,對處理程序的初始調用被同一處理程序的第二次調用中斷? –

+0

[這個問題](http://stackoverflow.com/questions/2559602/spin-lock-irqsave-vs-spin-lock-irq)關於'spin_lock_irq'和'spin_lock_irqsave'幫助我理解了這個話題。 – izzy

+0

@izzy對不起,我沒有完全遵循。我擔心在IRQ處理函數內執行完所有I/O操作後發生死鎖*因此我不相信一個自旋鎖可以解決這個問題,因爲它們只能在'處理函數'的範圍內。換句話說:'spin_unlock_irq'調用本來就會發生在'return IRQ_HANDLED'行之前,因此仍然有可能出現競爭條件。 –

相關問題