CPU 调度器架构特定代码实现提示¶
Nick Piggin, 2005
上下文切换¶
1. 运行队列锁:默认情况下,`switch_to` 架构函数在持有运行队列锁的情况下被调用。 通常这不是问题,除非 `switch_to` 可能需要获取运行队列锁。这通常是由于上下文切换中的唤醒操作引起的。
要请求调度器在不持有运行队列锁的情况下调用 `switch_to`,您必须在一个头文件中 `#define __ARCH_WANT_UNLOCKED_CTXSW`(通常是在定义 `switch_to` 的头文件中)。
在 CONFIG_SMP 的情况下,解锁的上下文切换只会给核心调度器实现带来非常小的性能损失。
CPU 空闲¶
您的 cpu_idle 例程需要遵守以下规则
应该在空闲例程中禁用抢占。 应该只启用它来调用 schedule(),然后再次禁用。
need_resched/TIF_NEED_RESCHED 只能被设置,直到运行的任务调用 schedule() 之前不会被清除。 空闲线程只需要查询 need_resched,永远不能设置或清除它。
当 cpu_idle 发现 (need_resched() == 'true') 时,它应该调用 schedule()。 否则,它不应该调用 schedule()。
只有当我们即将睡眠处理器直到下一次中断时,才需要在检查 need_resched 时禁用中断(这不会对 need_resched 提供任何保护,它会阻止丢失中断)
4a. 这种类型的睡眠的常见问题似乎是
local_irq_disable(); if (!need_resched()) { local_irq_enable(); *** resched interrupt arrives here *** __asm__("sleep until next interrupt"); }
当 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)