summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src/locking.h
diff options
context:
space:
mode:
Diffstat (limited to 'libglusterfs/src/locking.h')
-rw-r--r--libglusterfs/src/locking.h59
1 files changed, 50 insertions, 9 deletions
diff --git a/libglusterfs/src/locking.h b/libglusterfs/src/locking.h
index 24edf9aed44..71b6a286e6c 100644
--- a/libglusterfs/src/locking.h
+++ b/libglusterfs/src/locking.h
@@ -12,7 +12,8 @@
#define _LOCKING_H
#include <pthread.h>
-#ifdef GF_DARWIN_HOST_OS
+
+#if defined (GF_DARWIN_HOST_OS)
#include <libkern/OSAtomic.h>
#define pthread_spinlock_t OSSpinLock
#define pthread_spin_lock(l) OSSpinLockLock(l)
@@ -21,23 +22,63 @@
#define pthread_spin_init(l, v) (*l = v)
#endif
+#if defined (HAVE_SPINLOCK)
+
+typedef union {
+ pthread_spinlock_t spinlock;
+ pthread_mutex_t mutex;
+} gf_lock_t;
+
+#if !defined(LOCKING_IMPL)
+extern int use_spinlocks;
+
+/*
+ * Using a dispatch table would be unpleasant because we're dealing with two
+ * different types. If the dispatch contains direct pointers to pthread_xx
+ * or mutex_xxx then we have to hope that every possible union alternative
+ * starts at the same address as the union itself. I'm old enough to remember
+ * compilers where this was not the case (for alignment reasons) so I'm a bit
+ * paranoid about that. Also, I don't like casting arguments through "void *"
+ * which we'd also have to do to avoid type errors. The other alternative would
+ * be to define actual functions which pick out the right union member, and put
+ * those in the dispatch tables. Now we have a pointer dereference through the
+ * dispatch table plus a function call, which is likely to be worse than the
+ * branching here from the ?: construct. If it were a clear win it might be
+ * worth the extra complexity, but for now this way seems preferable.
+ */
+
+#define LOCK_INIT(x) (use_spinlocks \
+ ? pthread_spin_init (&((x)->spinlock), 0) \
+ : pthread_mutex_init (&((x)->mutex), 0))
+
+#define LOCK(x) (use_spinlocks \
+ ? pthread_spin_lock (&((x)->spinlock)) \
+ : pthread_mutex_lock (&((x)->mutex)))
+
+#define TRY_LOCK(x) (use_spinlocks \
+ ? pthread_spin_trylock (&((x)->spinlock)) \
+ : pthread_mutex_trylock (&((x)->mutex)))
-#if HAVE_SPINLOCK
-#define LOCK_INIT(x) pthread_spin_init (x, 0)
-#define LOCK(x) pthread_spin_lock (x)
-#define TRY_LOCK(x) pthread_spin_trylock (x)
-#define UNLOCK(x) pthread_spin_unlock (x)
-#define LOCK_DESTROY(x) pthread_spin_destroy (x)
+#define UNLOCK(x) (use_spinlocks \
+ ? pthread_spin_unlock (&((x)->spinlock)) \
+ : pthread_mutex_unlock (&((x)->mutex)))
+
+#define LOCK_DESTROY(x) (use_spinlocks \
+ ? pthread_spin_destroy (&((x)->spinlock)) \
+ : pthread_mutex_destroy (&((x)->mutex)))
+
+#endif
-typedef pthread_spinlock_t gf_lock_t;
#else
+
+typedef pthread_mutex_t gf_lock_t;
+
#define LOCK_INIT(x) pthread_mutex_init (x, 0)
#define LOCK(x) pthread_mutex_lock (x)
#define TRY_LOCK(x) pthread_mutex_trylock (x)
#define UNLOCK(x) pthread_mutex_unlock (x)
#define LOCK_DESTROY(x) pthread_mutex_destroy (x)
-typedef pthread_mutex_t gf_lock_t;
#endif /* HAVE_SPINLOCK */