注: 内核版本4.0
4. vruntime 的计算
时钟中断产生后会调用update_process_times()
-
/*
-
* Called from the timer interrupt handler to charge one tick to the current
-
* process. user_tick is 1 if the tick is user time, 0 for system.
-
*/
-
void update_process_times(int user_tick)
-
{
-
struct task_struct *p = current;
-
-
/* Note: this timer irq context must be accounted for as well. */
-
account_process_tick(p, user_tick);
-
run_local_timers();
-
rcu_check_callbacks(user_tick);
-
#ifdef CONFIG_IRQ_WORK
-
if (in_irq())
-
irq_work_tick();
-
#endif
-
scheduler_tick();
-
run_posix_cpu_timers(p);
-
}
在 scheduler_tick() 中有 curr->sched_class->task_tick(rq, curr, 0), 将调用 task_tick_fair(), 后者又调用 entity_tick(). 在 entity_tick() 中调用 update_curr() 和 check_preempt_tick().
可以看出 vruntime 的增量由 calc_delta_fair()计算, 这个函数的实现用到了一些移位操作, 但从函数前的注释可以看出其返回 delta * weight / lw.weight. 其中 weight 是当前进程的权重, lw.weight 是整个就绪队列总权重.
-
/*
-
* Update the current task's runtime statistics.
-
*/
-
static void update_curr(struct cfs_rq *cfs_rq)
-
{
-
…
-
delta_exec = now - curr->exec_start;
-
…
-
curr->sum_exec_runtime += delta_exec;/* 增加累计运行时间 */
-
…
-
curr->vruntime += calc_delta_fair(delta_exec, curr);
-
update_min_vruntime(cfs_rq);
-
…
-
}
进程的权重 weight 由进程优先级 prio 决定, 实时进程的 prio 值是 [0, 99], 一般进程是 [100, 139], 对应 nice 值 [-20, 19].
prio 到 weight 的转换使用这张表:
-
/*
-
* Nice levels are multiplicative, with a gentle 10% change for every
-
* nice level changed. I.e. when a CPU-bound task goes from nice 0 to
-
* nice 1, it will get ~10% less CPU time than another CPU-bound task
-
* that remained on nice 0.
-
*
-
* The "10% effect" is relative and cumulative: from _any_ nice level,
-
* if you go up 1 level, it's -10% CPU usage, if you go down 1 level
-
* it's +10% CPU usage. (to achieve that we use a multiplier of 1.25.
-
* If a task goes up by ~10% and another task goes down by ~10% then
-
* the relative distance between them is ~25%.)
-
*/
-
static const int prio_to_weight[40] = {
-
/* -20 */ 88761, 71755, 56483, 46273, 36291,
-
/* -15 */ 29154, 23254, 18705, 14949, 11916,
-
/* -10 */ 9548, 7620, 6100, 4904, 3906,
-
/* -5 */ 3121, 2501, 1991, 1586, 1277,
-
/* 0 */ 1024, 820, 655, 526, 423,
-
/* 5 */ 335, 272, 215, 172, 137,
-
/* 10 */ 110, 87, 70, 56, 45,
-
/* 15 */ 36, 29, 23, 18, 15,
-
};
在 check_preempt_tick()中会比较 delta 和 ideal_runtime, delta 超过 ideal_runtime 的话就对当前进程设置重调度位.
阅读(437) | 评论(0) | 转发(0) |