diff options
Diffstat (limited to 'arch/tile/include/asm/atomic.h')
| -rw-r--r-- | arch/tile/include/asm/atomic.h | 99 |
1 files changed, 74 insertions, 25 deletions
diff --git a/arch/tile/include/asm/atomic.h b/arch/tile/include/asm/atomic.h index b8c49f98a44..70979846076 100644 --- a/arch/tile/include/asm/atomic.h +++ b/arch/tile/include/asm/atomic.h @@ -17,10 +17,12 @@ #ifndef _ASM_TILE_ATOMIC_H #define _ASM_TILE_ATOMIC_H +#include <asm/cmpxchg.h> + #ifndef __ASSEMBLY__ #include <linux/compiler.h> -#include <asm/system.h> +#include <linux/types.h> #define ATOMIC_INIT(i) { (i) } @@ -32,7 +34,7 @@ */ static inline int atomic_read(const atomic_t *v) { - return v->counter; + return ACCESS_ONCE(v->counter); } /** @@ -112,36 +114,40 @@ static inline int atomic_read(const atomic_t *v) #define atomic_inc_and_test(v) (atomic_inc_return(v) == 0) /** - * atomic_add_negative - add and test if negative + * atomic_xchg - atomically exchange contents of memory with a new value * @v: pointer of type atomic_t - * @i: integer value to add + * @i: integer value to store in memory * - * Atomically adds @i to @v and returns true if the result is - * negative, or false when result is greater than or equal to zero. + * Atomically sets @v to @i and returns old @v */ -#define atomic_add_negative(i, v) (atomic_add_return((i), (v)) < 0) +static inline int atomic_xchg(atomic_t *v, int n) +{ + return xchg(&v->counter, n); +} /** - * atomic_inc_not_zero - increment unless the number is zero + * atomic_cmpxchg - atomically exchange contents of memory if it matches * @v: pointer of type atomic_t + * @o: old value that memory should have + * @n: new value to write to memory if it matches * - * Atomically increments @v by 1, so long as @v is non-zero. - * Returns non-zero if @v was non-zero, and zero otherwise. + * Atomically checks if @v holds @o and replaces it with @n if so. + * Returns the old value at @v. */ -#define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0) - +static inline int atomic_cmpxchg(atomic_t *v, int o, int n) +{ + return cmpxchg(&v->counter, o, n); +} -/* - * We define xchg() and cmpxchg() in the included headers. - * Note that we do not define __HAVE_ARCH_CMPXCHG, since that would imply - * that cmpxchg() is an efficient operation, which is not particularly true. +/** + * atomic_add_negative - add and test if negative + * @v: pointer of type atomic_t + * @i: integer value to add + * + * Atomically adds @i to @v and returns true if the result is + * negative, or false when result is greater than or equal to zero. */ - -/* Nonexistent functions intended to cause link errors. */ -extern unsigned long __xchg_called_with_bad_pointer(void); -extern unsigned long __cmpxchg_called_with_bad_pointer(void); - -#define tas(ptr) (xchg((ptr), 1)) +#define atomic_add_negative(i, v) (atomic_add_return((i), (v)) < 0) #endif /* __ASSEMBLY__ */ @@ -151,9 +157,52 @@ extern unsigned long __cmpxchg_called_with_bad_pointer(void); #include <asm/atomic_64.h> #endif -/* Provide the appropriate atomic_long_t definitions. */ #ifndef __ASSEMBLY__ -#include <asm-generic/atomic-long.h> -#endif + +/** + * atomic64_xchg - atomically exchange contents of memory with a new value + * @v: pointer of type atomic64_t + * @i: integer value to store in memory + * + * Atomically sets @v to @i and returns old @v + */ +static inline long long atomic64_xchg(atomic64_t *v, long long n) +{ + return xchg64(&v->counter, n); +} + +/** + * atomic64_cmpxchg - atomically exchange contents of memory if it matches + * @v: pointer of type atomic64_t + * @o: old value that memory should have + * @n: new value to write to memory if it matches + * + * Atomically checks if @v holds @o and replaces it with @n if so. + * Returns the old value at @v. + */ +static inline long long atomic64_cmpxchg(atomic64_t *v, long long o, + long long n) +{ + return cmpxchg64(&v->counter, o, n); +} + +static inline long long atomic64_dec_if_positive(atomic64_t *v) +{ + long long c, old, dec; + + c = atomic64_read(v); + for (;;) { + dec = c - 1; + if (unlikely(dec < 0)) + break; + old = atomic64_cmpxchg((v), c, dec); + if (likely(old == c)) + break; + c = old; + } + return dec; +} + +#endif /* __ASSEMBLY__ */ #endif /* _ASM_TILE_ATOMIC_H */ |
