調度子係統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