Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2acca55e authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Ingo Molnar
Browse files

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: default avatarFrank 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: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/20110405152729.192366907@chello.nl
parent a8e4f2ea
Loading
Loading
Loading
Loading
+19 −12
Original line number Diff line number Diff line
@@ -2568,7 +2568,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state,
 *
 * Put @p on the run-queue if it's not already there. The caller must
 * ensure that this_rq() is locked, @p is bound to this_rq() and not
 * the current task.  this_rq() stays locked over invocation.
 * the current task.
 */
static void try_to_wake_up_local(struct task_struct *p)
{
@@ -2578,14 +2578,22 @@ static void try_to_wake_up_local(struct task_struct *p)
	BUG_ON(p == current);
	lockdep_assert_held(&rq->lock);

	if (!raw_spin_trylock(&p->pi_lock)) {
		raw_spin_unlock(&rq->lock);
		raw_spin_lock(&p->pi_lock);
		raw_spin_lock(&rq->lock);
	}

	if (!(p->state & TASK_NORMAL))
		return;
		goto out;

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

	ttwu_post_activation(p, rq, 0);
	ttwu_stat(rq, p, smp_processor_id(), 0);
out:
	raw_spin_unlock(&p->pi_lock);
}

/**
@@ -4114,11 +4122,13 @@ asmlinkage void __sched schedule(void)
		if (unlikely(signal_pending_state(prev->state, prev))) {
			prev->state = TASK_RUNNING;
		} else {
			deactivate_task(rq, prev, DEQUEUE_SLEEP);
			prev->on_rq = 0;

			/*
			 * If a worker is going to sleep, notify and
			 * ask workqueue whether it wants to wake up a
			 * task to maintain concurrency.  If so, wake
			 * up the task.
			 * If a worker went to sleep, notify and ask workqueue
			 * whether it wants to wake up a task to maintain
			 * concurrency.
			 */
			if (prev->flags & PF_WQ_WORKER) {
				struct task_struct *to_wakeup;
@@ -4128,12 +4138,9 @@ asmlinkage void __sched schedule(void)
					try_to_wake_up_local(to_wakeup);
			}

			deactivate_task(rq, prev, DEQUEUE_SLEEP);
			prev->on_rq = 0;

			/*
			 * If we are going to sleep and we have plugged IO queued, make
			 * sure to submit it to avoid deadlocks.
			 * If we are going to sleep and we have plugged IO
			 * queued, make sure to submit it to avoid deadlocks.
			 */
			if (blk_needs_flush_plug(prev)) {
				raw_spin_unlock(&rq->lock);