From: Peter Zijlstra <pet...@infradead.org>

[ Upstream commit 952041a8639a7a3a73a2b6573cb8aa8518bc39f8 ]

While reviewing rwsem down_slowpath, Will noticed ldsem had a copy of
a bug we just found for rwsem.

  X = 0;

  CPU0                  CPU1

  rwsem_down_read()
    for (;;) {
      set_current_state(TASK_UNINTERRUPTIBLE);

                        X = 1;
                        rwsem_up_write();
                          rwsem_mark_wake()
                            atomic_long_add(adjustment, &sem->count);
                            smp_store_release(&waiter->task, NULL);

      if (!waiter.task)
        break;

      ...
    }

  r = X;

Allows 'r == 0'.

Reported-by: Will Deacon <w...@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <pet...@infradead.org>
Acked-by: Will Deacon <w...@kernel.org>
Cc: Linus Torvalds <torva...@linux-foundation.org>
Cc: Peter Hurley <pe...@hurleysoftware.com>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Thomas Gleixner <t...@linutronix.de>
Fixes: 4898e640caf0 ("tty: Add timed, writer-prioritized rw semaphore")
Signed-off-by: Ingo Molnar <mi...@kernel.org>
Signed-off-by: Sasha Levin <sas...@kernel.org>
---
 drivers/tty/tty_ldsem.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/tty_ldsem.c b/drivers/tty/tty_ldsem.c
index 34234c2338511..656c2ade6a434 100644
--- a/drivers/tty/tty_ldsem.c
+++ b/drivers/tty/tty_ldsem.c
@@ -137,8 +137,7 @@ static void __ldsem_wake_readers(struct ld_semaphore *sem)
 
        list_for_each_entry_safe(waiter, next, &sem->read_wait, list) {
                tsk = waiter->task;
-               smp_mb();
-               waiter->task = NULL;
+               smp_store_release(&waiter->task, NULL);
                wake_up_process(tsk);
                put_task_struct(tsk);
        }
@@ -234,7 +233,7 @@ down_read_failed(struct ld_semaphore *sem, long count, long 
timeout)
        for (;;) {
                set_task_state(tsk, TASK_UNINTERRUPTIBLE);
 
-               if (!waiter.task)
+               if (!smp_load_acquire(&waiter.task))
                        break;
                if (!timeout)
                        break;
-- 
2.20.1

Reply via email to