diff options
| author | Srivatsa Vaddagiri <vatsa@codeaurora.org> | 2014-06-13 19:15:29 -0700 |
|---|---|---|
| committer | David Keitel <dkeitel@codeaurora.org> | 2016-03-23 19:59:51 -0700 |
| commit | b310ce69b8d8558b958ae3b0215907d56e5215ca (patch) | |
| tree | 5e431bb232922ee25625d65554f60d74f39874c9 /kernel | |
| parent | c4529b59bc9fcf2dd01d1689aa6c7f4794caa969 (diff) | |
sched: fix up task load during migration
Fix the hack to set task's on_rq to 0 during task migration. Task's
load is temporarily added back to its runqueue so that
update_task_ravg() can fixup task's load when its demand is changing.
Task's load is removed immediately afterwards.
Temporarily setting p->on_rq to 0 introduces a race condition with
try_to_wake_up(). Another task (task A) may be attempting to wake
up the migrating task (task B). As long as task A sees task B's
p->on_rq as 1, the wake up will not continue. Changing p->on_rq to
0, then back to 1, allows task A to continue "waking" task B, at
which point we have both try_to_wake_up and the migration code
attempting to set the cpu of task B at the same time.
CRs-Fixed: 695071
Change-Id: I525745f144da4ffeba1d539890b4d46720ec3ef1
Signed-off-by: Srivatsa Vaddagiri <vatsa@codeaurora.org>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/sched/core.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index f7288a445975..65d61686ea84 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2022,7 +2022,6 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu) if (p->on_rq || p->state == TASK_WAKING) { struct rq *src_rq = task_rq(p); struct rq *dest_rq = cpu_rq(new_cpu); - int old_onrq; u64 wallclock; if (p->state == TASK_WAKING) @@ -2036,13 +2035,32 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu) update_task_ravg(dest_rq->curr, dest_rq, TASK_UPDATE, wallclock, NULL); - /* In the wakeup case the task has already had - * its statisics updated (and the RQ is not locked). */ - old_onrq = p->on_rq; - p->on_rq = 0; /* todo */ + /* + * In case of migration of task on runqueue, on_rq =1, + * however its load is removed from its runqueue. + * update_task_ravg() below can update its demand, which + * will require its load on runqueue to be adjusted to + * reflect new demand. Restore load temporarily for such + * task on its runqueue + */ + if (p->on_rq) { + inc_cumulative_runnable_avg(src_rq, p); + if (p->sched_class == &fair_sched_class) + inc_nr_big_small_task(src_rq, p); + } + update_task_ravg(p, task_rq(p), TASK_MIGRATE, wallclock, NULL); - p->on_rq = old_onrq; /* todo */ + + /* + * Remove task's load from rq as its now migrating to + * another cpu. + */ + if (p->on_rq) { + dec_cumulative_runnable_avg(src_rq, p); + if (p->sched_class == &fair_sched_class) + dec_nr_big_small_task(src_rq, p); + } if (p->ravg.sum) { src_rq->curr_runnable_sum -= |
