* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifndef OPENAFS_RX_ATOMIC_H
+#define OPENAFS_RX_ATOMIC_H 1
+
#define RX_ATOMIC_INIT(i) { (i) }
#ifdef AFS_NT40_ENV
typedef struct {
+ volatile int var;
+} rx_atomic_t;
+
+static_inline void
+rx_atomic_set(rx_atomic_t *atomic, int val) {
+ atomic->var = val;
+}
+
+static_inline int
+rx_atomic_read(rx_atomic_t *atomic) {
+ return atomic->var;
+}
+
+static_inline void
+rx_atomic_inc(rx_atomic_t *atomic) {
+ InterlockedIncrement(&atomic->var);
+}
+
+static_inline int
+rx_atomic_inc_and_read(rx_atomic_t *atomic) {
+ return InterlockedIncrement(&atomic->var);
+}
+
+static_inline void
+rx_atomic_add(rx_atomic_t *atomic, int change) {
+ InterlockedExchangeAdd(&atomic->var, change);
+}
+
+static_inline int
+rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
+ return InterlockedExchangeAdd(&atomic->var, change) + change;
+}
+
+static_inline void
+rx_atomic_dec(rx_atomic_t *atomic) {
+ InterlockedDecrement(&atomic->var);
+}
+
+static_inline int
+rx_atomic_dec_and_read(rx_atomic_t *atomic) {
+ return InterlockedDecrement(&atomic->var);
+}
+
+static_inline void
+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<<bit) != 0;
+}
+
+/* No InterlockedOr or InterlockedAnd on ix86, so just use the
+ * BitTest functions */
+
+static_inline void
+rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
+ (void) InterlockedBitTestAndSet(&atomic->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 <sys/atomic_op.h>
+
+typedef struct {
volatile int var;
} rx_atomic_t;
static_inline void
rx_atomic_set(rx_atomic_t *atomic, int val) {
- atomic->var = val;
+ atomic->var = val;
}
static_inline int
rx_atomic_read(rx_atomic_t *atomic) {
- return atomic->var;
+ return atomic->var;
}
static_inline void
rx_atomic_inc(rx_atomic_t *atomic) {
- InterlockedIncrement(&atomic->var);
+ fetch_and_add(&atomic->var, 1);
}
static_inline int
rx_atomic_inc_and_read(rx_atomic_t *atomic) {
- return InterlockedIncrement(&atomic->var);
+ return (fetch_and_add(&atomic->var, 1) + 1);
}
static_inline void
rx_atomic_add(rx_atomic_t *atomic, int change) {
- InterlockedExchangeAdd(&atomic->var, change);
+ fetch_and_add(&atomic->var, change);
+}
+
+static_inline int
+rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
+ return (fetch_and_add(&atomic->var, change) + change);
}
static_inline void
rx_atomic_dec(rx_atomic_t *atomic) {
- InterlockedDecrement(&atomic->var);
+ fetch_and_add(&atomic->var, -1);
+}
+
+static_inline int
+rx_atomic_dec_and_read(rx_atomic_t *atomic) {
+ return (fetch_and_add(&atomic->var, -1) - 1);
}
static_inline void
rx_atomic_sub(rx_atomic_t *atomic, int change) {
- InterlockedExchangeAdd(&atomic->var, 0 - 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<<bit) != 0;
+}
+
+static_inline void
+rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
+ fetch_and_or(&atomic->var, 1<<bit);
+}
+
+static_inline void
+rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
+ fetch_and_and(&atomic->var, ~(1<<bit));
+}
+
+static_inline int
+rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
+ return (fetch_and_or(&atomic->var, (1<<bit)) & 1<<bit) != 0;
+}
+
+static_inline int
+rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
+ return (fetch_and_and(&atomic->var, ~(1<<bit)) & 1<<bit) != 0;
}
#elif defined(AFS_DARWIN80_ENV) || defined(AFS_USR_DARWIN80_ENV)
-#include <libkern/OSAtomic.h>
+# if (defined(AFS_DARWIN160_ENV) || defined(AFS_USR_DARWIN160_ENV)) && !defined(KERNEL)
+# define OSATOMIC_USE_INLINED 1
+# endif
+
+# include <libkern/OSAtomic.h>
+
+# if defined(KERNEL) && !defined(UKERNEL)
+static_inline int
+OSAtomicIncrement32(volatile int *value)
+{
+ return OSIncrementAtomic(value) + 1;
+}
+
+static_inline int
+OSAtomicAdd32(int amount, volatile int *value)
+{
+ return OSAddAtomic(amount, value) + amount;
+}
+
+static_inline int
+OSAtomicDecrement32(volatile int *value)
+{
+ return OSDecrementAtomic(value) - 1;
+}
+
+static_inline unsigned int
+OSAtomicOr32(unsigned int mask, volatile unsigned int *value)
+{
+ return OSBitOrAtomic(mask, value) | mask;
+}
+
+static_inline unsigned int
+OSAtomicAnd32(unsigned int mask, volatile unsigned int *value)
+{
+ return OSBitAndAtomic(mask, value) & mask;
+}
+#define OSAtomicOr32Orig OSBitOrAtomic
+#define OSAtomicAnd32Orig OSBitAndAtomic
+# endif
+
typedef struct {
- volatile int var;
+ volatile int var;
} rx_atomic_t;
static_inline void
rx_atomic_set(rx_atomic_t *atomic, int val) {
- atomic->var = val;
+ atomic->var = val;
}
static_inline int
rx_atomic_read(rx_atomic_t *atomic) {
- return atomic->var;
+ return atomic->var;
}
static_inline void
rx_atomic_inc(rx_atomic_t *atomic) {
- OSAtomicIncrement32(&atomic->var);
+ OSAtomicIncrement32(&atomic->var);
}
static_inline int
rx_atomic_inc_and_read(rx_atomic_t *atomic) {
- return OSAtomicIncrement32(&atomic->var);
+ return OSAtomicIncrement32(&atomic->var);
}
static_inline void
rx_atomic_add(rx_atomic_t *atomic, int change) {
- OSAtomicAdd32(change, &atomic->var);
+ OSAtomicAdd32(change, &atomic->var);
+}
+
+static_inline int
+rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
+ return OSAtomicAdd32(change, &atomic->var);
}
static_inline void
rx_atomic_dec(rx_atomic_t *atomic) {
- OSAtomicDecrement32(&atomic->var);
+ OSAtomicDecrement32(&atomic->var);
+}
+
+static_inline int
+rx_atomic_dec_and_read(rx_atomic_t *atomic) {
+ return OSAtomicDecrement32(&atomic->var);
}
static_inline void
rx_atomic_sub(rx_atomic_t *atomic, int change) {
- OSAtomicAdd32(0 - change, &atomic->var);
+ 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<<bit) != 0;
+}
+
+static_inline void
+rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
+ OSAtomicOr32(1<<bit, (volatile uint32_t *)&atomic->var);
+}
+
+static_inline void
+rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
+ OSAtomicAnd32(~(1<<bit), (volatile uint32_t *)&atomic->var);
+}
+
+static_inline int
+rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
+ return ((OSAtomicOr32Orig(1<<bit, (volatile uint32_t *)&atomic->var) & 1<<bit)
+ != 0);
}
-#elif defined(AFS_LINUX20_ENV) && defined(KERNEL)
+
+static_inline int
+rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
+ return ((OSAtomicAnd32Orig(~(1<<bit),
+ (volatile uint32_t *)&atomic->var) & 1<<bit)
+ != 0);
+}
+
+#elif defined(AFS_LINUX26_ENV) && defined(KERNEL)
#include <asm/atomic.h>
typedef atomic_t rx_atomic_t;
-#define rx_atomic_set(X) atomic_set(X)
+#define rx_atomic_set(X, V) atomic_set(X, V)
#define rx_atomic_read(X) atomic_read(X)
#define rx_atomic_inc(X) atomic_inc(X)
#define rx_atomic_inc_and_read(X) atomic_inc_return(X)
-#define rx_atomic_add(X, V) atomic_add(X, V)
+#define rx_atomic_add(X, V) atomic_add(V, X)
+#define rx_atomic_add_and_read(X, V) atomic_add_return(V, X)
#define rx_atomic_dec(X) atomic_dec(X)
-#define rx_atomic_sub(X, V) atomic_sub(X, V)
+#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))
+
+# if defined(KERNEL) && !defined(UKERNEL)
+# include <sys/atomic.h>
+# else
+# include <atomic.h>
+# endif
+
+#ifndef AFS_SUN510_ENV
+# define atomic_inc_32(X) atomic_add_32((X), 1)
+# define atomic_inc_32_nv(X) atomic_add_32_nv((X), 1)
+# define atomic_dec_32(X) atomic_add_32((X), -1)
+# define atomic_dec_32_nv(X) atomic_add_32_nv((X), -1)
+#endif
-#elif defined(AFS_SUN58_ENV)
typedef struct {
- volatile int var;
+ volatile unsigned int var;
} rx_atomic_t;
static_inline void
rx_atomic_set(rx_atomic_t *atomic, int val) {
- atomic->var = val;
+ atomic->var = val;
}
static_inline int
rx_atomic_read(rx_atomic_t *atomic) {
- return atomic->var;
+ return atomic->var;
}
static_inline void
rx_atomic_inc(rx_atomic_t *atomic) {
- atomic_inc_32(&atomic->var);
+ atomic_inc_32(&atomic->var);
}
static_inline int
rx_atomic_inc_and_read(rx_atomic_t *atomic) {
- return atomic_inc_32_nv(&atomic->var);
+ return atomic_inc_32_nv(&atomic->var);
}
static_inline void
rx_atomic_add(rx_atomic_t *atomic, int change) {
- atomic_add_32(&atomic->var, change);
+ atomic_add_32(&atomic->var, change);
+}
+
+static_inline int
+rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
+ return atomic_add_32_nv(&atomic->var, change);
}
static_inline void
rx_atomic_dec(rx_atomic_t *atomic) {
- atomic_dec_32(&atomic->var);
+ atomic_dec_32(&atomic->var);
+}
+
+static_inline int
+rx_atomic_dec_and_read(rx_atomic_t *atomic) {
+ return atomic_dec_32_nv(&atomic->var);
}
static_inline void
rx_atomic_sub(rx_atomic_t *atomic, int change) {
- atomic_add_32(&object, 0 - 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<<bit) != 0;
+}
+
+static_inline void
+rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
+ atomic_or_32(&atomic->var, 1<<bit);
+}
+
+static_inline void
+rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
+ atomic_and_32(&atomic->var, ~(1<<bit));
+}
+
+static_inline int
+rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
+ return (atomic_set_long_excl(&atomic->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)
static_inline void
rx_atomic_set(rx_atomic_t *atomic, int val) {
- atomic->var = val;
+ atomic->var = val;
}
static_inline int
rx_atomic_read(rx_atomic_t *atomic) {
- return atomic->var;
+ return atomic->var;
}
static_inline void
rx_atomic_inc(rx_atomic_t *atomic) {
- (void)__sync_fetch_and_add(&atomic->var, 1);
+ (void)__sync_fetch_and_add(&atomic->var, 1);
}
static_inline int
rx_atomic_inc_and_read(rx_atomic_t *atomic) {
- return __sync_add_and_fetch(&atomic->var, 1);
+ return __sync_add_and_fetch(&atomic->var, 1);
}
static_inline void
rx_atomic_add(rx_atomic_t *atomic, int change) {
- (void)__sync_fetch_and_add(&atomic->var, change);
+ (void)__sync_fetch_and_add(&atomic->var, change);
+}
+
+static_inline int
+rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
+ return __sync_fetch_and_add(&atomic->var, change);
}
static_inline void
rx_atomic_dec(rx_atomic_t *atomic) {
- (void)__sync_fetch_and_sub(&atomic->var, 1);
+ (void)__sync_fetch_and_sub(&atomic->var, 1);
+}
+
+static_inline int
+rx_atomic_dec_and_read(rx_atomic_t *atomic) {
+ return __sync_sub_and_fetch(&atomic->var, 1);
}
static_inline void
rx_atomic_sub(rx_atomic_t *atomic, int change) {
- (void)__sync_fetch_and_sub(&atomic->var, 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<<bit) != 0;
+}
+
+static_inline void
+rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
+ (void)__sync_fetch_and_or(&atomic->var, 1<<bit);
+}
+
+static_inline void
+rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
+ (void)__sync_fetch_and_and(&atomic->var, ~(1<<bit));
+}
+
+static_inline int
+rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
+ return (__sync_fetch_and_or(&atomic->var, 1<<bit) & 1<<bit) != 0;
+}
+
+static_inline int
+rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
+ return (__sync_fetch_and_and(&atomic->var, ~(1<<bit)) & 1<<bit) != 0;
}
#else
MUTEX_EXIT(&rx_atomic_mutex);
}
+static_inline int
+rx_atomic_add_and_read(rx_atomic_t *atomic, int change) {
+ int retval;
+
+ MUTEX_ENTER(&rx_atomic_mutex);
+ atomic->var += change;
+ retval = atomic->var;
+ MUTEX_EXIT(&rx_atomic_mutex);
+
+ return retval;
+}
+
static_inline void
rx_atomic_dec(rx_atomic_t *atomic) {
MUTEX_ENTER(&rx_atomic_mutex);
MUTEX_EXIT(&rx_atomic_mutex);
}
+static_inline int
+rx_atomic_dec_and_read(rx_atomic_t *atomic) {
+ int retval;
+ MUTEX_ENTER(&rx_atomic_mutex);
+ atomic->var--;
+ retval = atomic->var;
+ MUTEX_EXIT(&rx_atomic_mutex);
+ return retval;
+}
+
+
static_inline void
rx_atomic_sub(rx_atomic_t *atomic, int change) {
MUTEX_ENTER(&rx_atomic_mutex);
atomic->var -= change;
+ MUTEX_EXIT(&rx_atomic_mutex);
+}
+
+static_inline int
+rx_atomic_test_bit(rx_atomic_t *atomic, int bit) {
+ return ((unsigned int) rx_atomic_read(atomic) & 1<<bit) != 0;
+}
+
+static_inline void
+rx_atomic_set_bit(rx_atomic_t *atomic, int bit) {
+ MUTEX_ENTER(&rx_atomic_mutex);
+ atomic->var |= (1<<bit);
+ MUTEX_EXIT(&rx_atomic_mutex);
+}
+
+static_inline void
+rx_atomic_clear_bit(rx_atomic_t *atomic, int bit) {
+ MUTEX_ENTER(&rx_atomic_mutex);
+ atomic->var &= ~(1<<bit);
+ MUTEX_EXIT(&rx_atomic_mutex);
+}
+
+static_inline int
+rx_atomic_test_and_set_bit(rx_atomic_t *atomic, int bit) {
+ int val;
+
MUTEX_ENTER(&rx_atomic_mutex);
+ val = atomic->var;
+ atomic->var |= 1<<bit;
+ MUTEX_EXIT(&rx_atomic_mutex);
+
+ return (val & 1<<bit) == 1<<bit;
}
+static_inline int
+rx_atomic_test_and_clear_bit(rx_atomic_t *atomic, int bit) {
+ int val;
+
+ MUTEX_ENTER(&rx_atomic_mutex);
+ val = atomic->var;
+ atomic->var &= ~(1<<bit);
+ MUTEX_EXIT(&rx_atomic_mutex);
+
+ return (val & 1<<bit) == 1<<bit;
+}
+#endif
+
#endif