Linux IRQ 处理程序中的固有竞争条件
Inherent race condition in Linux IRQ handlers
假设有一个端口映射 I/O 设备在 IRQ 线上任意生成中断。可以通过对特定寄存器的单个 outb
调用来清除设备的未决中断。
此外,假设后续中断处理程序通过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 处理程序中是否存在固有的竞争条件?例如,如果设备在 "clear IRQ" outb
调用之后但在 handler
函数 returns IRQ_HANDLED
之前生成另一个中断,会发生什么情况?
我能想到三种情况:
- 由于设备和 Linux 内核之间的死锁,IRQ 线冻结并且无法再处理。
- Linux 内核在 return 之后立即再次执行
handler
,以处理第二个中断。
- Linux 内核中断
handler
第二次调用 handler
.
在 SMP 系统上显然有可能进行比赛。中断是 CPU 的本地中断,因为它们中的大多数都实现了 LAPIC 控制器。因此,您必须通过临界区同步算法来保护您的数据和设备访问。由于中断上下文,这里最合适的是 spin_lock_irqsave()
.
情况 2 是正确的。中断处理程序是 运行 在本地 CPU 上禁用的中断。因此,从您的处理程序返回后,中断控制器将看到另一个中断发生,您的处理程序将再次被调用。
但可能会发生的情况是,如果您的速度不够快,您可能会错过一些中断,并且在您仍在处理第一个中断时会发生多个中断。这不应该发生在你的情况下,因为你必须清除挂起的中断。
安迪的回答是关于另一个问题的。您肯定必须锁定对您的设备和资源的访问,因为您的处理程序可能 运行 同时在不同的 CPU 上。
假设有一个端口映射 I/O 设备在 IRQ 线上任意生成中断。可以通过对特定寄存器的单个 outb
调用来清除设备的未决中断。
此外,假设后续中断处理程序通过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 处理程序中是否存在固有的竞争条件?例如,如果设备在 "clear IRQ" outb
调用之后但在 handler
函数 returns IRQ_HANDLED
之前生成另一个中断,会发生什么情况?
我能想到三种情况:
- 由于设备和 Linux 内核之间的死锁,IRQ 线冻结并且无法再处理。
- Linux 内核在 return 之后立即再次执行
handler
,以处理第二个中断。 - Linux 内核中断
handler
第二次调用handler
.
在 SMP 系统上显然有可能进行比赛。中断是 CPU 的本地中断,因为它们中的大多数都实现了 LAPIC 控制器。因此,您必须通过临界区同步算法来保护您的数据和设备访问。由于中断上下文,这里最合适的是 spin_lock_irqsave()
.
情况 2 是正确的。中断处理程序是 运行 在本地 CPU 上禁用的中断。因此,从您的处理程序返回后,中断控制器将看到另一个中断发生,您的处理程序将再次被调用。
但可能会发生的情况是,如果您的速度不够快,您可能会错过一些中断,并且在您仍在处理第一个中断时会发生多个中断。这不应该发生在你的情况下,因为你必须清除挂起的中断。
安迪的回答是关于另一个问题的。您肯定必须锁定对您的设备和资源的访问,因为您的处理程序可能 运行 同时在不同的 CPU 上。