blob: 24ddbdd131c837ff341bab33d2041da4fa7d4e29 [file] [log] [blame]
From 8c7c8225cf6bfcf8a6cdcc86bc8d1137e38dde56 Mon Sep 17 00:00:00 2001
From: Steven Rostedt <rostedt@goodmis.org>
Date: Mon, 19 Aug 2013 11:35:32 -0400
Subject: [PATCH] swait: Add memory barrier before checking list empty
There's a race condition with swait wakeups and adding to the list. The
__swait_wake() does a check for swait_head_has_waiters(), and if it is
empty it will exit without doing any wake ups. The problem is that the
check does not include any memory barriers before it makes a decision
to wake up or not.
CPU0 CPU1
---- ----
condition = 1
load h->list (is empty)
raw_spin_lock(hlist->lock)
hlist_add();
__set_current_state();
raw_spin_unlock(hlist->lock)
swait_wake()
swait_head_has_waiters()
(sees h->list as empty and returns)
check_condition (sees condition = 0)
store condition = 1
schedule()
Now the task on CPU1 has just missed its wakeup. By adding a memory
barrier before the list empty check, we fix the problem of miss seeing
the list not empty as well as pushing out the condition for the other
task to see.
Reviewed-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
kernel/wait-simple.c | 2 ++
1 file changed, 2 insertions(+)
--- a/kernel/wait-simple.c
+++ b/kernel/wait-simple.c
@@ -27,6 +27,8 @@ static inline void __swait_dequeue(struc
/* Check whether a head has waiters enqueued */
static inline bool swait_head_has_waiters(struct swait_head *h)
{
+ /* Make sure the condition is visible before checking list_empty() */
+ smp_mb();
return !list_empty(&h->list);
}