Commit 2368e6d3 authored by Peter Zijlstra's avatar Peter Zijlstra Committed by Greg Kroah-Hartman

futex: Fix (possible) missed wakeup

[ Upstream commit b061c38b ]

We must not rely on wake_q_add() to delay the wakeup; in particular
commit:

  1d0dcb3a ("futex: Implement lockless wakeups")

moved wake_q_add() before smp_store_release(&q->lock_ptr, NULL), which
could result in futex_wait() waking before observing ->lock_ptr ==
NULL and going back to sleep again.
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Fixes: 1d0dcb3a ("futex: Implement lockless wakeups")
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent 653a1dbc
...@@ -1444,11 +1444,7 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q) ...@@ -1444,11 +1444,7 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n")) if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n"))
return; return;
/* get_task_struct(p);
* Queue the task for later wakeup for after we've released
* the hb->lock. wake_q_add() grabs reference to p.
*/
wake_q_add(wake_q, p);
__unqueue_futex(q); __unqueue_futex(q);
/* /*
* The waiting task can free the futex_q as soon as q->lock_ptr = NULL * The waiting task can free the futex_q as soon as q->lock_ptr = NULL
...@@ -1458,6 +1454,13 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q) ...@@ -1458,6 +1454,13 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
* plist_del in __unqueue_futex(). * plist_del in __unqueue_futex().
*/ */
smp_store_release(&q->lock_ptr, NULL); smp_store_release(&q->lock_ptr, NULL);
/*
* Queue the task for later wakeup for after we've released
* the hb->lock. wake_q_add() grabs reference to p.
*/
wake_q_add(wake_q, p);
put_task_struct(p);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment