阅读428 返回首页    go 阿里云 go 技术社区[云栖]


调度子系统3_周期调度器

//	周期调度器
//	调用路径: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);
	}
}

最后更新:2017-04-03 12:53:45

  上一篇:go HI3531串口测试程序(arm)
  下一篇:go 百度云和微信账号接入