• Arnd Bergmann's avatar
    asm-generic: avoid __generic_cmpxchg_local warnings · 656e9007
    Arnd Bergmann authored
    Code that passes a 32-bit constant into cmpxchg() produces a harmless
    sparse warning because of the truncation in the branch that is not taken:
    
    fs/erofs/zdata.c: note: in included file (through /home/arnd/arm-soc/arch/arm/include/asm/cmpxchg.h, /home/arnd/arm-soc/arch/arm/include/asm/atomic.h, /home/arnd/arm-soc/include/linux/atomic.h, ...):
    include/asm-generic/cmpxchg-local.h:29:33: warning: cast truncates bits from constant value (5f0ecafe becomes fe)
    include/asm-generic/cmpxchg-local.h:33:34: warning: cast truncates bits from constant value (5f0ecafe becomes cafe)
    include/asm-generic/cmpxchg-local.h:29:33: warning: cast truncates bits from constant value (5f0ecafe becomes fe)
    include/asm-generic/cmpxchg-local.h:30:42: warning: cast truncates bits from constant value (5f0edead becomes ad)
    include/asm-generic/cmpxchg-local.h:33:34: warning: cast truncates bits from constant value (5f0ecafe becomes cafe)
    include/asm-generic/cmpxchg-local.h:34:44: warning: cast truncates bits from constant value (5f0edead becomes dead)
    
    This was reported as a regression to Matt's recent __generic_cmpxchg_local
    patch, though this patch only added more warnings on top of the ones
    that were already there.
    
    Rewording the truncation to use an explicit bitmask instead of a cast
    to a smaller type avoids the warning but otherwise leaves the code
    unchanged.
    
    I had another look at why the cast is even needed for atomic_cmpxchg(),
    and as Matt describes the problem here is that atomic_t contains a
    signed 'int', but cmpxchg() takes an 'unsigned long' argument, and
    converting between the two leads to a 64-bit sign-extension of
    negative 32-bit atomics.
    
    I checked the other implementations of arch_cmpxchg() and did not find
    any others that run into the same problem as __generic_cmpxchg_local(),
    but it's easy to be on the safe side here and always convert the
    signed int into an unsigned int when calling arch_cmpxchg(), as this
    will work even when any of the arch_cmpxchg() implementations run
    into the same problem.
    
    Fixes: 62465415 ("locking/atomic: cmpxchg: Make __generic_cmpxchg_local compare against zero-extended 'old' value")
    Reviewed-by: default avatarMatt Evans <mev@rivosinc.com>
    Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
    656e9007
cmpxchg.h 2.42 KB