The previous code calculates CPU's total utilization with runnable tasks and block tasks. These two variables will be updated separately, so there have chance to get intermediate values for them; for example, in the function enqueue_entity_load_avg() it will wake up one task, it firstly will decrease cfs_rq::utilization_blocked_avg and then increase cfs_rq::utilization_load_avg, but between these two operations there has interval caused by function update_entity_load_avg(). So finally it's easily to get these two value equal zero, even though there have one big workload task on this CPU.
So add one more variable util_total to trace the sum value for CPU's utilization and dismiss intermediate value issue.
Signed-off-by: Leo Yan leo.yan@linaro.org --- kernel/sched/fair.c | 38 +++++++++++++++++++++++++------------- kernel/sched/sched.h | 1 + 2 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index 01bb3f0..6203a20 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2872,7 +2872,10 @@ static inline void update_entity_load_avg(struct sched_entity *se, -utilization_delta); }
- trace_sched_load_avg_cpu(cpu, cfs_rq); + cfs_rq->util_total = cfs_rq->utilization_load_avg + + cfs_rq->utilization_blocked_avg; + + trace_sched_load_avg_cpu(cpu, &cpu_rq(cpu)->cfs); }
/* @@ -2883,6 +2886,7 @@ static void update_cfs_rq_blocked_load(struct cfs_rq *cfs_rq, int force_update) { u64 now = cfs_rq_clock_task(cfs_rq) >> 20; u64 decays; + int cpu = cpu_of(rq_of(cfs_rq));
decays = now - cfs_rq->last_decay; if (!decays && !force_update) @@ -2908,6 +2912,9 @@ static void update_cfs_rq_blocked_load(struct cfs_rq *cfs_rq, int force_update) }
__update_cfs_rq_tg_load_contrib(cfs_rq, force_update); + + cfs_rq->util_total = cfs_rq->utilization_load_avg + + cfs_rq->utilization_blocked_avg; }
/* Add the load generated by se into cfs_rq's child load-average */ @@ -2958,6 +2965,9 @@ static inline void enqueue_entity_load_avg(struct cfs_rq *cfs_rq, cfs_rq->utilization_load_avg += se->avg.utilization_avg_contrib; /* we force update consideration on load-balancer moves */ update_cfs_rq_blocked_load(cfs_rq, !wakeup); + + cfs_rq->util_total = cfs_rq->utilization_load_avg + + cfs_rq->utilization_blocked_avg; }
/* @@ -2969,6 +2979,8 @@ static inline void dequeue_entity_load_avg(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) { + int cpu = cpu_of(rq_of(cfs_rq)); + update_entity_load_avg(se, 1); /* we force update consideration on load-balancer moves */ update_cfs_rq_blocked_load(cfs_rq, !sleep); @@ -2981,6 +2993,9 @@ static inline void dequeue_entity_load_avg(struct cfs_rq *cfs_rq, se->avg.utilization_avg_contrib; se->avg.decay_count = atomic64_read(&cfs_rq->decay_counter); } /* migrations, e.g. sleep=0 leave decay_count == 0 */ + + cfs_rq->util_total = cfs_rq->utilization_load_avg + + cfs_rq->utilization_blocked_avg; }
/* @@ -4891,8 +4906,7 @@ static inline bool energy_aware(void) }
struct energy_env_snapshot { - int util[8]; - int block[8]; + int util_total[8]; };
struct energy_env { @@ -4923,11 +4937,10 @@ struct energy_env { static unsigned long __eas_get_cpu_usage(struct energy_env *eenv, int cpu, int delta) { int sum; - unsigned long usage = eenv->snapshot.util[cpu]; - unsigned long blocked = eenv->snapshot.block[cpu]; + unsigned long util_total = eenv->snapshot.util_total[cpu]; unsigned long capacity_orig = capacity_orig_of(cpu);
- sum = usage + blocked + delta; + sum = util_total + delta;
if (sum < 0) return 0; @@ -5183,13 +5196,9 @@ static int energy_diff(struct energy_env *eenv) sg = sd->groups;
for_each_cpu(i, sched_domain_span(sd)) { - eenv_before.snapshot.util[i] = - cpu_rq(i)->cfs.utilization_load_avg; - eenv_before.snapshot.block[i] = - cpu_rq(i)->cfs.utilization_blocked_avg; - - eenv->snapshot.util[i] = eenv_before.snapshot.util[i]; - eenv->snapshot.block[i] = eenv_before.snapshot.block[i]; + eenv_before.snapshot.util_total[i] = cpu_rq(i)->cfs.util_total; + eenv->snapshot.util_total[i] = + eenv_before.snapshot.util_total[i]; }
do { @@ -8972,6 +8981,9 @@ static void task_move_group_fair(struct task_struct *p, int queued) cfs_rq->blocked_load_avg += se->avg.load_avg_contrib; cfs_rq->utilization_blocked_avg += se->avg.utilization_avg_contrib; + + cfs_rq->util_total = cfs_rq->utilization_load_avg + + cfs_rq->utilization_blocked_avg; #endif } } diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 849b6b5..deb1fae 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -382,6 +382,7 @@ struct cfs_rq { */ unsigned long runnable_load_avg, blocked_load_avg; unsigned long utilization_load_avg, utilization_blocked_avg; + unsigned long util_total; atomic64_t decay_counter; u64 last_decay; atomic_long_t removed_load, removed_utilization; -- 1.9.1