sched: fix CPU frequency estimation while idle

CPU cycle counter won't increase when CPU or cluster is idle depending
on hardware.  Thus using cycle counter in that period of time can
result in incorrect CPU frequency estimation.  Use previously calculated
CPU frequency when CPU was idle.

Change-Id: I732b50c974a73c08038995900e008b4e16e9437b
Signed-off-by: Joonwoo Park <joonwoop@codeaurora.org>
This commit is contained in:
Joonwoo Park 2016-04-28 16:41:53 -07:00 committed by Kyle Yan
parent 54c0b0001b
commit 6e8c9ac98d

View file

@ -2702,7 +2702,7 @@ static void update_task_cpu_cycles(struct task_struct *p, int cpu)
static void
update_task_rq_cpu_cycles(struct task_struct *p, struct rq *rq, int event,
u64 wallclock)
u64 wallclock, u64 irqtime)
{
u64 cur_cycles;
int cpu = cpu_of(rq);
@ -2716,13 +2716,23 @@ update_task_rq_cpu_cycles(struct task_struct *p, struct rq *rq, int event,
}
cur_cycles = cpu_cycle_counter_cb.get_cpu_cycle_counter(cpu);
if (unlikely(cur_cycles < p->cpu_cycles))
rq->cc.cycles = cur_cycles + (U64_MAX - p->cpu_cycles);
else
rq->cc.cycles = cur_cycles - p->cpu_cycles;
rq->cc.cycles = rq->cc.cycles * NSEC_PER_MSEC;
rq->cc.time = wallclock - p->ravg.mark_start;
BUG_ON((s64)rq->cc.time < 0);
/*
* If current task is idle task and irqtime == 0 CPU was
* indeed idle and probably its cycle counter was not
* increasing. We still need estimatied CPU frequency
* for IO wait time accounting. Use the previously
* calculated frequency in such a case.
*/
if (!is_idle_task(rq->curr) || irqtime) {
if (unlikely(cur_cycles < p->cpu_cycles))
rq->cc.cycles = cur_cycles + (U64_MAX - p->cpu_cycles);
else
rq->cc.cycles = cur_cycles - p->cpu_cycles;
rq->cc.cycles = rq->cc.cycles * NSEC_PER_MSEC;
rq->cc.time = wallclock - p->ravg.mark_start;
BUG_ON((s64)rq->cc.time < 0);
}
p->cpu_cycles = cur_cycles;
@ -2941,7 +2951,7 @@ update_task_ravg(struct task_struct *p, struct rq *rq, int event,
goto done;
}
update_task_rq_cpu_cycles(p, rq, event, wallclock);
update_task_rq_cpu_cycles(p, rq, event, wallclock, irqtime);
update_task_demand(p, rq, event, wallclock);
update_cpu_busy_time(p, rq, event, wallclock, irqtime);
update_task_pred_demand(rq, p, event);