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'行之前,因此仍然有可能出现竞争条件。 –

相关问题