diff options
author | Noah Watkins <noahwatkins@gmail.com> | 2013-07-20 18:41:40 -0700 |
---|---|---|
committer | Noah Watkins <noahwatkins@gmail.com> | 2013-07-20 18:41:40 -0700 |
commit | 6339abb9d707a244640a962cfe9838259ceb22ed (patch) | |
tree | 16419eed12b0f8778464b2e4aa46e5b9913bc059 | |
parent | 160a7fe793d380ea07133a66f70c961e60b578ed (diff) | |
download | ceph-6339abb9d707a244640a962cfe9838259ceb22ed.tar.gz |
spinlock: add generic spinlock implementation
Adds a ceph_spinlock_t implementation that will use pthread_spinlock_t
if available, and otherwise reverts to pthread_mutex_t. Note that this
spinlock is not intended to be used in process-shared memory.
Switches implementation in:
ceph_context
SimpleMessenger
atomic_t
Only ceph_context initialized its spinlock with PTHREAD_PROCESS_SHARED.
However, there does not appear to be any instance in which CephContext
is allocated in shared memory, and thus can use the default private
memory space behavior.
Signed-off-by: Noah Watkins <noahwatkins@gmail.com>
-rw-r--r-- | configure.ac | 16 | ||||
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/common/ceph_context.cc | 22 | ||||
-rw-r--r-- | src/common/ceph_context.h | 3 | ||||
-rw-r--r-- | src/include/atomic.h | 33 | ||||
-rw-r--r-- | src/include/spinlock.h | 62 | ||||
-rw-r--r-- | src/msg/SimpleMessenger.cc | 3 | ||||
-rw-r--r-- | src/msg/SimpleMessenger.h | 7 |
8 files changed, 115 insertions, 32 deletions
diff --git a/configure.ac b/configure.ac index 68f3af025ad..71e323c549d 100644 --- a/configure.ac +++ b/configure.ac @@ -554,6 +554,22 @@ AC_CHECK_FUNCS([pipe2]) AC_CHECK_HEADERS([sys/vfs.h sys/mount.h]) +# +# Check for pthread spinlock. +# +# NOTE: virtually everythink in Makefile.am links against the pthread +# libraries. It would be cleaner to just set LIBS and CFLAGS globally to +# include the pthread bits. +# +saved_LIBS="$LIBS" +saved_CFLAGS="$CFLAGS" +LIBS="$LIBS $PTHREAD_LIBS" +CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +AC_CHECK_FUNC([pthread_spin_init], + [AC_DEFINE(HAVE_PTHREAD_SPINLOCK, 1, [Define if you have pthread_spin_init])]) +LIBS="$saved_LIBS" +CFLAGS="$saved_CFLAGS" + # Checks for typedefs, structures, and compiler characteristics. #AC_HEADER_STDBOOL #AC_C_CONST diff --git a/src/Makefile.am b/src/Makefile.am index 7ad55117e43..d8e331fb141 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1864,6 +1864,7 @@ noinst_HEADERS = \ include/addr_parsing.h\ include/assert.h\ include/atomic.h\ + include/spinlock.h\ include/bitmapper.h\ include/blobhash.h\ include/buffer.h\ diff --git a/src/common/ceph_context.cc b/src/common/ceph_context.cc index 7d1b74ebd43..8d3c18a2fb4 100644 --- a/src/common/ceph_context.cc +++ b/src/common/ceph_context.cc @@ -33,6 +33,8 @@ #include <pthread.h> #include <semaphore.h> +#include "include/spinlock.h" + using ceph::HeartbeatMap; class CephContextServiceThread : public Thread @@ -247,7 +249,7 @@ CephContext::CephContext(uint32_t module_type_) _crypto_none(NULL), _crypto_aes(NULL) { - pthread_spin_init(&_service_thread_lock, PTHREAD_PROCESS_SHARED); + ceph_spin_init(&_service_thread_lock); _log = new ceph::log::Log(&_conf->subsys); _log->start(); @@ -317,7 +319,7 @@ CephContext::~CephContext() _log = NULL; delete _conf; - pthread_spin_destroy(&_service_thread_lock); + ceph_spin_destroy(&_service_thread_lock); delete _crypto_none; delete _crypto_aes; @@ -325,14 +327,14 @@ CephContext::~CephContext() void CephContext::start_service_thread() { - pthread_spin_lock(&_service_thread_lock); + ceph_spin_lock(&_service_thread_lock); if (_service_thread) { - pthread_spin_unlock(&_service_thread_lock); + ceph_spin_unlock(&_service_thread_lock); return; } _service_thread = new CephContextServiceThread(this); _service_thread->create(); - pthread_spin_unlock(&_service_thread_lock); + ceph_spin_unlock(&_service_thread_lock); // make logs flush on_exit() if (_conf->log_flush_on_exit) @@ -350,22 +352,22 @@ void CephContext::start_service_thread() void CephContext::reopen_logs() { - pthread_spin_lock(&_service_thread_lock); + ceph_spin_lock(&_service_thread_lock); if (_service_thread) _service_thread->reopen_logs(); - pthread_spin_unlock(&_service_thread_lock); + ceph_spin_unlock(&_service_thread_lock); } void CephContext::join_service_thread() { - pthread_spin_lock(&_service_thread_lock); + ceph_spin_lock(&_service_thread_lock); CephContextServiceThread *thread = _service_thread; if (!thread) { - pthread_spin_unlock(&_service_thread_lock); + ceph_spin_unlock(&_service_thread_lock); return; } _service_thread = NULL; - pthread_spin_unlock(&_service_thread_lock); + ceph_spin_unlock(&_service_thread_lock); thread->exit_thread(); thread->join(); diff --git a/src/common/ceph_context.h b/src/common/ceph_context.h index 1678680fa6d..9d801a1537b 100644 --- a/src/common/ceph_context.h +++ b/src/common/ceph_context.h @@ -20,6 +20,7 @@ #include "include/buffer.h" #include "include/atomic.h" +#include "include/spinlock.h" class AdminSocket; class CephContextServiceThread; @@ -124,7 +125,7 @@ private: AdminSocket *_admin_socket; /* lock which protects service thread creation, destruction, etc. */ - pthread_spinlock_t _service_thread_lock; + ceph_spinlock_t _service_thread_lock; /* The collection of profiling loggers associated with this context */ PerfCountersCollection *_perf_counters_collection; diff --git a/src/include/atomic.h b/src/include/atomic.h index 3ecbd287376..65230024f80 100644 --- a/src/include/atomic.h +++ b/src/include/atomic.h @@ -67,53 +67,52 @@ namespace ceph { /* * crappy slow implementation that uses a pthreads spinlock. */ -#include <pthread.h> -#include "include/assert.h" +#include "include/spinlock.h" namespace ceph { class atomic_t { - mutable pthread_spinlock_t lock; + mutable ceph_spinlock_t lock; signed long val; public: atomic_t(int i=0) : val(i) { - pthread_spin_init(&lock, PTHREAD_PROCESS_PRIVATE); + ceph_spin_init(&lock); } ~atomic_t() { - pthread_spin_destroy(&lock); + ceph_spin_destroy(&lock); } void set(size_t v) { - pthread_spin_lock(&lock); + ceph_spin_lock(&lock); val = v; - pthread_spin_unlock(&lock); + ceph_spin_unlock(&lock); } int inc() { - pthread_spin_lock(&lock); + ceph_spin_lock(&lock); int r = ++val; - pthread_spin_unlock(&lock); + ceph_spin_unlock(&lock); return r; } int dec() { - pthread_spin_lock(&lock); + ceph_spin_lock(&lock); int r = --val; - pthread_spin_unlock(&lock); + ceph_spin_unlock(&lock); return r; } void add(int d) { - pthread_spin_lock(&lock); + ceph_spin_lock(&lock); val += d; - pthread_spin_unlock(&lock); + ceph_spin_unlock(&lock); } void sub(int d) { - pthread_spin_lock(&lock); + ceph_spin_lock(&lock); val -= d; - pthread_spin_unlock(&lock); + ceph_spin_unlock(&lock); } int read() const { signed long ret; - pthread_spin_lock(&lock); + ceph_spin_lock(&lock); ret = val; - pthread_spin_unlock(&lock); + ceph_spin_unlock(&lock); return ret; } private: diff --git a/src/include/spinlock.h b/src/include/spinlock.h new file mode 100644 index 00000000000..505e89ec6b4 --- /dev/null +++ b/src/include/spinlock.h @@ -0,0 +1,62 @@ +#ifndef CEPH_SPINLOCK_H +#define CEPH_SPINLOCK_H + +#include <pthread.h> + +#include "acconfig.h" + +typedef struct { +#ifdef HAVE_PTHREAD_SPINLOCK + pthread_spinlock_t lock; +#else + pthread_mutex_t lock; +#endif +} ceph_spinlock_t; + +#ifdef HAVE_PTHREAD_SPINLOCK + +static inline int ceph_spin_init(ceph_spinlock_t *l) +{ + return pthread_spin_init(&l->lock, PTHREAD_PROCESS_PRIVATE); +} + +static inline int ceph_spin_destroy(ceph_spinlock_t *l) +{ + return pthread_spin_destroy(&l->lock); +} + +static inline int ceph_spin_lock(ceph_spinlock_t *l) +{ + return pthread_spin_lock(&l->lock); +} + +static inline int ceph_spin_unlock(ceph_spinlock_t *l) +{ + return pthread_spin_unlock(&l->lock); +} + +#else /* !HAVE_PTHREAD_SPINLOCK */ + +static inline int ceph_spin_init(ceph_spinlock_t *l) +{ + return pthread_mutex_init(&l->lock, NULL); +} + +static inline int ceph_spin_destroy(ceph_spinlock_t *l) +{ + return pthread_mutex_destroy(&l->lock); +} + +static inline int ceph_spin_lock(ceph_spinlock_t *l) +{ + return pthread_mutex_lock(&l->lock); +} + +static inline int ceph_spin_unlock(ceph_spinlock_t *l) +{ + return pthread_mutex_unlock(&l->lock); +} + +#endif + +#endif diff --git a/src/msg/SimpleMessenger.cc b/src/msg/SimpleMessenger.cc index 48e37d87098..93510ccb8a7 100644 --- a/src/msg/SimpleMessenger.cc +++ b/src/msg/SimpleMessenger.cc @@ -23,6 +23,7 @@ #include "common/Timer.h" #include "common/errno.h" #include "auth/Crypto.h" +#include "include/spinlock.h" #define dout_subsys ceph_subsys_ms #undef dout_prefix @@ -53,7 +54,7 @@ SimpleMessenger::SimpleMessenger(CephContext *cct, entity_name_t name, timeout(0), local_connection(new Connection(this)) { - pthread_spin_init(&global_seq_lock, PTHREAD_PROCESS_PRIVATE); + ceph_spin_init(&global_seq_lock); init_local_connection(); } diff --git a/src/msg/SimpleMessenger.h b/src/msg/SimpleMessenger.h index 47ee145aa5e..71198720354 100644 --- a/src/msg/SimpleMessenger.h +++ b/src/msg/SimpleMessenger.h @@ -38,6 +38,7 @@ using namespace __gnu_cxx; #include "Pipe.h" #include "Accepter.h" +#include "include/spinlock.h" /* * This class handles transmission and reception of messages. Generally @@ -505,7 +506,7 @@ private: /// counter for the global seq our connection protocol uses __u32 global_seq; /// lock to protect the global_seq - pthread_spinlock_t global_seq_lock; + ceph_spinlock_t global_seq_lock; /** * hash map of addresses to Pipes @@ -579,11 +580,11 @@ public: * @return a global sequence ID that nobody else has seen. */ __u32 get_global_seq(__u32 old=0) { - pthread_spin_lock(&global_seq_lock); + ceph_spin_lock(&global_seq_lock); if (old > global_seq) global_seq = old; __u32 ret = ++global_seq; - pthread_spin_unlock(&global_seq_lock); + ceph_spin_unlock(&global_seq_lock); return ret; } /** |