Chapter 2: Process Management and Scheduling
static void set_load_weight(struct task_struct *p)
{
if (task_has_rt_policy(p)) {
p->se.load.weight = prio_to_weight[0] * 2;
p->se.load.inv_weight = prio_to_wmult[0] >> 1;
return;
}
/*
* SCHED_IDLE tasks get minimal weight:
*/
if (p->policy == SCHED_IDLE) {
p->se.load.weight = WEIGHT_IDLEPRIO;
p->se.load.inv_weight = WMULT_IDLEPRIO;
return;
}
p->se.load.weight = prio_to_weight[p->static_prio - MAX_RT_PRIO];
p->se.load.inv_weight = prio_to_wmult[p->static_prio - MAX_RT_PRIO];
}
The kernel not only computes the weight itself, but also stores the value required for division. Notice that
allowing 10 percent more CPU time per priority change leads to anexponentialbehavior of the weight
(and the related CPU times), which is illustrated in Figure 2-15. The upper inset in the figure shows the
graph for a restricted region of regular priorities. The lower inset employs a logarithmic scale on they
axis. Note that the function is discontinuous at the transition point from regular to real-time processes.
Recall that not only processes, but also run queues are associated with a load weight. Every time a process
is added to a run queue, the kernel callsinc_nr_running. This not only ensures that the run queue keeps
track of how many processes are running, but also adds the process weight to the weight of the run
queue:
kernel/sched.c
static inline void update_load_add(struct load_weight *lw, unsigned long inc)
{
lw->weight += inc;
}
static inline void inc_load(struct rq *rq, const struct task_struct *p)
{
update_load_add(&rq->load, p->se.load.weight);
}
static void inc_nr_running(struct task_struct *p, struct rq *rq)
{
rq->nr_running++;
inc_load(rq, p);
}
Corresponding functions (dec_nr_running,dec_load,andupdate_load_sub) are called when a process
is removed from the run queue.