diff options
| author | Joonwoo Park <joonwoop@codeaurora.org> | 2015-07-02 09:48:33 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 20:02:08 -0700 |
| commit | b1fb594df9371dcfeae484ca71ae23841f9da729 (patch) | |
| tree | b356f99da879cd1ffef1981593d9ad599a3049dc /kernel | |
| parent | a4c475e43db22d2db8bdea676536792cc6b0f724 (diff) | |
sched: fix incorrect prev_runnable_sum accounting with long ISR run
At present, when IRQ handler spans multiple scheduler windows, HMP
scheduler resets the IRQ CPU's prev_runnable_sum with its current max
capacity under the assumption that there is no other possible contribution
to the CPU's prev_runnable_sum. This isn't correct as another CPU can
migrate tasks to the IRQ CPU.
Furthermore such incorrectness can trigger BUG_ON() if the migrated task's
prev_window is larger than migrating CPU's current capacity in following
scenario.
1. ISR on the power efficient CPU has been running for multiple windows.
2. A task which has prev_window higher than IRQ CPU's current capacity
migrated to the IRQ CPU.
3. Servicing IRQ is done and the IRQ CPU resets its prev_runnable_rum =
CPU's current capacity.
4. Before window rollover, the task on the IRQ CPU migrates to other CPU
and fixes up source and destnation CPUs' busy time.
5. BUG_ON(src_rq->prev_runnable_sum < 0) triggers as p->ravg.prev_window
is larger than src_rq->prev_runnable_sum.
Fix such incorrectness by preserving prev_runnable_sum when ISR spans
multiple scheduler windows. There is no need to reset it.
CRs-fixed: 828055
Change-Id: I1f95ece026493e49d3810f9c940ec5f698cc0b81
Signed-off-by: Joonwoo Park <joonwoop@codeaurora.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/sched/core.c | 8 |
1 files changed, 1 insertions, 7 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 6f47fa3dbf41..bdf8b6fe5f27 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -1611,14 +1611,8 @@ static void update_cpu_busy_time(struct task_struct *p, struct rq *rq, /* The IRQ busy time spanned multiple windows. Process the * busy time preceding the current window start first. */ delta = window_start - mark_start; - if (delta > window_size) { + if (delta > window_size) delta = window_size; - /* If there's 1 or more full windows of IRQ busy time - * then the entire prev_runnable_sum will be a window - * of IRQ time - there should be no contribution from - * anything else. */ - rq->prev_runnable_sum = 0; - } delta = scale_exec_time(delta, rq); rq->prev_runnable_sum += delta; |
