diff options
author | Ingo Molnar <mingo@kernel.org> | 2015-10-20 10:16:46 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-10-20 10:16:46 +0200 |
commit | a1a2ab2ff7040bdc9a31bfe7173913971f7d723b (patch) | |
tree | a5b448aaedafafca6974710b7d64074ed964fe24 /kernel/sched | |
parent | 00eb4bab69db349c3bdc7e0b0f7e9070dafea58c (diff) | |
parent | 7379047d5585187d1288486d4627873170d0005a (diff) | |
download | linux-a1a2ab2ff7040bdc9a31bfe7173913971f7d723b.tar.gz linux-a1a2ab2ff7040bdc9a31bfe7173913971f7d723b.tar.bz2 linux-a1a2ab2ff7040bdc9a31bfe7173913971f7d723b.zip |
Merge tag 'v4.3-rc6' into locking/core, to pick up fixes before applying new changes
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'kernel/sched')
-rw-r--r-- | kernel/sched/core.c | 10 | ||||
-rw-r--r-- | kernel/sched/sched.h | 5 |
2 files changed, 8 insertions, 7 deletions
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 615953141951..10a8faa1b0d4 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2517,11 +2517,11 @@ static struct rq *finish_task_switch(struct task_struct *prev) * If a task dies, then it sets TASK_DEAD in tsk->state and calls * schedule one last time. The schedule call will never return, and * the scheduled task must drop that reference. - * The test for TASK_DEAD must occur while the runqueue locks are - * still held, otherwise prev could be scheduled on another cpu, die - * there before we look at prev->state, and then the reference would - * be dropped twice. - * Manfred Spraul <manfred@colorfullife.com> + * + * We must observe prev->state before clearing prev->on_cpu (in + * finish_lock_switch), otherwise a concurrent wakeup can get prev + * running on another CPU and we could rave with its RUNNING -> DEAD + * transition, resulting in a double drop. */ prev_state = prev->state; vtime_task_switch(prev); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 68cda117574c..6d2a119c7ad9 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1078,9 +1078,10 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev) * After ->on_cpu is cleared, the task can be moved to a different CPU. * We must ensure this doesn't happen until the switch is completely * finished. + * + * Pairs with the control dependency and rmb in try_to_wake_up(). */ - smp_wmb(); - prev->on_cpu = 0; + smp_store_release(&prev->on_cpu, 0); #endif #ifdef CONFIG_DEBUG_SPINLOCK /* this is a valid case when another task releases the spinlock */ |