Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

locking/atomic: Fix atomic_set_release() for 'funny' architectures

Those architectures that have a special atomic_set implementation also
need a special atomic_set_release(), because for the very same reason
WRITE_ONCE() is broken for them, smp_store_release() is too.

The vast majority is architectures that have spinlock hash based atomic
implementation except hexagon which seems to have a hardware 'feature'.

The spinlock based atomics should be SC, that is, none of them appear to
place extra barriers in atomic_cmpxchg() or any of the other SC atomic
primitives and therefore seem to rely on their spinlock implementation
being SC (I did not fully validate all that).

Therefore, the normal atomic_set() is SC and can be used at
atomic_set_release().

Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: Chris Metcalf <cmetcalf@mellanox.com> [for tile]
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Paul McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Will Deacon <will.deacon@arm.com>
Cc: davem@davemloft.net
Cc: james.hogan@imgtec.com
Cc: jejb@parisc-linux.org
Cc: rkuo@codeaurora.org
Cc: vgupta@synopsys.com
Link: http://lkml.kernel.org/r/20170609110506.yod47flaav3wgoj5@hirez.programming.kicks-ass.net
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

Peter Zijlstra and committed by
Ingo Molnar
9d664c0a 35a2897c

+14
+2
arch/arc/include/asm/atomic.h
··· 123 123 atomic_ops_unlock(flags); 124 124 } 125 125 126 + #define atomic_set_release(v, i) atomic_set((v), (i)) 127 + 126 128 #endif 127 129 128 130 /*
+2
arch/hexagon/include/asm/atomic.h
··· 42 42 ); 43 43 } 44 44 45 + #define atomic_set_release(v, i) atomic_set((v), (i)) 46 + 45 47 /** 46 48 * atomic_read - reads a word, atomically 47 49 * @v: pointer to atomic value
+2
arch/metag/include/asm/atomic_lock1.h
··· 37 37 return i; 38 38 } 39 39 40 + #define atomic_set_release(v, i) atomic_set((v), (i)) 41 + 40 42 #define ATOMIC_OP(op, c_op) \ 41 43 static inline void atomic_##op(int i, atomic_t *v) \ 42 44 { \
+2
arch/parisc/include/asm/atomic.h
··· 65 65 _atomic_spin_unlock_irqrestore(v, flags); 66 66 } 67 67 68 + #define atomic_set_release(v, i) atomic_set((v), (i)) 69 + 68 70 static __inline__ int atomic_read(const atomic_t *v) 69 71 { 70 72 return READ_ONCE((v)->counter);
+2
arch/sparc/include/asm/atomic_32.h
··· 29 29 int __atomic_add_unless(atomic_t *, int, int); 30 30 void atomic_set(atomic_t *, int); 31 31 32 + #define atomic_set_release(v, i) atomic_set((v), (i)) 33 + 32 34 #define atomic_read(v) ACCESS_ONCE((v)->counter) 33 35 34 36 #define atomic_add(i, v) ((void)atomic_add_return( (int)(i), (v)))
+2
arch/tile/include/asm/atomic_32.h
··· 101 101 _atomic_xchg(&v->counter, n); 102 102 } 103 103 104 + #define atomic_set_release(v, i) atomic_set((v), (i)) 105 + 104 106 /* A 64bit atomic type */ 105 107 106 108 typedef struct {
+2
include/asm-generic/atomic64.h
··· 21 21 extern long long atomic64_read(const atomic64_t *v); 22 22 extern void atomic64_set(atomic64_t *v, long long i); 23 23 24 + #define atomic64_set_release(v, i) atomic64_set((v), (i)) 25 + 24 26 #define ATOMIC64_OP(op) \ 25 27 extern void atomic64_##op(long long a, atomic64_t *v); 26 28