Define OSATOMIC_USE_INLINED to get usable atomics on DARWIN
[openafs.git] / src / rx / rx_atomic.h
index e920afc..5bf35fe 100644 (file)
@@ -57,6 +57,11 @@ 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);
@@ -72,14 +77,128 @@ 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;
+}
+
+static_inline int
+rx_atomic_read(rx_atomic_t *atomic) {
+    return atomic->var;
+}
+
+static_inline void
+rx_atomic_inc(rx_atomic_t *atomic) {
+    fetch_and_add(&atomic->var, 1);
+}
+
+static_inline int
+rx_atomic_inc_and_read(rx_atomic_t *atomic) {
+    return (fetch_and_add(&atomic->var, 1) + 1);
+}
+
+static_inline void
+rx_atomic_add(rx_atomic_t *atomic, int 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) {
+    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) {
+    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(KERNEL) && !defined(UKERNEL)
-#define OSAtomicIncrement32 OSIncrementAtomic
-#define OSAtomicAdd32 OSAddAtomic
-#define OSAtomicDecrement32 OSDecrementAtomic
-#endif
+# if defined (AFS_DARWIN160_ENV) || defined(AFS_USR_DARWIN160_ENV)
+#  define OSATOMIC_USE_INLINED 1
+# else
+
+#  if defined(KERNEL) && !defined(UKERNEL)
+#   define OSAtomicIncrement32 OSIncrementAtomic
+#   define OSAtomicAdd32 OSAddAtomic
+#   define OSAtomicDecrement32 OSDecrementAtomic
+#   define OSAtomicOr32 OSBitOrAtomic
+#   define OSAtomicAnd32 OSBitAndAtomic
+#  endif
+
+# endif /* end defined DARWIN160 */
+
+# include <libkern/OSAtomic.h>
 
 typedef struct {
     volatile int var;
@@ -110,6 +229,11 @@ rx_atomic_add(rx_atomic_t *atomic, int change) {
     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);
@@ -124,20 +248,56 @@ static_inline void
 rx_atomic_sub(rx_atomic_t *atomic, int change) {
     OSAtomicAdd32(0 - change, &atomic->var);
 }
-#elif defined(AFS_LINUX20_ENV) && defined(KERNEL)
+
+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);
+}
+
+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(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_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_SUN58_ENV) && defined(KERNEL) && !defined(UKERNEL))
+#elif defined(AFS_SUN510_ENV) || (defined(AFS_SUN5_ENV) && defined(KERNEL) && !defined(UKERNEL))
 
 # if defined(KERNEL) && !defined(UKERNEL)
 #  include <sys/atomic.h>
@@ -145,6 +305,13 @@ typedef atomic_t rx_atomic_t;
 #  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
+
 typedef struct {
     volatile unsigned int var;
 } rx_atomic_t;
@@ -174,6 +341,11 @@ rx_atomic_add(rx_atomic_t *atomic, int 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);
@@ -189,6 +361,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<<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)
 
 typedef struct {
@@ -220,6 +417,11 @@ rx_atomic_add(rx_atomic_t *atomic, int 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);
@@ -235,6 +437,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<<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
 
 /* If we're on a platform where we have no idea how to do atomics,
@@ -292,6 +519,18 @@ rx_atomic_add(rx_atomic_t *atomic, int change) {
     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);
@@ -317,6 +556,48 @@ rx_atomic_sub(rx_atomic_t *atomic, int 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