On 10/11/15 09:58, Leo Yan wrote:
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.
This shouldn't be necessary any more in EAS RFC 5.1/5.2 with the PELT rewrite. We still have cfs_rq->avg.util_avg and cfs_rq->removed_util_avg though so the former one isn't always up to date (e.g. in case of task migrations and dying tasks).
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;
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.