summaryrefslogtreecommitdiffstats
path: root/sys/alpha/include
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2000-10-05 22:19:50 +0000
committerjhb <jhb@FreeBSD.org>2000-10-05 22:19:50 +0000
commit4cc9f87fa24c6b90c1d657b2704432cbea1b7bea (patch)
tree450dfcb1e8c87b4bdd8c5ff6f9366ee352c20736 /sys/alpha/include
parentf1af81aa6915279026a28a9737be7ab17bfbf3e9 (diff)
downloadFreeBSD-src-4cc9f87fa24c6b90c1d657b2704432cbea1b7bea.zip
FreeBSD-src-4cc9f87fa24c6b90c1d657b2704432cbea1b7bea.tar.gz
Add atomic_readandclear_int and atomic_readandclear_long.
Diffstat (limited to 'sys/alpha/include')
-rw-r--r--sys/alpha/include/atomic.h42
1 files changed, 42 insertions, 0 deletions
diff --git a/sys/alpha/include/atomic.h b/sys/alpha/include/atomic.h
index d6869b2..3532a06 100644
--- a/sys/alpha/include/atomic.h
+++ b/sys/alpha/include/atomic.h
@@ -116,6 +116,26 @@ static __inline void atomic_subtract_32(volatile u_int32_t *p, u_int32_t v)
: "memory");
}
+static __inline u_int32_t atomic_readandclear_32(volatile u_int32_t *addr)
+{
+ u_int32_t result,temp;
+
+ __asm __volatile (
+ "wmb\n" /* ensure pending writes have drained */
+ "1:\tldl_l %0,%3\n\t" /* load current value, asserting lock */
+ "ldiq %1,0\n\t" /* value to store */
+ "stl_c %1,%2\n\t" /* attempt to store */
+ "beq %1,2f\n\t" /* if the store failed, spin */
+ "br 3f\n" /* it worked, exit */
+ "2:\tbr 1b\n" /* *addr not updated, loop */
+ "3:\tmb\n" /* it worked */
+ : "=&r"(result), "=&r"(temp), "=m" (*addr)
+ : "m"(*addr)
+ : "memory");
+
+ return result;
+}
+
static __inline void atomic_set_64(volatile u_int64_t *p, u_int64_t v)
{
u_int64_t temp;
@@ -188,6 +208,26 @@ static __inline void atomic_subtract_64(volatile u_int64_t *p, u_int64_t v)
: "memory");
}
+static __inline u_int64_t atomic_readandclear_64(volatile u_int64_t *addr)
+{
+ u_int64_t result,temp;
+
+ __asm __volatile (
+ "wmb\n" /* ensure pending writes have drained */
+ "1:\tldq_l %0,%3\n\t" /* load current value, asserting lock */
+ "ldiq %1,0\n\t" /* value to store */
+ "stq_c %1,%2\n\t" /* attempt to store */
+ "beq %1,2f\n\t" /* if the store failed, spin */
+ "br 3f\n" /* it worked, exit */
+ "2:\tbr 1b\n" /* *addr not updated, loop */
+ "3:\tmb\n" /* it worked */
+ : "=&r"(result), "=&r"(temp), "=m" (*addr)
+ : "m"(*addr)
+ : "memory");
+
+ return result;
+}
+
#define atomic_set_char atomic_set_8
#define atomic_clear_char atomic_clear_8
#define atomic_add_char atomic_add_8
@@ -202,11 +242,13 @@ static __inline void atomic_subtract_64(volatile u_int64_t *p, u_int64_t v)
#define atomic_clear_int atomic_clear_32
#define atomic_add_int atomic_add_32
#define atomic_subtract_int atomic_subtract_32
+#define atomic_readandclear_int atomic_readandclear_32
#define atomic_set_long atomic_set_64
#define atomic_clear_long atomic_clear_64
#define atomic_add_long atomic_add_64
#define atomic_subtract_long atomic_subtract_64
+#define atomic_readandclear_long atomic_readandclear_64
/*
* Atomically compare the value stored at *p with cmpval and if the
OpenPOWER on IntegriCloud