aboutsummaryrefslogtreecommitdiffstats
path: root/arch/alpha
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2013-07-11 10:42:14 -0400
committerMatt Turner <mattst88@gmail.com>2013-07-19 16:54:24 -0400
commit6da7539734d4e0f5caeea1e0efbb74d7b83db1ca (patch)
treef29b23ea3236acda9db434aa89052537f2a8092a /arch/alpha
parenta5c6eae4d6763e50101494b392ef6518c0ef96e9 (diff)
alpha: Improve atomic_add_unless
Use ll/sc loops instead of C loops around cmpxchg. Update the atomic64_add_unless block comment to match the code. Reviewed-and-Tested-by: Matt Turner <mattst88@gmail.com> Signed-off-by: Matt Turner <mattst88@gmail.com> Signed-off-by: Richard Henderson <rth@twiddle.net>
Diffstat (limited to 'arch/alpha')
-rw-r--r--arch/alpha/include/asm/atomic.h60
1 files changed, 37 insertions, 23 deletions
diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h
index c2cbe4fc391c..0dc18fc4d925 100644
--- a/arch/alpha/include/asm/atomic.h
+++ b/arch/alpha/include/asm/atomic.h
@@ -186,17 +186,24 @@ static __inline__ long atomic64_sub_return(long i, atomic64_t * v)
186 */ 186 */
187static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u) 187static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
188{ 188{
189 int c, old; 189 int c, new, old;
190 c = atomic_read(v); 190 smp_mb();
191 for (;;) { 191 __asm__ __volatile__(
192 if (unlikely(c == (u))) 192 "1: ldl_l %[old],%[mem]\n"
193 break; 193 " cmpeq %[old],%[u],%[c]\n"
194 old = atomic_cmpxchg((v), c, c + (a)); 194 " addl %[old],%[a],%[new]\n"
195 if (likely(old == c)) 195 " bne %[c],2f\n"
196 break; 196 " stl_c %[new],%[mem]\n"
197 c = old; 197 " beq %[new],3f\n"
198 } 198 "2:\n"
199 return c; 199 ".subsection 2\n"
200 "3: br 1b\n"
201 ".previous"
202 : [old] "=&r"(old), [new] "=&r"(new), [c] "=&r"(c)
203 : [mem] "m"(*v), [a] "rI"(a), [u] "rI"((long)u)
204 : "memory");
205 smp_mb();
206 return old;
200} 207}
201 208
202 209
@@ -207,21 +214,28 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
207 * @u: ...unless v is equal to u. 214 * @u: ...unless v is equal to u.
208 * 215 *
209 * Atomically adds @a to @v, so long as it was not @u. 216 * Atomically adds @a to @v, so long as it was not @u.
210 * Returns the old value of @v. 217 * Returns true iff @v was not @u.
211 */ 218 */
212static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u) 219static __inline__ int atomic64_add_unless(atomic64_t *v, long a, long u)
213{ 220{
214 long c, old; 221 long c, tmp;
215 c = atomic64_read(v); 222 smp_mb();
216 for (;;) { 223 __asm__ __volatile__(
217 if (unlikely(c == (u))) 224 "1: ldq_l %[tmp],%[mem]\n"
218 break; 225 " cmpeq %[tmp],%[u],%[c]\n"
219 old = atomic64_cmpxchg((v), c, c + (a)); 226 " addq %[tmp],%[a],%[tmp]\n"
220 if (likely(old == c)) 227 " bne %[c],2f\n"
221 break; 228 " stq_c %[tmp],%[mem]\n"
222 c = old; 229 " beq %[tmp],3f\n"
223 } 230 "2:\n"
224 return c != (u); 231 ".subsection 2\n"
232 "3: br 1b\n"
233 ".previous"
234 : [tmp] "=&r"(tmp), [c] "=&r"(c)
235 : [mem] "m"(*v), [a] "rI"(a), [u] "rI"(u)
236 : "memory");
237 smp_mb();
238 return !c;
225} 239}
226 240
227#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0) 241#define atomic64_inc_not_zero(v) atomic64_add_unless((v), 1, 0)