Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 955b16f3 authored by Srivatsa Vaddagiri's avatar Srivatsa Vaddagiri Committed by Steve Muckle
Browse files

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: default avatarSrivatsa Vaddagiri <vatsa@codeaurora.org>
parent 6075c8a6
Loading
Loading
Loading
Loading
+24 −6
Original line number Diff line number Diff line
@@ -1743,7 +1743,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)
@@ -1757,13 +1756,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 -=