Commit c6fc81af authored by John Wright's avatar John Wright Committed by Greg Kroah-Hartman

sched: Fix a race between ttwu() and migrate_task()

Based on commit e2912009 upstream, but
done differently as this issue is not present in .33 or .34 kernels due
to rework in this area.

If a task is in the TASK_WAITING state, then try_to_wake_up() is working
on it, and it will place it on the correct cpu.

This commit ensures that neither migrate_task() nor __migrate_task()
calls set_task_cpu(p) while p is in the TASK_WAKING state.  Otherwise,
there could be two concurrent calls to set_task_cpu(p), resulting in
the task's cfs_rq being inconsistent with its cpu.
Signed-off-by: default avatarJohn Wright <john.wright@hp.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 328851d3
...@@ -2116,12 +2116,10 @@ migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req) ...@@ -2116,12 +2116,10 @@ migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req)
/* /*
* If the task is not on a runqueue (and not running), then * If the task is not on a runqueue (and not running), then
* it is sufficient to simply update the task's cpu field. * the next wake-up will properly place the task.
*/ */
if (!p->se.on_rq && !task_running(rq, p)) { if (!p->se.on_rq && !task_running(rq, p))
set_task_cpu(p, dest_cpu);
return 0; return 0;
}
init_completion(&req->done); init_completion(&req->done);
req->task = p; req->task = p;
...@@ -7167,6 +7165,9 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu) ...@@ -7167,6 +7165,9 @@ static int __migrate_task(struct task_struct *p, int src_cpu, int dest_cpu)
/* Already moved. */ /* Already moved. */
if (task_cpu(p) != src_cpu) if (task_cpu(p) != src_cpu)
goto done; goto done;
/* Waking up, don't get in the way of try_to_wake_up(). */
if (p->state == TASK_WAKING)
goto fail;
/* Affinity changed (again). */ /* Affinity changed (again). */
if (!cpumask_test_cpu(dest_cpu, &p->cpus_allowed)) if (!cpumask_test_cpu(dest_cpu, &p->cpus_allowed))
goto fail; goto fail;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment