diff options
author | Andrea Parri <parri.andrea@gmail.com> | 2018-02-26 23:00:58 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2018-03-12 05:59:03 -0400 |
commit | fbfcd0199170984bd3c2812e49ed0fe7b226959a (patch) | |
tree | a17482251a965cb047cda3d91bbc4810aeb3a48b | |
parent | bd5c0ba2cd78a4c116726ead84f8f37dc92d043e (diff) |
locking/xchg/alpha: Remove superfluous memory barriers from the _local() variants
The following two commits:
79d442461df74 ("locking/xchg/alpha: Clean up barrier usage by using smp_mb() in place of __ASM__MB")
472e8c55cf662 ("locking/xchg/alpha: Fix xchg() and cmpxchg() memory ordering bugs")
... ended up adding unnecessary barriers to the _local() variants on Alpha,
which the previous code took care to avoid.
Fix them by adding the smp_mb() into the cmpxchg() macro rather than into the
____cmpxchg() variants.
Reported-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Andrea Parri <parri.andrea@gmail.com>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Matt Turner <mattst88@gmail.com>
Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-alpha@vger.kernel.org
Fixes: 472e8c55cf662 ("locking/xchg/alpha: Fix xchg() and cmpxchg() memory ordering bugs")
Fixes: 79d442461df74 ("locking/xchg/alpha: Clean up barrier usage by using smp_mb() in place of __ASM__MB")
Link: http://lkml.kernel.org/r/1519704058-13430-1-git-send-email-parri.andrea@gmail.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r-- | arch/alpha/include/asm/cmpxchg.h | 20 | ||||
-rw-r--r-- | arch/alpha/include/asm/xchg.h | 27 |
2 files changed, 16 insertions, 31 deletions
diff --git a/arch/alpha/include/asm/cmpxchg.h b/arch/alpha/include/asm/cmpxchg.h index 8a2b331e43fe..6c7c39452471 100644 --- a/arch/alpha/include/asm/cmpxchg.h +++ b/arch/alpha/include/asm/cmpxchg.h | |||
@@ -38,19 +38,31 @@ | |||
38 | #define ____cmpxchg(type, args...) __cmpxchg ##type(args) | 38 | #define ____cmpxchg(type, args...) __cmpxchg ##type(args) |
39 | #include <asm/xchg.h> | 39 | #include <asm/xchg.h> |
40 | 40 | ||
41 | /* | ||
42 | * The leading and the trailing memory barriers guarantee that these | ||
43 | * operations are fully ordered. | ||
44 | */ | ||
41 | #define xchg(ptr, x) \ | 45 | #define xchg(ptr, x) \ |
42 | ({ \ | 46 | ({ \ |
47 | __typeof__(*(ptr)) __ret; \ | ||
43 | __typeof__(*(ptr)) _x_ = (x); \ | 48 | __typeof__(*(ptr)) _x_ = (x); \ |
44 | (__typeof__(*(ptr))) __xchg((ptr), (unsigned long)_x_, \ | 49 | smp_mb(); \ |
45 | sizeof(*(ptr))); \ | 50 | __ret = (__typeof__(*(ptr))) \ |
51 | __xchg((ptr), (unsigned long)_x_, sizeof(*(ptr))); \ | ||
52 | smp_mb(); \ | ||
53 | __ret; \ | ||
46 | }) | 54 | }) |
47 | 55 | ||
48 | #define cmpxchg(ptr, o, n) \ | 56 | #define cmpxchg(ptr, o, n) \ |
49 | ({ \ | 57 | ({ \ |
58 | __typeof__(*(ptr)) __ret; \ | ||
50 | __typeof__(*(ptr)) _o_ = (o); \ | 59 | __typeof__(*(ptr)) _o_ = (o); \ |
51 | __typeof__(*(ptr)) _n_ = (n); \ | 60 | __typeof__(*(ptr)) _n_ = (n); \ |
52 | (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \ | 61 | smp_mb(); \ |
53 | (unsigned long)_n_, sizeof(*(ptr)));\ | 62 | __ret = (__typeof__(*(ptr))) __cmpxchg((ptr), \ |
63 | (unsigned long)_o_, (unsigned long)_n_, sizeof(*(ptr)));\ | ||
64 | smp_mb(); \ | ||
65 | __ret; \ | ||
54 | }) | 66 | }) |
55 | 67 | ||
56 | #define cmpxchg64(ptr, o, n) \ | 68 | #define cmpxchg64(ptr, o, n) \ |
diff --git a/arch/alpha/include/asm/xchg.h b/arch/alpha/include/asm/xchg.h index e2b59fac5257..7adb80c6746a 100644 --- a/arch/alpha/include/asm/xchg.h +++ b/arch/alpha/include/asm/xchg.h | |||
@@ -12,10 +12,6 @@ | |||
12 | * Atomic exchange. | 12 | * Atomic exchange. |
13 | * Since it can be used to implement critical sections | 13 | * Since it can be used to implement critical sections |
14 | * it must clobber "memory" (also for interrupts in UP). | 14 | * it must clobber "memory" (also for interrupts in UP). |
15 | * | ||
16 | * The leading and the trailing memory barriers guarantee that these | ||
17 | * operations are fully ordered. | ||
18 | * | ||
19 | */ | 15 | */ |
20 | 16 | ||
21 | static inline unsigned long | 17 | static inline unsigned long |
@@ -23,7 +19,6 @@ ____xchg(_u8, volatile char *m, unsigned long val) | |||
23 | { | 19 | { |
24 | unsigned long ret, tmp, addr64; | 20 | unsigned long ret, tmp, addr64; |
25 | 21 | ||
26 | smp_mb(); | ||
27 | __asm__ __volatile__( | 22 | __asm__ __volatile__( |
28 | " andnot %4,7,%3\n" | 23 | " andnot %4,7,%3\n" |
29 | " insbl %1,%4,%1\n" | 24 | " insbl %1,%4,%1\n" |
@@ -38,7 +33,6 @@ ____xchg(_u8, volatile char *m, unsigned long val) | |||
38 | ".previous" | 33 | ".previous" |
39 | : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64) | 34 | : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64) |
40 | : "r" ((long)m), "1" (val) : "memory"); | 35 | : "r" ((long)m), "1" (val) : "memory"); |
41 | smp_mb(); | ||
42 | 36 | ||
43 | return ret; | 37 | return ret; |
44 | } | 38 | } |
@@ -48,7 +42,6 @@ ____xchg(_u16, volatile short *m, unsigned long val) | |||
48 | { | 42 | { |
49 | unsigned long ret, tmp, addr64; | 43 | unsigned long ret, tmp, addr64; |
50 | 44 | ||
51 | smp_mb(); | ||
52 | __asm__ __volatile__( | 45 | __asm__ __volatile__( |
53 | " andnot %4,7,%3\n" | 46 | " andnot %4,7,%3\n" |
54 | " inswl %1,%4,%1\n" | 47 | " inswl %1,%4,%1\n" |
@@ -63,7 +56,6 @@ ____xchg(_u16, volatile short *m, unsigned long val) | |||
63 | ".previous" | 56 | ".previous" |
64 | : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64) | 57 | : "=&r" (ret), "=&r" (val), "=&r" (tmp), "=&r" (addr64) |
65 | : "r" ((long)m), "1" (val) : "memory"); | 58 | : "r" ((long)m), "1" (val) : "memory"); |
66 | smp_mb(); | ||
67 | 59 | ||
68 | return ret; | 60 | return ret; |
69 | } | 61 | } |
@@ -73,7 +65,6 @@ ____xchg(_u32, volatile int *m, unsigned long val) | |||
73 | { | 65 | { |
74 | unsigned long dummy; | 66 | unsigned long dummy; |
75 | 67 | ||
76 | smp_mb(); | ||
77 | __asm__ __volatile__( | 68 | __asm__ __volatile__( |
78 | "1: ldl_l %0,%4\n" | 69 | "1: ldl_l %0,%4\n" |
79 | " bis $31,%3,%1\n" | 70 | " bis $31,%3,%1\n" |
@@ -84,7 +75,6 @@ ____xchg(_u32, volatile int *m, unsigned long val) | |||
84 | ".previous" | 75 | ".previous" |
85 | : "=&r" (val), "=&r" (dummy), "=m" (*m) | 76 | : "=&r" (val), "=&r" (dummy), "=m" (*m) |
86 | : "rI" (val), "m" (*m) : "memory"); | 77 | : "rI" (val), "m" (*m) : "memory"); |
87 | smp_mb(); | ||
88 | 78 | ||
89 | return val; | 79 | return val; |
90 | } | 80 | } |
@@ -94,7 +84,6 @@ ____xchg(_u64, volatile long *m, unsigned long val) | |||
94 | { | 84 | { |
95 | unsigned long dummy; | 85 | unsigned long dummy; |
96 | 86 | ||
97 | smp_mb(); | ||
98 | __asm__ __volatile__( | 87 | __asm__ __volatile__( |
99 | "1: ldq_l %0,%4\n" | 88 | "1: ldq_l %0,%4\n" |
100 | " bis $31,%3,%1\n" | 89 | " bis $31,%3,%1\n" |
@@ -105,7 +94,6 @@ ____xchg(_u64, volatile long *m, unsigned long val) | |||
105 | ".previous" | 94 | ".previous" |
106 | : "=&r" (val), "=&r" (dummy), "=m" (*m) | 95 | : "=&r" (val), "=&r" (dummy), "=m" (*m) |
107 | : "rI" (val), "m" (*m) : "memory"); | 96 | : "rI" (val), "m" (*m) : "memory"); |
108 | smp_mb(); | ||
109 | 97 | ||
110 | return val; | 98 | return val; |
111 | } | 99 | } |
@@ -135,13 +123,6 @@ ____xchg(, volatile void *ptr, unsigned long x, int size) | |||
135 | * Atomic compare and exchange. Compare OLD with MEM, if identical, | 123 | * Atomic compare and exchange. Compare OLD with MEM, if identical, |
136 | * store NEW in MEM. Return the initial value in MEM. Success is | 124 | * store NEW in MEM. Return the initial value in MEM. Success is |
137 | * indicated by comparing RETURN with OLD. | 125 | * indicated by comparing RETURN with OLD. |
138 | * | ||
139 | * The leading and the trailing memory barriers guarantee that these | ||
140 | * operations are fully ordered. | ||
141 | * | ||
142 | * The trailing memory barrier is placed in SMP unconditionally, in | ||
143 | * order to guarantee that dependency ordering is preserved when a | ||
144 | * dependency is headed by an unsuccessful operation. | ||
145 | */ | 126 | */ |
146 | 127 | ||
147 | static inline unsigned long | 128 | static inline unsigned long |
@@ -149,7 +130,6 @@ ____cmpxchg(_u8, volatile char *m, unsigned char old, unsigned char new) | |||
149 | { | 130 | { |
150 | unsigned long prev, tmp, cmp, addr64; | 131 | unsigned long prev, tmp, cmp, addr64; |
151 | 132 | ||
152 | smp_mb(); | ||
153 | __asm__ __volatile__( | 133 | __asm__ __volatile__( |
154 | " andnot %5,7,%4\n" | 134 | " andnot %5,7,%4\n" |
155 | " insbl %1,%5,%1\n" | 135 | " insbl %1,%5,%1\n" |
@@ -167,7 +147,6 @@ ____cmpxchg(_u8, volatile char *m, unsigned char old, unsigned char new) | |||
167 | ".previous" | 147 | ".previous" |
168 | : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64) | 148 | : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64) |
169 | : "r" ((long)m), "Ir" (old), "1" (new) : "memory"); | 149 | : "r" ((long)m), "Ir" (old), "1" (new) : "memory"); |
170 | smp_mb(); | ||
171 | 150 | ||
172 | return prev; | 151 | return prev; |
173 | } | 152 | } |
@@ -177,7 +156,6 @@ ____cmpxchg(_u16, volatile short *m, unsigned short old, unsigned short new) | |||
177 | { | 156 | { |
178 | unsigned long prev, tmp, cmp, addr64; | 157 | unsigned long prev, tmp, cmp, addr64; |
179 | 158 | ||
180 | smp_mb(); | ||
181 | __asm__ __volatile__( | 159 | __asm__ __volatile__( |
182 | " andnot %5,7,%4\n" | 160 | " andnot %5,7,%4\n" |
183 | " inswl %1,%5,%1\n" | 161 | " inswl %1,%5,%1\n" |
@@ -195,7 +173,6 @@ ____cmpxchg(_u16, volatile short *m, unsigned short old, unsigned short new) | |||
195 | ".previous" | 173 | ".previous" |
196 | : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64) | 174 | : "=&r" (prev), "=&r" (new), "=&r" (tmp), "=&r" (cmp), "=&r" (addr64) |
197 | : "r" ((long)m), "Ir" (old), "1" (new) : "memory"); | 175 | : "r" ((long)m), "Ir" (old), "1" (new) : "memory"); |
198 | smp_mb(); | ||
199 | 176 | ||
200 | return prev; | 177 | return prev; |
201 | } | 178 | } |
@@ -205,7 +182,6 @@ ____cmpxchg(_u32, volatile int *m, int old, int new) | |||
205 | { | 182 | { |
206 | unsigned long prev, cmp; | 183 | unsigned long prev, cmp; |
207 | 184 | ||
208 | smp_mb(); | ||
209 | __asm__ __volatile__( | 185 | __asm__ __volatile__( |
210 | "1: ldl_l %0,%5\n" | 186 | "1: ldl_l %0,%5\n" |
211 | " cmpeq %0,%3,%1\n" | 187 | " cmpeq %0,%3,%1\n" |
@@ -219,7 +195,6 @@ ____cmpxchg(_u32, volatile int *m, int old, int new) | |||
219 | ".previous" | 195 | ".previous" |
220 | : "=&r"(prev), "=&r"(cmp), "=m"(*m) | 196 | : "=&r"(prev), "=&r"(cmp), "=m"(*m) |
221 | : "r"((long) old), "r"(new), "m"(*m) : "memory"); | 197 | : "r"((long) old), "r"(new), "m"(*m) : "memory"); |
222 | smp_mb(); | ||
223 | 198 | ||
224 | return prev; | 199 | return prev; |
225 | } | 200 | } |
@@ -229,7 +204,6 @@ ____cmpxchg(_u64, volatile long *m, unsigned long old, unsigned long new) | |||
229 | { | 204 | { |
230 | unsigned long prev, cmp; | 205 | unsigned long prev, cmp; |
231 | 206 | ||
232 | smp_mb(); | ||
233 | __asm__ __volatile__( | 207 | __asm__ __volatile__( |
234 | "1: ldq_l %0,%5\n" | 208 | "1: ldq_l %0,%5\n" |
235 | " cmpeq %0,%3,%1\n" | 209 | " cmpeq %0,%3,%1\n" |
@@ -243,7 +217,6 @@ ____cmpxchg(_u64, volatile long *m, unsigned long old, unsigned long new) | |||
243 | ".previous" | 217 | ".previous" |
244 | : "=&r"(prev), "=&r"(cmp), "=m"(*m) | 218 | : "=&r"(prev), "=&r"(cmp), "=m"(*m) |
245 | : "r"((long) old), "r"(new), "m"(*m) : "memory"); | 219 | : "r"((long) old), "r"(new), "m"(*m) : "memory"); |
246 | smp_mb(); | ||
247 | 220 | ||
248 | return prev; | 221 | return prev; |
249 | } | 222 | } |