【问题标题】:Can ISRs migrate to other CPUs when preempted?ISR 在被抢占时可以迁移到其他 CPU 吗?
【发布时间】:2011-05-19 12:46:09
【问题描述】:
在旧版本的 Linux 内核中,SMP 系统中硬件 IRQ 的中断服务例程 (ISR) 从头到尾在它们开始的 CPU 上执行。如果被其他代码抢占,ISR 将随后在同一个 CPU 上恢复。
但是在最近的内核中,大多数 ISR 应该默认在特殊内核线程的上下文中执行 (http://lwn.net/Articles/433854/)。 “普通”内核线程在被抢占时可以迁移到另一个 CPU。所以问题是,无论出于何种原因,ISR 现在也可以做这些事情吗?
请注意,我不是在谈论 IRQ 的 CPU 亲和力和处理器之间的 IRQ 平衡。我很好奇中断处理程序已经在运行但被抢占的情况。
也就是说,假设一个 ISR 已经开始在 CPU #1 上执行。现在它被一些更高优先级的代码抢占了。当后者完成其工作时,ISR 恢复执行 - 但在 CPU #2 上。这种情况可能吗?
始终欢迎提供相关文档、讨论等的指针。
【问题讨论】:
标签:
linux-kernel
linux-device-driver
【解决方案1】:
ISR 线程与 ISR 例程具有相同的亲和性,因此在抢占的情况下,ISR 线程不会重新调度到任意 CPU。
此外,根据您提供的链接中的信息,默认情况下不启用强制 ISR 成为线程的行为。它由 threadirqs 命令行选项决定。命令行选项的处理以传统 ISR 不需要关心重新调度的方式处理 ISR 线程。根据 kernel/irq/manage.c 中的以下代码,这些线程禁用了抢占:
/*
* Interrupts which are not explicitely requested as threaded
* interrupts rely on the implicit bh/preempt disable of the hard irq
* context. So we need to disable bh here to avoid deadlocks and other
* side effects.
*/
static void
irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action)
{
local_bh_disable();
action->thread_fn(action->irq, action->dev_id);
irq_finalize_oneshot(desc, action, false);
local_bh_enable();
}