调度子系统2_核心调度器
// 核心调度器 // 当进程决定让出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)
最后更新:2017-04-03 12:53:45