diff options
author | jhb <jhb@FreeBSD.org> | 2000-10-05 22:19:50 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2000-10-05 22:19:50 +0000 |
commit | 4cc9f87fa24c6b90c1d657b2704432cbea1b7bea (patch) | |
tree | 450dfcb1e8c87b4bdd8c5ff6f9366ee352c20736 /sys | |
parent | f1af81aa6915279026a28a9737be7ab17bfbf3e9 (diff) | |
download | FreeBSD-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.h | 42 | ||||
-rw-r--r-- | sys/amd64/include/atomic.h | 36 | ||||
-rw-r--r-- | sys/i386/include/atomic.h | 36 |
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_ */ |