英语

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

Nick Piggin, 2005

上下文切换

1. 运行队列锁:默认情况下,`switch_to` 架构函数在持有运行队列锁的情况下被调用。 通常这不是问题,除非 `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,并且我们确实决定进入中断睡眠,则需要清除它,然后发出内存屏障(然后禁用中断测试 need_resched,如 3 中所述)。

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

可能的 arch/ 问题

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

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