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

[PATCH] atomic: add_unless cmpxchg optimise

Without branch hints, the very unlikely chance of the loop repeating due to
cmpxchg failure is unrolled with gcc-4 that I have tested.

Improve this for architectures with a native cas/cmpxchg. llsc archs
should try to implement this natively.

Signed-off-by: Nick Piggin <npiggin@suse.de>
Cc: Andi Kleen <ak@muc.de>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Roman Zippel <zippel@linux-m68k.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Nick Piggin and committed by
Linus Torvalds
0b2fcfdb 713729e8

+50 -10
+7 -1
include/asm-i386/atomic.h
··· 225 225 ({ \ 226 226 int c, old; \ 227 227 c = atomic_read(v); \ 228 - while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ 228 + for (;;) { \ 229 + if (unlikely(c == (u))) \ 230 + break; \ 231 + old = atomic_cmpxchg((v), c, c + (a)); \ 232 + if (likely(old == c)) \ 233 + break; \ 229 234 c = old; \ 235 + } \ 230 236 c != (u); \ 231 237 }) 232 238 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+7 -1
include/asm-ia64/atomic.h
··· 95 95 ({ \ 96 96 int c, old; \ 97 97 c = atomic_read(v); \ 98 - while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ 98 + for (;;) { \ 99 + if (unlikely(c == (u))) \ 100 + break; \ 101 + old = atomic_cmpxchg((v), c, c + (a)); \ 102 + if (likely(old == c)) \ 103 + break; \ 99 104 c = old; \ 105 + } \ 100 106 c != (u); \ 101 107 }) 102 108 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+7 -1
include/asm-m68k/atomic.h
··· 175 175 ({ \ 176 176 int c, old; \ 177 177 c = atomic_read(v); \ 178 - while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ 178 + for (;;) { \ 179 + if (unlikely(c == (u))) \ 180 + break; \ 181 + old = atomic_cmpxchg((v), c, c + (a)); \ 182 + if (likely(old == c)) \ 183 + break; \ 179 184 c = old; \ 185 + } \ 180 186 c != (u); \ 181 187 }) 182 188 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
+14 -4
include/asm-s390/atomic.h
··· 89 89 static __inline__ int atomic_add_unless(atomic_t *v, int a, int u) 90 90 { 91 91 int c, old; 92 - 93 92 c = atomic_read(v); 94 - while (c != u && (old = atomic_cmpxchg(v, c, c + a)) != c) 93 + for (;;) { 94 + if (unlikely(c == u)) 95 + break; 96 + old = atomic_cmpxchg(v, c, c + a); 97 + if (likely(old == c)) 98 + break; 95 99 c = old; 100 + } 96 101 return c != u; 97 102 } 98 103 ··· 172 167 long long a, long long u) 173 168 { 174 169 long long c, old; 175 - 176 170 c = atomic64_read(v); 177 - while (c != u && (old = atomic64_cmpxchg(v, c, c + a)) != c) 171 + for (;;) { 172 + if (unlikely(c == u)) 173 + break; 174 + old = atomic64_cmpxchg(v, c, c + a); 175 + if (likely(old == c)) 176 + break; 178 177 c = old; 178 + } 179 179 return c != u; 180 180 } 181 181
+8 -2
include/asm-sparc64/atomic.h
··· 78 78 ({ \ 79 79 int c, old; \ 80 80 c = atomic_read(v); \ 81 - while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ 81 + for (;;) { \ 82 + if (unlikely(c == (u))) \ 83 + break; \ 84 + old = atomic_cmpxchg((v), c, c + (a)); \ 85 + if (likely(old == c)) \ 86 + break; \ 82 87 c = old; \ 83 - c != (u); \ 88 + } \ 89 + likely(c != (u)); \ 84 90 }) 85 91 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) 86 92
+7 -1
include/asm-x86_64/atomic.h
··· 405 405 ({ \ 406 406 int c, old; \ 407 407 c = atomic_read(v); \ 408 - while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \ 408 + for (;;) { \ 409 + if (unlikely(c == (u))) \ 410 + break; \ 411 + old = atomic_cmpxchg((v), c, c + (a)); \ 412 + if (likely(old == c)) \ 413 + break; \ 409 414 c = old; \ 415 + } \ 410 416 c != (u); \ 411 417 }) 412 418 #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)