【问题标题】:Preemption among SOFTIRQ contextSOFTIRQ 上下文之间的抢占
【发布时间】:2017-08-19 00:48:56
【问题描述】:

我有一个具有以下配置的系统;

  • SMP 平台(但我只关心本地 CPU)和抢占关闭
  • ISR A -> raise_softirq(1)
  • ISR B -> raise_softirq(2)

当 SOFTIRQ 1 运行时,中断 B 出现,然后 ISR B 启动。 当 irq_exit() 发生在 ISR B 时,它将调用 softirq。因此,它将调度 SOFTIRQ 2(不处理被中断的 SOFTIRQ 1)。

这是正确的说法吗?

另一个问题。此时,如果 SOFTIRQ 1 禁用了“bottom_half”,我们在哪里检测到下半部分被禁用并跳过 SOFTIRQ 2 的执行? 提前致谢!

【问题讨论】:

    标签: linux-kernel interrupt-handling


    【解决方案1】:

    您可能混淆了 SOFTIRQ 和 HARDIRQ。 Linux 内核中的 Softirq 是 IRQ 处理中的“bottom_half”,由任务调度器调度执行以处理延迟的 IRQ 处理。在此处理期间,它可能会处理多个延迟 IRQ 处理,例如您的 IRQ A 和 IRQ B。

    但是如果有任何IRQ进入系统,它会触发ISR处理程序,并且不会立即触发任何SOFTIRQ,只是被安排在以后处理,而不是“调用”作为你的措辞说。 (即,所有硬件 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内核得到以下结果(没有来自硬件,它来自“驱动程序”分支):

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

    【讨论】:

      猜你喜欢
      • 2017-05-29
      • 2013-07-10
      • 2012-07-21
      • 1970-01-01
      • 1970-01-01
      • 2018-09-16
      • 2013-11-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多