summaryrefslogtreecommitdiffstats
path: root/sys
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
parentf1af81aa6915279026a28a9737be7ab17bfbf3e9 (diff)
downloadFreeBSD-src-4cc9f87fa24c6b90c1d657b2704432cbea1b7bea.zip
FreeBSD-src-4cc9f87fa24c6b90c1d657b2704432cbea1b7bea.tar.gz
Add atomic_readandclear_int and atomic_readandclear_long.
Diffstat (limited to 'sys')
-rw-r--r--sys/alpha/include/atomic.h42
-rw-r--r--sys/amd64/include/atomic.h36
-rw-r--r--sys/i386/include/atomic.h36
3 files changed, 110 insertions, 4 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
diff --git a/sys/amd64/include/atomic.h b/sys/amd64/include/atomic.h
index 35a710e..b38fd83 100644
--- a/sys/amd64/include/atomic.h
+++ b/sys/amd64/include/atomic.h
@@ -46,11 +46,13 @@
* atomic_clear_int(P, V) (*(u_int*)(P) &= ~(V))
* atomic_add_int(P, V) (*(u_int*)(P) += (V))
* atomic_subtract_int(P, V) (*(u_int*)(P) -= (V))
+ * atomic_readandclear_int(P) (return *(u_int*)P; *(u_int*)P = 0;)
*
* atomic_set_long(P, V) (*(u_long*)(P) |= (V))
* atomic_clear_long(P, V) (*(u_long*)(P) &= ~(V))
* atomic_add_long(P, V) (*(u_long*)(P) += (V))
* atomic_subtract_long(P, V) (*(u_long*)(P) -= (V))
+ * atomic_readandclear_long(P) (return *(u_long*)P; *(u_long*)P = 0;)
*/
/*
@@ -63,9 +65,9 @@
*/
#if defined(KLD_MODULE)
#define ATOMIC_ASM(NAME, TYPE, OP, V) \
- extern void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v);
+ void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v);
-extern int atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src);
+int atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src);
#else /* !KLD_MODULE */
#if defined(SMP)
@@ -218,6 +220,36 @@ atomic_cmpset_ptr(volatile void *dst, void *exp, void *src)
return (
atomic_cmpset_int((volatile u_int *)dst, (u_int)exp, (u_int)src));
}
+
+static __inline u_int
+atomic_readandclear_int(volatile u_int *addr)
+{
+ u_int result;
+
+ __asm __volatile (
+ " xorl %0,%0 ; "
+ " xchgl %1,%0 ; "
+ "# atomic_readandclear_int"
+ : "=&r" (result) /* 0 (result) */
+ : "m" (*addr)); /* 1 (addr) */
+
+ return (result);
+}
+
+static __inline u_long
+atomic_readandclear_long(volatile u_long *addr)
+{
+ u_long result;
+
+ __asm __volatile (
+ " xorl %0,%0 ; "
+ " xchgl %1,%0 ; "
+ "# atomic_readandclear_int"
+ : "=&r" (result) /* 0 (result) */
+ : "m" (*addr)); /* 1 (addr) */
+
+ return (result);
+}
#endif
#endif /* ! _MACHINE_ATOMIC_H_ */
diff --git a/sys/i386/include/atomic.h b/sys/i386/include/atomic.h
index 35a710e..b38fd83 100644
--- a/sys/i386/include/atomic.h
+++ b/sys/i386/include/atomic.h
@@ -46,11 +46,13 @@
* atomic_clear_int(P, V) (*(u_int*)(P) &= ~(V))
* atomic_add_int(P, V) (*(u_int*)(P) += (V))
* atomic_subtract_int(P, V) (*(u_int*)(P) -= (V))
+ * atomic_readandclear_int(P) (return *(u_int*)P; *(u_int*)P = 0;)
*
* atomic_set_long(P, V) (*(u_long*)(P) |= (V))
* atomic_clear_long(P, V) (*(u_long*)(P) &= ~(V))
* atomic_add_long(P, V) (*(u_long*)(P) += (V))
* atomic_subtract_long(P, V) (*(u_long*)(P) -= (V))
+ * atomic_readandclear_long(P) (return *(u_long*)P; *(u_long*)P = 0;)
*/
/*
@@ -63,9 +65,9 @@
*/
#if defined(KLD_MODULE)
#define ATOMIC_ASM(NAME, TYPE, OP, V) \
- extern void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v);
+ void atomic_##NAME##_##TYPE(volatile u_##TYPE *p, u_##TYPE v);
-extern int atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src);
+int atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src);
#else /* !KLD_MODULE */
#if defined(SMP)
@@ -218,6 +220,36 @@ atomic_cmpset_ptr(volatile void *dst, void *exp, void *src)
return (
atomic_cmpset_int((volatile u_int *)dst, (u_int)exp, (u_int)src));
}
+
+static __inline u_int
+atomic_readandclear_int(volatile u_int *addr)
+{
+ u_int result;
+
+ __asm __volatile (
+ " xorl %0,%0 ; "
+ " xchgl %1,%0 ; "
+ "# atomic_readandclear_int"
+ : "=&r" (result) /* 0 (result) */
+ : "m" (*addr)); /* 1 (addr) */
+
+ return (result);
+}
+
+static __inline u_long
+atomic_readandclear_long(volatile u_long *addr)
+{
+ u_long result;
+
+ __asm __volatile (
+ " xorl %0,%0 ; "
+ " xchgl %1,%0 ; "
+ "# atomic_readandclear_int"
+ : "=&r" (result) /* 0 (result) */
+ : "m" (*addr)); /* 1 (addr) */
+
+ return (result);
+}
#endif
#endif /* ! _MACHINE_ATOMIC_H_ */
OpenPOWER on IntegriCloud