// 週期調度器
// 調用路徑:update_process_times->scheduler_tick
// 函數任務:
// 1.更新rq的clock
// 2.更新隊列負載
// 3.通知調度器類更新進程運行時間
// 4.更新下一次load balance的時間戳
// 5.觸發load balance
1.1 void scheduler_tick(void)
{
int cpu = smp_processor_id();
struct rq *rq = cpu_rq(cpu);
//當前運行的進程
struct task_struct *curr = rq->curr;
raw_spin_lock(&rq->lock);
//更新rq的clock
update_rq_clock(rq);
//更新隊列負載
update_cpu_load_active(rq);
//更新進程的運行時間
curr->sched_class->task_tick(rq, curr, 0);
raw_spin_unlock(&rq->lock);
#ifdef CONFIG_SMP
//更新下一次load balance的時間戳
rq->idle_balance = idle_cpu(cpu);
//觸發load balance軟中斷
trigger_load_balance(rq, cpu);
#endif
}
// 更新隊列負載(rq->cpu_load[])
// 每scheduler tick(TICK_NSEC)被調用一次
// 函數任務:
// 1.更新rq負載
// 1.1 通過CPU_LOAD_IDX_MAX個項記錄rq的歷史負載信息
// 1.2 更新方法
// cpu_load[0] = load.weight
// cpu_load[1] = (cpu_load[1] + load.weight)/2
// cpu_load[2] = (cpu_load[2]*3 + load.weight)/4
// cpu_load[3] = (cpu_load[2]*7 + load.weight)/8
// 2.如果當前時間到達計算cpu負載的時間點
// 2.1 更新下一次計算cpu負載的時間點
// 2.2 計算cpu負載
// 調用路徑:scheduler_tick->update_cpu_load
2.1 static void update_cpu_load(struct rq *this_rq)
{
//rq中所有se負載的總和
unsigned long this_load = this_rq->load.weight;
int i, scale;
this_rq->nr_load_updates++;
//通過CPU_LOAD_IDX_MAX個項記錄rq的歷史負載信息
for (i = 0, scale = 1; i < CPU_LOAD_IDX_MAX; i++, scale += scale) {
unsigned long old_load, new_load;
old_load = this_rq->cpu_load[i];
//rq中所有se的load.weight之和
new_load = this_load;
if (new_load > old_load)
new_load += scale-1;
//cpu_load[0] = load.weight
//cpu_load[1] = (cpu_load[1] + load.weight)/2
//cpu_load[2] = (cpu_load[2]*3 + load.weight)/4
//cpu_load[3] = (cpu_load[2]*7 + load.weight)/8
//....
this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) >> i;
}
//到達計算cpu負載的時間點
if (time_after_eq(jiffies, this_rq->calc_load_update)) {
//更新下一次計算cpu負載的時間點
this_rq->calc_load_update += LOAD_FREQ;
//計算系統負載
calc_load_account_active(this_rq);
}
}
// 計算系統負載
// 系統負載考慮就緒狀態進程和不可中斷睡眠的進程(I/O)進程
// 調用路徑:update_cpu_load->calc_load_account_active
2.2 static void calc_load_account_active(struct rq *this_rq)
{
long nr_active, delta;
nr_active = this_rq->nr_running; //就緒狀態的進程
nr_active += (long) this_rq->nr_uninterruptible; //不可中斷睡眠的進程
if (nr_active != this_rq->calc_load_active) {
delta = nr_active - this_rq->calc_load_active;
this_rq->calc_load_active = nr_active;
atomic_long_add(delta, &calc_load_tasks);
}
}
調度子系統3_週期調度器
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.