Skip to content

Commit c20cf06

Browse files
Peter ZijlstraIngo Molnar
authored andcommitted
sched: Simplify migration_cpu_stop()
When affine_move_task() issues a migration_cpu_stop(), the purpose of that function is to complete that @pending, not any random other p->migration_pending that might have gotten installed since. This realization much simplifies migration_cpu_stop() and allows further necessary steps to fix all this as it provides the guarantee that @pending's stopper will complete @pending (and not some random other @pending). Fixes: 6d337ea ("sched: Fix migrate_disable() vs set_cpus_allowed_ptr()") Cc: [email protected] Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Reviewed-by: Valentin Schneider <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 8a6edb5 commit c20cf06

File tree

1 file changed

+8
-48
lines changed

1 file changed

+8
-48
lines changed

kernel/sched/core.c

Lines changed: 8 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1898,8 +1898,8 @@ static struct rq *__migrate_task(struct rq *rq, struct rq_flags *rf,
18981898
*/
18991899
static int migration_cpu_stop(void *data)
19001900
{
1901-
struct set_affinity_pending *pending;
19021901
struct migration_arg *arg = data;
1902+
struct set_affinity_pending *pending = arg->pending;
19031903
struct task_struct *p = arg->task;
19041904
int dest_cpu = arg->dest_cpu;
19051905
struct rq *rq = this_rq();
@@ -1921,25 +1921,6 @@ static int migration_cpu_stop(void *data)
19211921
raw_spin_lock(&p->pi_lock);
19221922
rq_lock(rq, &rf);
19231923

1924-
pending = p->migration_pending;
1925-
if (pending && !arg->pending) {
1926-
/*
1927-
* This happens from sched_exec() and migrate_task_to(),
1928-
* neither of them care about pending and just want a task to
1929-
* maybe move about.
1930-
*
1931-
* Even if there is a pending, we can ignore it, since
1932-
* affine_move_task() will have it's own stop_work's in flight
1933-
* which will manage the completion.
1934-
*
1935-
* Notably, pending doesn't need to match arg->pending. This can
1936-
* happen when tripple concurrent affine_move_task() first sets
1937-
* pending, then clears pending and eventually sets another
1938-
* pending.
1939-
*/
1940-
pending = NULL;
1941-
}
1942-
19431924
/*
19441925
* If task_rq(p) != rq, it cannot be migrated here, because we're
19451926
* holding rq->lock, if p->on_rq == 0 it cannot get enqueued because
@@ -1950,31 +1931,20 @@ static int migration_cpu_stop(void *data)
19501931
goto out;
19511932

19521933
if (pending) {
1953-
p->migration_pending = NULL;
1934+
if (p->migration_pending == pending)
1935+
p->migration_pending = NULL;
19541936
complete = true;
19551937
}
19561938

1957-
/* migrate_enable() -- we must not race against SCA */
1958-
if (dest_cpu < 0) {
1959-
/*
1960-
* When this was migrate_enable() but we no longer
1961-
* have a @pending, a concurrent SCA 'fixed' things
1962-
* and we should be valid again. Nothing to do.
1963-
*/
1964-
if (!pending) {
1965-
WARN_ON_ONCE(!cpumask_test_cpu(task_cpu(p), &p->cpus_mask));
1966-
goto out;
1967-
}
1968-
1939+
if (dest_cpu < 0)
19691940
dest_cpu = cpumask_any_distribute(&p->cpus_mask);
1970-
}
19711941

19721942
if (task_on_rq_queued(p))
19731943
rq = __migrate_task(rq, &rf, p, dest_cpu);
19741944
else
19751945
p->wake_cpu = dest_cpu;
19761946

1977-
} else if (dest_cpu < 0 || pending) {
1947+
} else if (pending) {
19781948
/*
19791949
* This happens when we get migrated between migrate_enable()'s
19801950
* preempt_enable() and scheduling the stopper task. At that
@@ -1989,22 +1959,13 @@ static int migration_cpu_stop(void *data)
19891959
* ->pi_lock, so the allowed mask is stable - if it got
19901960
* somewhere allowed, we're done.
19911961
*/
1992-
if (pending && cpumask_test_cpu(task_cpu(p), p->cpus_ptr)) {
1993-
p->migration_pending = NULL;
1962+
if (cpumask_test_cpu(task_cpu(p), p->cpus_ptr)) {
1963+
if (p->migration_pending == pending)
1964+
p->migration_pending = NULL;
19941965
complete = true;
19951966
goto out;
19961967
}
19971968

1998-
/*
1999-
* When this was migrate_enable() but we no longer have an
2000-
* @pending, a concurrent SCA 'fixed' things and we should be
2001-
* valid again. Nothing to do.
2002-
*/
2003-
if (!pending) {
2004-
WARN_ON_ONCE(!cpumask_test_cpu(task_cpu(p), &p->cpus_mask));
2005-
goto out;
2006-
}
2007-
20081969
/*
20091970
* When migrate_enable() hits a rq mis-match we can't reliably
20101971
* determine is_migration_disabled() and so have to chase after
@@ -2022,7 +1983,6 @@ static int migration_cpu_stop(void *data)
20221983
complete_all(&pending->done);
20231984

20241985
/* For pending->{arg,stop_work} */
2025-
pending = arg->pending;
20261986
if (pending && refcount_dec_and_test(&pending->refs))
20271987
wake_up_var(&pending->refs);
20281988

0 commit comments

Comments
 (0)