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