// 核心调度器
// 当进程决定让出cpu时调用
// 函数任务:
// 1.禁止内核抢占
// 2.获取本cpu的rq
// 3.取消为当前进程运行的hrtimer
// 4.获取队列锁
// 5.更新队列时钟
// 6.清除当前进程need resched标志
// 7.如果当前进程为非运行状态,并且当前非内核抢占路径
// 7.1 如果当前进程有信号待处理,设置当前进程为就绪状态
// 7.2 否则进程出队rq
// 8.如果当前rq没有可运行进程
// 8.1 通过load balance从其他进程搬进程
// 9.通知调度器类用另一个进程代替当前进程
// 10.通知调度器类选择下一个可运行进程
// 11.如果下一个运行的进程非当前进程
// 11.1 执行进程切换
// 12.否则释放队列锁
// 13.开启内核抢占
// 14.如果当前进程被设置need resched,重复1
1.1 asmlinkage void __sched schedule(void)
{
struct task_struct *prev, *next;
unsigned long *switch_count;
struct rq *rq;
int cpu;
need_resched:
//禁止抢占
preempt_disable();
cpu = smp_processor_id();
//本cpu的rq
rq = cpu_rq(cpu);
//当前rq上正在运行的进程
prev = rq->curr;
//进程被切换的次数
switch_count = &prev->nivcsw;
//取消为当前进程运行的hrtimer
if (sched_feat(HRTICK))
hrtick_clear(rq);
//获取队列锁
raw_spin_lock_irq(&rq->lock);
//更新队列时钟
update_rq_clock(rq);
//清除当前进程need resched标志
clear_tsk_need_resched(prev);
//当前进程非运行状态,并且非内核抢占
if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) {
//当前进程有信号待处理,设置进程为运行态
if (unlikely(signal_pending_state(prev->state, prev)))
{
prev->state = TASK_RUNNING;
}
else
{ //进程出队rq
deactivate_task(rq, prev, 1);
}
switch_count = &prev->nvcsw;
}
//通知调度器类,即将发生进程切换
pre_schedule(rq, prev);
//当前rq没有可运行进程,通过loadbalance从其他cpu的rq搬进程过来
if (unlikely(!rq->nr_running))
idle_balance(cpu, rq);
//通知调度器类用另一个进程代替当前进程
put_prev_task(rq, prev);
//通知调度器类选择下一个可运行进程
next = pick_next_task(rq);
//切换当前进程
if (likely(prev != next)) {
//统计rq切换次数
rq->nr_switches++;
rq->curr = next;
++*switch_count;
//切换进程上下文
context_switch(rq, prev, next);
//现在已经是另一个进程在运行
cpu = smp_processor_id();
rq = cpu_rq(cpu);
} else
raw_spin_unlock_irq(&rq->lock);
//通知调度器类,完成了进程切换
post_schedule(rq);
//开启内核抢占
preempt_enable_no_resched();
//如果当前进程需要切换,则再次切换
if (need_resched())
goto need_resched;
}
// 通知调度器类,即将进程切换
2.1 static inline void pre_schedule(struct rq *rq, struct task_struct *prev)
{
if (prev->sched_class->pre_schedule)
prev->sched_class->pre_schedule(rq, prev);
}
// 通知调度器,完成了进程切换
2.2 static inline void post_schedule(struct rq *rq)
{
if (rq->post_schedule) {
unsigned long flags;
//获取队列锁
raw_spin_lock_irqsave(&rq->lock, flags);
if (rq->curr->sched_class->post_schedule)
rq->curr->sched_class->post_schedule(rq);
raw_spin_unlock_irqrestore(&rq->lock, flags);
rq->post_schedule = 0;
}
}
// 通知调度器类,用另一个进程替换当前进程
3.1 static void put_prev_task(struct rq *rq, struct task_struct *prev)
{
....
prev->sched_class->put_prev_task(rq, prev);
}
// 通知调度器类,选择下一个运行的进程
4.1 static inline struct task_struct *pick_next_task(struct rq *rq)
{
const struct sched_class *class;
struct task_struct *p;
//如果rq中进程数等于cfs中进程数,说明没有rt进程,由cfs选出下一个运行的进程
if (likely(rq->nr_running == rq->cfs.nr_running)) {
p = fair_sched_class.pick_next_task(rq);
if (likely(p))
return p;
}
//否则由最高优先级的调度类
class = sched_class_highest;
for ( ; ; ) {
//选择下一个运行进程
p = class->pick_next_task(rq);
if (p)
return p;
//下一个优先级的调度类
class = class->next;
}
}
// 最高优先级调度器类
4.2 #define sched_class_highest (&rt_sched_class)
调度子系统2_核心调度器
最新推荐文章于 2024-03-09 20:40:20 发布