lkml.org 
[lkml]   [2016]   [Mar]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.2.y-ckt 140/218] bitops: Do not default to __clear_bit() for __clear_bit_unlock()
    Date
    4.2.8-ckt7 -stable review patch.  If anyone has any objections, please let me know.

    ---8<------------------------------------------------------------

    From: Peter Zijlstra <peterz@infradead.org>

    commit f75d48644c56a31731d17fa693c8175328957e1d upstream.

    __clear_bit_unlock() is a special little snowflake. While it carries the
    non-atomic '__' prefix, it is specifically documented to pair with
    test_and_set_bit() and therefore should be 'somewhat' atomic.

    Therefore the generic implementation of __clear_bit_unlock() cannot use
    the fully non-atomic __clear_bit() as a default.

    If an arch is able to do better; is must provide an implementation of
    __clear_bit_unlock() itself.

    Specifically, this came up as a result of hackbench livelock'ing in
    slab_lock() on ARC with SMP + SLUB + !LLSC.

    The issue was incorrect pairing of atomic ops.

    slab_lock() -> bit_spin_lock() -> test_and_set_bit()
    slab_unlock() -> __bit_spin_unlock() -> __clear_bit()

    The non serializing __clear_bit() was getting "lost"

    80543b8e: ld_s r2,[r13,0] <--- (A) Finds PG_locked is set
    80543b90: or r3,r2,1 <--- (B) other core unlocks right here
    80543b94: st_s r3,[r13,0] <--- (C) sets PG_locked (overwrites unlock)

    Fixes ARC STAR 9000817404 (and probably more).

    Reported-by: Vineet Gupta <Vineet.Gupta1@synopsys.com>
    Tested-by: Vineet Gupta <Vineet.Gupta1@synopsys.com>
    Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
    Cc: Andrew Morton <akpm@linux-foundation.org>
    Cc: Christoph Lameter <cl@linux.com>
    Cc: David Rientjes <rientjes@google.com>
    Cc: Helge Deller <deller@gmx.de>
    Cc: James E.J. Bottomley <jejb@parisc-linux.org>
    Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Noam Camus <noamc@ezchip.com>
    Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
    Cc: Pekka Enberg <penberg@kernel.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Link: http://lkml.kernel.org/r/20160309114054.GJ6356@twins.programming.kicks-ass.net
    Signed-off-by: Ingo Molnar <mingo@kernel.org>
    Signed-off-by: Kamal Mostafa <kamal@canonical.com>
    ---
    include/asm-generic/bitops/lock.h | 14 +++++++-------
    1 file changed, 7 insertions(+), 7 deletions(-)

    diff --git a/include/asm-generic/bitops/lock.h b/include/asm-generic/bitops/lock.h
    index c30266e..8ef0ccb 100644
    --- a/include/asm-generic/bitops/lock.h
    +++ b/include/asm-generic/bitops/lock.h
    @@ -29,16 +29,16 @@ do { \
    * @nr: the bit to set
    * @addr: the address to start counting from
    *
    - * This operation is like clear_bit_unlock, however it is not atomic.
    - * It does provide release barrier semantics so it can be used to unlock
    - * a bit lock, however it would only be used if no other CPU can modify
    - * any bits in the memory until the lock is released (a good example is
    - * if the bit lock itself protects access to the other bits in the word).
    + * A weaker form of clear_bit_unlock() as used by __bit_lock_unlock(). If all
    + * the bits in the word are protected by this lock some archs can use weaker
    + * ops to safely unlock.
    + *
    + * See for example x86's implementation.
    */
    #define __clear_bit_unlock(nr, addr) \
    do { \
    - smp_mb(); \
    - __clear_bit(nr, addr); \
    + smp_mb__before_atomic(); \
    + clear_bit(nr, addr); \
    } while (0)

    #endif /* _ASM_GENERIC_BITOPS_LOCK_H_ */
    --
    2.7.4
    \
     
     \ /
      Last update: 2016-03-31 23:01    [W:4.164 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site