《CPU调度器实现提示:针对特定体系结构代码》
Nick Piggin,2005
上下文切换
- 运行队列锁定 默认情况下,调用switch_to体系结构函数时会锁定运行队列。除非switch_to需要获取运行队列锁,否则通常不会出现问题。这通常是由上下文切换中的唤醒操作引起的。请参阅arch/ia64/include/asm/switch_to.h以获取示例。
要求调度器在运行队列未锁定的情况下调用switch_to,您必须在头文件中(通常是定义switch_to的文件)使用#define __ARCH_WANT_UNLOCKED_CTXSW。
在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"); }
- TIF_POLLING_NRFLAG可以由不需要中断唤醒的空闲例程设置,当need_resched变为高时。换句话说,它们必须定期轮询need_resched,尽管可能合理地进行一些后台工作或进入低CPU优先级。
5a. 如果设置了TIF_POLLING_NRFLAG,并且我们决定进入中断休眠,那么需要清除它,然后发出内存屏障(随后需要禁用中断进行need_resched的测试,如第3点所述)。
arch/x86/kernel/process.c中有轮询和休眠空闲函数的示例。
可能的体系结构问题
我发现的可能的体系结构问题(尝试修复或未修复):
ia64 - safe_halt调用与中断存在竞争条件吗?(它会休眠吗?)(见#4a)
sparc - 此时是否开启IRQ?将local_irq_save更改为_disable。
TODO:需要辅助CPU来禁用抢占(见#1)