lkml.org 
[lkml]   [2019]   [Aug]   [2]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.9 21/22] tty/ldsem, locking/rwsem: Add missing ACQUIRE to read_failed sleep loop
    Date
    From: Peter Zijlstra <peterz@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 <will@kernel.org>
    Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    Acked-by: Will Deacon <will@kernel.org>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Peter Hurley <peter@hurleysoftware.com>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Fixes: 4898e640caf0 ("tty: Add timed, writer-prioritized rw semaphore")
    Signed-off-by: Ingo Molnar <mingo@kernel.org>
    Signed-off-by: Sasha Levin <sashal@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 dbd7ba32caac3..6c5eb99fcfcee 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
    \
     
     \ /
      Last update: 2019-08-02 15:39    [W:6.027 / U:0.000 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site