aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/sched/core.c10
-rw-r--r--kernel/sched/sched.h5
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)
2517 * If a task dies, then it sets TASK_DEAD in tsk->state and calls 2517 * If a task dies, then it sets TASK_DEAD in tsk->state and calls
2518 * schedule one last time. The schedule call will never return, and 2518 * schedule one last time. The schedule call will never return, and
2519 * the scheduled task must drop that reference. 2519 * the scheduled task must drop that reference.
2520 * The test for TASK_DEAD must occur while the runqueue locks are 2520 *
2521 * still held, otherwise prev could be scheduled on another cpu, die 2521 * We must observe prev->state before clearing prev->on_cpu (in
2522 * there before we look at prev->state, and then the reference would 2522 * finish_lock_switch), otherwise a concurrent wakeup can get prev
2523 * be dropped twice. 2523 * running on another CPU and we could rave with its RUNNING -> DEAD
2524 * Manfred Spraul <manfred@colorfullife.com> 2524 * transition, resulting in a double drop.
2525 */ 2525 */
2526 prev_state = prev->state; 2526 prev_state = prev->state;
2527 vtime_task_switch(prev); 2527 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)
1078 * After ->on_cpu is cleared, the task can be moved to a different CPU. 1078 * After ->on_cpu is cleared, the task can be moved to a different CPU.
1079 * We must ensure this doesn't happen until the switch is completely 1079 * We must ensure this doesn't happen until the switch is completely
1080 * finished. 1080 * finished.
1081 *
1082 * Pairs with the control dependency and rmb in try_to_wake_up().
1081 */ 1083 */
1082 smp_wmb(); 1084 smp_store_release(&prev->on_cpu, 0);
1083 prev->on_cpu = 0;
1084#endif 1085#endif
1085#ifdef CONFIG_DEBUG_SPINLOCK 1086#ifdef CONFIG_DEBUG_SPINLOCK
1086 /* this is a valid case when another task releases the spinlock */ 1087 /* this is a valid case when another task releases the spinlock */