英语

CPU 调度器架构特定代码实现提示

Nick Piggin, 2005

上下文切换

1. 运行队列锁定。默认情况下,调用 switch_to arch 函数时会锁定运行队列。通常这不是问题,除非 switch_to 可能需要获取运行队列锁。这通常是由于上下文切换中的唤醒操作引起的。

要请求调度器在未锁定运行队列的情况下调用 switch_to,必须在头文件中 #define __ARCH_WANT_UNLOCKED_CTXSW(通常是定义 switch_to 的那个头文件)。

在 CONFIG_SMP 情况下,未锁定的上下文切换只会对核心调度器实现引入非常小的性能损失。

CPU 空闲

您的 cpu_idle 例程需要遵守以下规则

  1. 在空闲例程中应禁用抢占。仅应在调用 schedule() 时启用,然后再次禁用。

  2. need_resched/TIF_NEED_RESCHED 仅会被设置,并且在运行的任务调用 schedule() 之前不会被清除。空闲线程只需要查询 need_resched,并且永远不会设置或清除它。

  3. 当 cpu_idle 发现 (need_resched() == 'true') 时,它应该调用 schedule()。否则,它不应该调用 schedule()。

  4. 在检查 need_resched 时,唯一需要禁用中断的情况是,如果我们要使处理器休眠直到下一次中断(这不会提供任何对 need_resched 的保护,它会防止丢失中断)

    4a. 这种类型的睡眠常见问题似乎是

    local_irq_disable();
    if (!need_resched()) {
            local_irq_enable();
            *** resched interrupt arrives here ***
            __asm__("sleep until next interrupt");
    }
    
  5. 当 need_resched 变高时,不需要中断来唤醒它们的空闲例程可以设置 TIF_POLLING_NRFLAG。换句话说,它们必须定期轮询 need_resched,尽管执行一些后台工作或进入低 CPU 优先级可能是合理的。

    • 5a. 如果设置了 TIF_POLLING_NRFLAG,并且我们决定进入中断睡眠,则需要清除它,然后发出内存屏障(然后禁用中断,并按照第 3 点所述测试 need_resched)。

arch/x86/kernel/process.c 包含轮询和睡眠空闲函数的示例。

可能的架构问题

我发现的(并且尝试修复或没有修复的)可能的架构问题

sparc - 此时 IRQ 开启(?),将 local_irq_save 更改为 _disable。
  • TODO:需要辅助 CPU 来禁用抢占(参见 #1)