为什么我们需要在ARM Linux cpu_idle中的WFI之前禁用中断

时间:2014-04-26 02:34:37

标签: linux kernel interrupt

ARM的Linux内核基本上在循环中执行CPU_idle:

while (1) {
    disalbe_irq
    wfi
    enable_irq
}

我可以理解这个逻辑是有效的,因为“wfi”会唤醒ARM而不管IRQ / FIQ状态如何。但是,为什么“wfi”必须首先被disable_irq和eanble_irq括起来?

源代码/arch/arm/process.c有以下表彰:

* We need to disable interrupts here
* to ensure we don't miss a wakeup call.

但我无法理解它。有人可以告诉我在哪种情况下我们会错过唤醒电话吗?

2 个答案:

答案 0 :(得分:3)

主循环中的整个“进入睡眠”序列分为两个步骤:

  1. 意识到你没有工作要做;
  2. 尝试睡觉(即WFI)
  3. 如果仍然设置了一些中断标志,WFI指令将充当NOP,这允许主循环返回运行所需的任务。到目前为止一切都很好。

    如果在步骤1之后和步骤2之前发生中断,则会出现问题。如果发生这种情况,则退出ISR时中断标志将被清除,当控制返回主循环时,它将触发WFI指令清除所有中断标志,导致CPU在主循环有机会执行ISR所需的任何任务之前进入休眠状态。

答案 1 :(得分:0)

<< Cortex-A系列程序员指南>>:

  

ARM建议使用数据同步屏障(DSB)指令   在WFI或WFE之前,确保在更改状态之前完成挂起的内存事务。

如果启用了中断,我们可能会看到:

DSB
interrupt handler
WFI

但是我们不能假设在中断处理程序之后我们不需要DSB。所以,我们需要禁用中断。