我确定这是有充分理由的,但我看不出它是什么。里面__handle_irq_event_percpu
内核遍历为特定 IRQ 行注册的所有处理程序并调用它。我不明白的是为什么当到达第一个返回 IRQ_HANDLED
的处理程序时这个循环没有退出?看起来只是一个简单的性能提升,所以肯定有我不明白的地方。
有人知道为什么吗?
最佳答案
在 Linux 源代码树中,__handle_irq_event_percpu() 在 kernel/irq/handle.c 中:
irqreturn_t __handle_irq_event_percpu(struct irq_desc *desc, unsigned int *flags)
{
irqreturn_t retval = IRQ_NONE;
unsigned int irq = desc->irq_data.irq;
struct irqaction *action;
record_irq_time(desc);
for_each_action_of_desc(desc, action) {
irqreturn_t res;
trace_irq_handler_entry(irq, action);
res = action->handler(irq, action->dev_id);
trace_irq_handler_exit(irq, action, res);
if (WARN_ONCE(!irqs_disabled(),"irq %u handler %pS enabled interrupts\n",
irq, action->handler))
local_irq_disable();
switch (res) {
case IRQ_WAKE_THREAD:
/*
* Catch drivers which return WAKE_THREAD but
* did not set up a thread function
*/
if (unlikely(!action->thread_fn)) {
warn_no_thread(irq, action);
break;
}
__irq_wake_thread(desc, action);
/* Fall through - to add to randomness */
case IRQ_HANDLED:
*flags |= action->flags;
break;
default:
break;
}
retval |= res;
}
return retval;
}
for_each_action_of_desc(desc, action) 宏在 IRQ 描述符的 Action 列表中移动:
#define for_each_action_of_desc(desc, act) \
for (act = desc->action; act; act = act->next)
[...]
struct irq_desc {
struct irq_common_data irq_common_data;
struct irq_data irq_data;
unsigned int __percpu *kstat_irqs;
irq_flow_handler_t handle_irq;
struct irqaction *action; /* IRQ action list */
[...]
struct irqaction {
irq_handler_t handler;
void *dev_id;
void __percpu *percpu_dev_id;
struct irqaction *next;
irq_handler_t thread_fn;
struct task_struct *thread;
struct irqaction *secondary;
unsigned int irq;
unsigned int flags;
unsigned long thread_flags;
unsigned long thread_mask;
const char *name;
struct proc_dir_entry *dir;
} ____cacheline_internodealigned_in_smp;
如果中断线路由多个设备共享,则 Action 列表中有多个条目。 因此,多个设备可能同时进入中断状态。因此,将调用所有共享线路的设备以检查是否有事情要做。
注意:
- This answer在这个问题上有更好的论证
- 这blog article描述了 Linux 内核中中断处理的步骤。
关于c - 为什么 Linux 内核不会在返回 IRQ_HANDLED 的共享 IRQ 的第一个处理程序处停止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65093611/