From: Steven Rostedt 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 Signed-off-by: Steven Rostedt --- kernel/wait-simple.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/wait-simple.c b/kernel/wait-simple.c index 4b9a0b5..9725a11 100644 --- a/kernel/wait-simple.c +++ b/kernel/wait-simple.c @@ -27,6 +27,8 @@ static inline void __swait_dequeue(struct swaiter *w) /* 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); } -- 1.7.10.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/