Skip to content

Commit 2acca55

Browse files
Peter ZijlstraIngo Molnar
Peter Zijlstra
authored and
Ingo Molnar
committed
sched: Also serialize ttwu_local() with p->pi_lock
Since we now serialize ttwu() using p->pi_lock, we also need to serialize ttwu_local() using that, otherwise, once we drop the rq->lock from ttwu() it can race with ttwu_local(). Reviewed-by: Frank Rowand <frank.rowand@am.sony.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Nick Piggin <npiggin@kernel.dk> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Link: http://lkml.kernel.org/r/20110405152729.192366907@chello.nl
1 parent a8e4f2e commit 2acca55

File tree

1 file changed

+19
-12
lines changed

1 file changed

+19
-12
lines changed

kernel/sched.c

+19-12
Original file line numberDiff line numberDiff line change
@@ -2566,9 +2566,9 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state,
25662566
* try_to_wake_up_local - try to wake up a local task with rq lock held
25672567
* @p: the thread to be awakened
25682568
*
2569-
* Put @p on the run-queue if it's not already there. The caller must
2569+
* Put @p on the run-queue if it's not already there. The caller must
25702570
* ensure that this_rq() is locked, @p is bound to this_rq() and not
2571-
* the current task. this_rq() stays locked over invocation.
2571+
* the current task.
25722572
*/
25732573
static void try_to_wake_up_local(struct task_struct *p)
25742574
{
@@ -2578,14 +2578,22 @@ static void try_to_wake_up_local(struct task_struct *p)
25782578
BUG_ON(p == current);
25792579
lockdep_assert_held(&rq->lock);
25802580

2581+
if (!raw_spin_trylock(&p->pi_lock)) {
2582+
raw_spin_unlock(&rq->lock);
2583+
raw_spin_lock(&p->pi_lock);
2584+
raw_spin_lock(&rq->lock);
2585+
}
2586+
25812587
if (!(p->state & TASK_NORMAL))
2582-
return;
2588+
goto out;
25832589

25842590
if (!p->on_rq)
25852591
ttwu_activate(rq, p, ENQUEUE_WAKEUP);
25862592

25872593
ttwu_post_activation(p, rq, 0);
25882594
ttwu_stat(rq, p, smp_processor_id(), 0);
2595+
out:
2596+
raw_spin_unlock(&p->pi_lock);
25892597
}
25902598

25912599
/**
@@ -4114,11 +4122,13 @@ asmlinkage void __sched schedule(void)
41144122
if (unlikely(signal_pending_state(prev->state, prev))) {
41154123
prev->state = TASK_RUNNING;
41164124
} else {
4125+
deactivate_task(rq, prev, DEQUEUE_SLEEP);
4126+
prev->on_rq = 0;
4127+
41174128
/*
4118-
* If a worker is going to sleep, notify and
4119-
* ask workqueue whether it wants to wake up a
4120-
* task to maintain concurrency. If so, wake
4121-
* up the task.
4129+
* If a worker went to sleep, notify and ask workqueue
4130+
* whether it wants to wake up a task to maintain
4131+
* concurrency.
41224132
*/
41234133
if (prev->flags & PF_WQ_WORKER) {
41244134
struct task_struct *to_wakeup;
@@ -4128,12 +4138,9 @@ asmlinkage void __sched schedule(void)
41284138
try_to_wake_up_local(to_wakeup);
41294139
}
41304140

4131-
deactivate_task(rq, prev, DEQUEUE_SLEEP);
4132-
prev->on_rq = 0;
4133-
41344141
/*
4135-
* If we are going to sleep and we have plugged IO queued, make
4136-
* sure to submit it to avoid deadlocks.
4142+
* If we are going to sleep and we have plugged IO
4143+
* queued, make sure to submit it to avoid deadlocks.
41374144
*/
41384145
if (blk_needs_flush_plug(prev)) {
41394146
raw_spin_unlock(&rq->lock);

0 commit comments

Comments
 (0)