aboutsummaryrefslogtreecommitdiff
path: root/arch/tile/include/asm/atomic.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/tile/include/asm/atomic.h')
-rw-r--r--arch/tile/include/asm/atomic.h99
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 */