SOFTIRQ 上下文中的抢占

Preemption among SOFTIRQ context

我的系统配置如下;

当 SOFTIRQ 1 为 运行 时,中断 B 到来,然后 ISR B 启动。 当 irq_exit() 发生在 ISR B 时,它会调用 softirq。因此,它将安排 SOFTIRQ 2(不处理被中断的 SOFTIRQ 1)。

这个说法正确吗?

另一个问题。此时,如果 SOFTIRQ 1 禁用 "bottom_half",我们检测 bottom half 的地方被禁用并跳过 SOFTIRQ 2 的执行? 提前致谢!

也许你混淆了SOFTIRQ和HARDIRQ。 Linux内核中的Softirq是IRQ处理中的"bottom_half",由任务调度器调度执行以处理延迟的IRQ处理。并且在此处理过程中,它可以潜在地处理多个延迟 IRQ 处理,例如您的情况下的 IRQ A 和 IRQ B。

但是如果有任何IRQ进入系统,它会触发ISR handler,并没有立即触发任何SOFTIRQ,只是被安排在以后处理,而不是"invoke" 正如你的措辞所说。 (即,所有硬件 IRQ 处理程序都不应该调用 raise_softirq(),而是安排一个处理程序来处理 IRQ)

总而言之,对于您的场景:

ISR B 结束后,它可能会提交 SOFTIRQ B 供以后处理 - 但它不会调用 raise_softirq()。但是由于SOFTIRQ A在中途被拦截,任何硬件中断后它都会继续之前的最后任务,所以SOFTIRQ A会执行到完成。

详述raise_softirq()内部,调用raise_softirq_irqoff():

inline void raise_softirq_irqoff(unsigned int nr)
{
        __raise_softirq_irqoff(nr);

        /*
         * If we're in an interrupt or softirq, we're done
         * (this also catches softirq-disabled code). We will
         * actually run the softirq once we return from
         * the irq or softirq.
         *
         * Otherwise we wake up ksoftirqd to make sure we
         * schedule the softirq soon.
         */ 
        if (!in_interrupt())
                wakeup_softirqd();
}

正如评论所说,如果你在 softirq A 中并且 IRQ B 进来,IRQ B 处理将结束 - 在完成当前 SOFTIRQ A 后重新运行。

为了强调并非所有硬件都调用"raise_softirq()",搜索linux内核得到以下结果(none来自硬件,来自"drivers"分支):

并且在网络 IRQ 处理程序中 - napi_schedule() 被调用。 (通常在所有驱动程序 IRQ 处理程序中搜索 "sched")。以下来自drivers/net/usb/r8152.c: