diff options
author | Arun Sharma <asharma@fb.com> | 2011-07-26 16:09:07 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-07-26 16:49:47 -0700 |
commit | f24219b4e90cf70ec4a211b17fbabc725a0ddf3c (patch) | |
tree | c1c753bd425d61a5094995d9835b23b46383d9b2 /arch/avr32 | |
parent | 60063497a95e716c9a689af3be2687d261f115b4 (diff) |
atomic: move atomic_add_unless to generic code
This is in preparation for more generic atomic primitives based on
__atomic_add_unless.
Signed-off-by: Arun Sharma <asharma@fb.com>
Signed-off-by: Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>
Reviewed-by: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: David Miller <davem@davemloft.net>
Acked-by: Mike Frysinger <vapier@gentoo.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/avr32')
-rw-r--r-- | arch/avr32/include/asm/atomic.h | 57 |
1 files changed, 25 insertions, 32 deletions
diff --git a/arch/avr32/include/asm/atomic.h b/arch/avr32/include/asm/atomic.h index f229c3849f0..dc6c3a41a2d 100644 --- a/arch/avr32/include/asm/atomic.h +++ b/arch/avr32/include/asm/atomic.h @@ -78,70 +78,63 @@ static inline int atomic_add_return(int i, atomic_t *v) /* * atomic_sub_unless - sub unless the number is a given value * @v: pointer of type atomic_t - * @a: the amount to add to v... + * @a: the amount to subtract from v... * @u: ...unless v is equal to u. * - * If the atomic value v is not equal to u, this function subtracts a - * from v, and returns non zero. If v is equal to u then it returns - * zero. This is done as an atomic operation. + * Atomically subtract @a from @v, so long as it was not @u. + * Returns the old value of @v. */ -static inline int atomic_sub_unless(atomic_t *v, int a, int u) +static inline void atomic_sub_unless(atomic_t *v, int a, int u) { - int tmp, result = 0; + int tmp; asm volatile( "/* atomic_sub_unless */\n" "1: ssrf 5\n" - " ld.w %0, %3\n" - " cp.w %0, %5\n" + " ld.w %0, %2\n" + " cp.w %0, %4\n" " breq 1f\n" - " sub %0, %4\n" - " stcond %2, %0\n" + " sub %0, %3\n" + " stcond %1, %0\n" " brne 1b\n" - " mov %1, 1\n" "1:" - : "=&r"(tmp), "=&r"(result), "=o"(v->counter) - : "m"(v->counter), "rKs21"(a), "rKs21"(u), "1"(result) + : "=&r"(tmp), "=o"(v->counter) + : "m"(v->counter), "rKs21"(a), "rKs21"(u) : "cc", "memory"); - - return result; } /* - * atomic_add_unless - add unless the number is a given value + * __atomic_add_unless - add unless the number is a given value * @v: pointer of type atomic_t * @a: the amount to add to v... * @u: ...unless v is equal to u. * - * If the atomic value v is not equal to u, this function adds a to v, - * and returns non zero. If v is equal to u then it returns zero. This - * is done as an atomic operation. + * Atomically adds @a to @v, so long as it was not @u. + * Returns the old value of @v. */ -static inline int atomic_add_unless(atomic_t *v, int a, int u) +static inline int __atomic_add_unless(atomic_t *v, int a, int u) { - int tmp, result; + int tmp, old = atomic_read(v); if (__builtin_constant_p(a) && (a >= -1048575) && (a <= 1048576)) - result = atomic_sub_unless(v, -a, u); + atomic_sub_unless(v, -a, u); else { - result = 0; asm volatile( - "/* atomic_add_unless */\n" + "/* __atomic_add_unless */\n" "1: ssrf 5\n" - " ld.w %0, %3\n" - " cp.w %0, %5\n" + " ld.w %0, %2\n" + " cp.w %0, %4\n" " breq 1f\n" - " add %0, %4\n" - " stcond %2, %0\n" + " add %0, %3\n" + " stcond %1, %0\n" " brne 1b\n" - " mov %1, 1\n" "1:" - : "=&r"(tmp), "=&r"(result), "=o"(v->counter) - : "m"(v->counter), "r"(a), "ir"(u), "1"(result) + : "=&r"(tmp), "=o"(v->counter) + : "m"(v->counter), "r"(a), "ir"(u) : "cc", "memory"); } - return result; + return old; } /* |