From 1839cdbe268f4b19ac8e81ae78548f5c78e0c641 Mon Sep 17 00:00:00 2001 From: Simon Wilkinson Date: Mon, 21 Jan 2013 16:50:25 -0500 Subject: [PATCH] rx: atomic bit ops Add rx_atomic_test_bit, rx_atomic_set_bit, and rx_atomic_clear_bit to provide bitwise operations over atomic types. These allow the use of atomic flag variables. Uses native platform atomic operations wherever these are available, otherwise falls back to our 'standard' MUTEX based implementation. LICENSE BSD Change-Id: I161631b2408e85f757ff04bf831a631ccb1f930d Reviewed-on: http://gerrit.openafs.org/8936 Reviewed-by: Marc Dionne Tested-by: BuildBot Reviewed-by: Derrick Brashear --- src/rx/rx_atomic.h | 181 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) diff --git a/src/rx/rx_atomic.h b/src/rx/rx_atomic.h index 0fcc429..83a52b4 100644 --- a/src/rx/rx_atomic.h +++ b/src/rx/rx_atomic.h @@ -77,6 +77,34 @@ rx_atomic_sub(rx_atomic_t *atomic, int change) { InterlockedExchangeAdd(&atomic->var, 0 - change); } +static_inline int +rx_atomic_test_bit(rx_atomic_t *atomic, int bit) { + return ((unsigned int) rx_atomic_read(atomic) & 1<var, bit); +} + +static_inline void +rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) { + (void) InterlockedBitTestAndReset(&atomic->var, bit); +} + +static_inline int +rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) { + return InterlockedBitTestAndSet(&atomic->var, bit); +} + +static_inline int +rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) { + return InterlockedBitTestAndReset(&atomic->var, bit); +} + #elif defined(AFS_AIX61_ENV) || defined(AFS_USR_AIX61_ENV) #include @@ -129,6 +157,31 @@ rx_atomic_sub(rx_atomic_t *atomic, int change) { fetch_and_add(&atomic->var, -change); } +static_inline int +rx_atomic_test_bit(rx_atomic_t *atomic, int bit) { + return ((unsigned int) rx_atomic_read(atomic) & 1<var, 1<var, ~(1<var, (1<var, ~(1< @@ -136,6 +189,8 @@ rx_atomic_sub(rx_atomic_t *atomic, int change) { #define OSAtomicIncrement32 OSIncrementAtomic #define OSAtomicAdd32 OSAddAtomic #define OSAtomicDecrement32 OSDecrementAtomic +#define OSAtomicOr32 OSBitOrAtomic +#define OSAtomicAnd32 OSBitAndAtomic #endif typedef struct { @@ -186,6 +241,35 @@ static_inline void rx_atomic_sub(rx_atomic_t *atomic, int change) { OSAtomicAdd32(0 - change, &atomic->var); } + +static_inline int +rx_atomic_test_bit(rx_atomic_t *atomic, int bit) { + return ((unsigned int) rx_atomic_read(atomic) & 1<var); +} + +static_inline void +rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) { + OSAtomicAnd32(~(1<var); +} + +static_inline int +rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) { + return ((OSAtomicOr32Orig(1<var) & 1<var) & 1< @@ -200,6 +284,11 @@ typedef atomic_t rx_atomic_t; #define rx_atomic_dec(X) atomic_dec(X) #define rx_atomic_dec_and_read(X) atomic_dec_return(X) #define rx_atomic_sub(X, V) atomic_sub(V, X) +#define rx_atomic_test_bit(X, B) test_bit(B, (unsigned long *) &(X)->counter) +#define rx_atomic_set_bit(X, B) set_bit(B, (unsigned long *) &(X)->counter) +#define rx_atomic_clear_bit(X, B) clear_bit(B, (unsigned long *) &(X)->counter) +#define rx_atomic_test_and_set_bit(X, B) test_and_set_bit(B, (unsigned long *) &(X)->counter) +#define rx_atomic_test_and_clear_bit(X, B) test_and_clear_bit(B, (unsigned long *) &(X)->counter) #elif defined(AFS_SUN510_ENV) || (defined(AFS_SUN5_ENV) && defined(KERNEL) && !defined(UKERNEL)) @@ -265,6 +354,31 @@ rx_atomic_sub(rx_atomic_t *atomic, int change) { atomic_add_32(&atomic->var, 0 - change); } +static_inline int +rx_atomic_test_bit(rx_atomic_t *atomic, int bit) { + return ((unsigned int) rx_atomic_read(atomic) & 1<var, 1<var, ~(1<var, bit) == -1); +} + +static_inline int +rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) { + return (atomic_clear_long_excl(&atomic->var, bit) == 0); +} + #elif defined(__GNUC__) && defined(HAVE_SYNC_FETCH_AND_ADD) typedef struct { @@ -316,6 +430,31 @@ rx_atomic_sub(rx_atomic_t *atomic, int change) { (void)__sync_fetch_and_sub(&atomic->var, change); } +static_inline int +rx_atomic_test_bit(rx_atomic_t *atomic, int bit) { + return ((unsigned int) rx_atomic_read(atomic) & 1<var, 1<var, ~(1<var, 1<var, ~(1<var |= (1<var &= ~(1<var; + atomic->var |= 1<var; + atomic->var &= ~(1<