/* file: kernel/sched/core.c */
void scheduler_tick(void) {
int cpu = smp_processor_id();
struct rq *rq = cpu_rq(cpu);
struct task_struct *curr = rq->curr;
/* 调用当前任务的调度类的 task_tick 方法 */
curr->sched_class->task_tick(rq, curr, 0);
#ifdef CONFIG_SMP
/* SMP 架构下触发负载均衡 */
rq->idle_balance = idle_cpu(cpu);
trigger_load_balance(rq);
#endif
}
/* file: kernel/sched/fair.c */
static void task_tick_fair(struct rq *rq, struct task_struct *curr,
int queued) {
struct cfs_rq *cfs_rq;
struct sched_entity *se = &curr->se;
/* 在不考虑组调度的情况下,此处的循环只会迭代一次,处理的就是当前任务 */
for_each_sched_entity(se) {
cfs_rq = cfs_rq_of(se);
entity_tick(cfs_rq, se, queued);
}
}
/* file: kernel/sched/fair.c */
static void entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr,
int queued)
{
/* 首先更新当前任务及队列的各种时间信息,详见 vruntime 一节 */
update_curr(cfs_rq);
if (cfs_rq->nr_running > 1)
/* 检查是否需要抢占当前任务 */
check_preempt_tick(cfs_rq, curr);
}
该函数的主要任务有两个,一个是更新任务的各种时间信息;另一个是检查当前任务是否已经执行地足够久了,如果是的话就需要对其进行抢占,换其它任务来执行。关于抢占的概念将在下一节中介绍。