summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2021-03-28 22:42:32 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-03-30 14:41:42 +0200
commit5083fb83381fd011fe4a8e84b7089fcde8cfcb25 (patch)
tree6152d3bc1e074a17c1dfc507bb74c2528cff9f23
parentb4f92d8dec9ba55c6d68cd190f139c682e9700ae (diff)
downloadlinux-stable-5083fb83381fd011fe4a8e84b7089fcde8cfcb25.tar.gz
linux-stable-5083fb83381fd011fe4a8e84b7089fcde8cfcb25.tar.bz2
linux-stable-5083fb83381fd011fe4a8e84b7089fcde8cfcb25.zip
futex: Fix (possible) missed wakeup
commit b061c38bef43406df8e73c5be06cbfacad5ee6ad upstream. We must not rely on wake_q_add() to delay the wakeup; in particular commit: 1d0dcb3ad9d3 ("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: Peter 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: 1d0dcb3ad9d3 ("futex: Implement lockless wakeups") Signed-off-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Ben Hutchings <ben@decadent.org.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--kernel/futex.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/kernel/futex.c b/kernel/futex.c
index 60be2d3cfdd7..5677fbb97aea 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -1553,11 +1553,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"))
return;
- /*
- * 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);
+ get_task_struct(p);
__unqueue_futex(q);
/*
* The waiting task can free the futex_q as soon as
@@ -1566,6 +1562,13 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
* store to lock_ptr from getting ahead of the plist_del.
*/
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);
}
/*