summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorSrivatsa Vaddagiri <vatsa@codeaurora.org>2014-06-13 19:15:29 -0700
committerDavid Keitel <dkeitel@codeaurora.org>2016-03-23 19:59:51 -0700
commitb310ce69b8d8558b958ae3b0215907d56e5215ca (patch)
tree5e431bb232922ee25625d65554f60d74f39874c9 /kernel
parentc4529b59bc9fcf2dd01d1689aa6c7f4794caa969 (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.c30
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 -=