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

arm64: cmpxchg: avoid memory barrier on comparison failure

cmpxchg doesn't require memory barrier semantics when the value
comparison fails, so make the barrier conditional on success.

Reviewed-by: Steve Capper <steve.capper@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>

+22 -26
+22 -26
arch/arm64/include/asm/atomic_ll_sc.h
··· 97 97 unsigned long tmp; 98 98 int oldval; 99 99 100 - smp_mb(); 101 - 102 100 asm volatile("// atomic_cmpxchg\n" 103 101 "1: ldxr %w1, %2\n" 104 102 " eor %w0, %w1, %w3\n" 105 103 " cbnz %w0, 2f\n" 106 - " stxr %w0, %w4, %2\n" 104 + " stlxr %w0, %w4, %2\n" 107 105 " cbnz %w0, 1b\n" 106 + " dmb ish\n" 108 107 "2:" 109 108 : "=&r" (tmp), "=&r" (oldval), "+Q" (ptr->counter) 110 - : "Lr" (old), "r" (new)); 109 + : "Lr" (old), "r" (new) 110 + : "memory"); 111 111 112 - smp_mb(); 113 112 return oldval; 114 113 } 115 114 __LL_SC_EXPORT(atomic_cmpxchg); ··· 173 174 long oldval; 174 175 unsigned long res; 175 176 176 - smp_mb(); 177 - 178 177 asm volatile("// atomic64_cmpxchg\n" 179 178 "1: ldxr %1, %2\n" 180 179 " eor %0, %1, %3\n" 181 180 " cbnz %w0, 2f\n" 182 - " stxr %w0, %4, %2\n" 181 + " stlxr %w0, %4, %2\n" 183 182 " cbnz %w0, 1b\n" 183 + " dmb ish\n" 184 184 "2:" 185 185 : "=&r" (res), "=&r" (oldval), "+Q" (ptr->counter) 186 - : "Lr" (old), "r" (new)); 186 + : "Lr" (old), "r" (new) 187 + : "memory"); 187 188 188 - smp_mb(); 189 189 return oldval; 190 190 } 191 191 __LL_SC_EXPORT(atomic64_cmpxchg); ··· 211 213 } 212 214 __LL_SC_EXPORT(atomic64_dec_if_positive); 213 215 214 - #define __CMPXCHG_CASE(w, sz, name, mb, cl) \ 216 + #define __CMPXCHG_CASE(w, sz, name, mb, rel, cl) \ 215 217 __LL_SC_INLINE unsigned long \ 216 218 __LL_SC_PREFIX(__cmpxchg_case_##name(volatile void *ptr, \ 217 219 unsigned long old, \ ··· 220 222 unsigned long tmp, oldval; \ 221 223 \ 222 224 asm volatile( \ 223 - " " #mb "\n" \ 224 225 "1: ldxr" #sz "\t%" #w "[oldval], %[v]\n" \ 225 226 " eor %" #w "[tmp], %" #w "[oldval], %" #w "[old]\n" \ 226 227 " cbnz %" #w "[tmp], 2f\n" \ 227 - " stxr" #sz "\t%w[tmp], %" #w "[new], %[v]\n" \ 228 + " st" #rel "xr" #sz "\t%w[tmp], %" #w "[new], %[v]\n" \ 228 229 " cbnz %w[tmp], 1b\n" \ 229 230 " " #mb "\n" \ 230 231 " mov %" #w "[oldval], %" #w "[old]\n" \ ··· 237 240 } \ 238 241 __LL_SC_EXPORT(__cmpxchg_case_##name); 239 242 240 - __CMPXCHG_CASE(w, b, 1, , ) 241 - __CMPXCHG_CASE(w, h, 2, , ) 242 - __CMPXCHG_CASE(w, , 4, , ) 243 - __CMPXCHG_CASE( , , 8, , ) 244 - __CMPXCHG_CASE(w, b, mb_1, dmb ish, "memory") 245 - __CMPXCHG_CASE(w, h, mb_2, dmb ish, "memory") 246 - __CMPXCHG_CASE(w, , mb_4, dmb ish, "memory") 247 - __CMPXCHG_CASE( , , mb_8, dmb ish, "memory") 243 + __CMPXCHG_CASE(w, b, 1, , , ) 244 + __CMPXCHG_CASE(w, h, 2, , , ) 245 + __CMPXCHG_CASE(w, , 4, , , ) 246 + __CMPXCHG_CASE( , , 8, , , ) 247 + __CMPXCHG_CASE(w, b, mb_1, dmb ish, l, "memory") 248 + __CMPXCHG_CASE(w, h, mb_2, dmb ish, l, "memory") 249 + __CMPXCHG_CASE(w, , mb_4, dmb ish, l, "memory") 250 + __CMPXCHG_CASE( , , mb_8, dmb ish, l, "memory") 248 251 249 252 #undef __CMPXCHG_CASE 250 253 251 - #define __CMPXCHG_DBL(name, mb, cl) \ 254 + #define __CMPXCHG_DBL(name, mb, rel, cl) \ 252 255 __LL_SC_INLINE int \ 253 256 __LL_SC_PREFIX(__cmpxchg_double##name(unsigned long old1, \ 254 257 unsigned long old2, \ ··· 259 262 unsigned long tmp, ret; \ 260 263 \ 261 264 asm volatile("// __cmpxchg_double" #name "\n" \ 262 - " " #mb "\n" \ 263 265 "1: ldxp %0, %1, %2\n" \ 264 266 " eor %0, %0, %3\n" \ 265 267 " eor %1, %1, %4\n" \ 266 268 " orr %1, %0, %1\n" \ 267 269 " cbnz %1, 2f\n" \ 268 - " stxp %w0, %5, %6, %2\n" \ 270 + " st" #rel "xp %w0, %5, %6, %2\n" \ 269 271 " cbnz %w0, 1b\n" \ 270 272 " " #mb "\n" \ 271 273 "2:" \ ··· 276 280 } \ 277 281 __LL_SC_EXPORT(__cmpxchg_double##name); 278 282 279 - __CMPXCHG_DBL( , , ) 280 - __CMPXCHG_DBL(_mb, dmb ish, "memory") 283 + __CMPXCHG_DBL( , , , ) 284 + __CMPXCHG_DBL(_mb, dmb ish, l, "memory") 281 285 282 286 #undef __CMPXCHG_DBL 283 287