c - 为什么 Linux 内核不会在返回 IRQ_HANDLED 的共享 IRQ 的第一个处理程序处停止?

标签 c linux-kernel interrupt interrupt-handling irq

我确定这是有充分理由的,但我看不出它是什么。里面__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 列表中有多个条目。 因此,多个设备可能同时进入中断状态。因此,将调用所有共享线路的设备以检查是否有事情要做。

注意:

关于c - 为什么 Linux 内核不会在返回 IRQ_HANDLED 的共享 IRQ 的第一个处理程序处停止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65093611/

相关文章:

c - 处理数组中的 free 的简单方法

C 计算txt文件一行中的字符数

linux - Linux 中的 cakephp 热插拔驱动程序是否与 Windows 中的设备禁用/启用功能相同?

C Pthreads 问题,无法传递我想要的信息?

将 char c = 'a' 转换为 int value = 10

c - 奇怪的 printk 对 linux 堆栈大小测试的影响

linux - 在启动时启用动态调试

c - 在 vector、SEI 和 intflags 仍然设置后中断停止执行。 (AtMega4809)

python - 如何在不终止解释器的情况下中断 native 扩展代码?

c++ - 如何正确处理音频中断?