调度子系统2_核心调度器

来源:互联网 发布:淘宝女装宣传视频 编辑:程序博客网 时间:2024/05/18 21:42
//核心调度器//当进程决定让出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的rqrq = cpu_rq(cpu);//当前rq上正在运行的进程prev = rq->curr;//进程被切换的次数switch_count = &prev->nivcsw;//取消为当前进程运行的hrtimerif (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{//进程出队rqdeactivate_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);} elseraw_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)

0 0
原创粉丝点击