Commit-ID:  6dc080eeb2ba01973bfff0d79844d7a59e12542e
Gitweb:     https://git.kernel.org/tip/6dc080eeb2ba01973bfff0d79844d7a59e12542e
Author:     Prateek Sood <[email protected]>
AuthorDate: Fri, 30 Nov 2018 20:40:56 +0530
Committer:  Ingo Molnar <[email protected]>
CommitDate: Mon, 21 Jan 2019 11:15:36 +0100

sched/wait: Fix rcuwait_wake_up() ordering

For some peculiar reason rcuwait_wake_up() has the right barrier in
the comment, but not in the code.

This mistake has been observed to cause a deadlock in the following
situation:

    P1                                  P2

    percpu_up_read()                    percpu_down_write()
      rcu_sync_is_idle() // false
                                          rcu_sync_enter()
                                          ...
      __percpu_up_read()

[S] ,-  __this_cpu_dec(*sem->read_count)
    |   smp_rmb();
[L] |   task = rcu_dereference(w->task) // NULL
    |
    |                               [S]     w->task = current
    |                                       smp_mb();
    |                               [L]     readers_active_check() // fail
    `-> <store happens here>

Where the smp_rmb() (obviously) fails to constrain the store.

[ peterz: Added changelog. ]

Signed-off-by: Prateek Sood <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Reviewed-by: Andrea Parri <[email protected]>
Acked-by: Davidlohr Bueso <[email protected]>
Cc: Linus Torvalds <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Thomas Gleixner <[email protected]>
Fixes: 8f95c90ceb54 ("sched/wait, RCU: Introduce rcuwait machinery")
Link: 
https://lkml.kernel.org/r/[email protected]
Signed-off-by: Ingo Molnar <[email protected]>
---
 kernel/exit.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/exit.c b/kernel/exit.c
index 284f2fe9a293..3fb7be001964 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -307,7 +307,7 @@ void rcuwait_wake_up(struct rcuwait *w)
         *        MB (A)              MB (B)
         *    [L] cond            [L] tsk
         */
-       smp_rmb(); /* (B) */
+       smp_mb(); /* (B) */
 
        /*
         * Avoid using task_rcu_dereference() magic as long as we are careful,

Reply via email to