summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVsevolod Stakhov <vsevolod@highsecure.ru>2014-11-01 22:11:15 +0000
committerVsevolod Stakhov <vsevolod@highsecure.ru>2014-11-01 22:11:15 +0000
commit2eed87e9b8d39f4f1d03e83f02dce377a1b187f5 (patch)
tree0ff97489a98773cf4b845b610398c91cbef8bbdd
parent75ef01b07b276ead8199f85a8942735f5b762028 (diff)
downloadrspamd-2eed87e9b8d39f4f1d03e83f02dce377a1b187f5.tar.gz
rspamd-2eed87e9b8d39f4f1d03e83f02dce377a1b187f5.zip
Use PTHREAD_PROCESS_SHARED mutexes if possible.
-rw-r--r--CMakeLists.txt1
-rw-r--r--config.h.in1
-rw-r--r--src/libutil/mem_pool.c175
-rw-r--r--src/libutil/mem_pool.h24
4 files changed, 149 insertions, 52 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 34e07940b..a00d9cc48 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -748,6 +748,7 @@ CHECK_SYMBOL_EXISTS(_SC_NPROCESSORS_ONLN unistd.h HAVE_SC_NPROCESSORS_ONLN)
CHECK_SYMBOL_EXISTS(setbit sys/param.h PARAM_H_HAS_BITSET)
CHECK_SYMBOL_EXISTS(getaddrinfo "sys/types.h;sys/socket.h;netdb.h" HAVE_GETADDRINFO)
CHECK_SYMBOL_EXISTS(sched_yield "sched.h" HAVE_SCHED_YIELD)
+CHECK_SYMBOL_EXISTS(PTHREAD_PROCESS_SHARED "pthread.h" HAVE_PTHREAD_PROCESS_SHARED)
IF(NOT HAVE_GETADDRINFO)
MESSAGE(FATAL_ERROR "Your system does not support getaddrinfo call, please consider upgrading it to run rspamd")
diff --git a/config.h.in b/config.h.in
index ba57103f8..158140c9c 100644
--- a/config.h.in
+++ b/config.h.in
@@ -211,6 +211,7 @@
#cmakedefine HAVE_CTYPE_H 1
#cmakedefine HAVE_SCHED_YEILD 1
+#cmakedefine HAVE_PTHREAD_PROCESS_SHARED 1
/* Configure allocator */
#define uthash_malloc(sz) g_slice_alloc(sz)
diff --git a/src/libutil/mem_pool.c b/src/libutil/mem_pool.c
index 810c85d0c..6c9ee6f16 100644
--- a/src/libutil/mem_pool.c
+++ b/src/libutil/mem_pool.c
@@ -483,50 +483,6 @@ memory_pool_find_pool (rspamd_mempool_t * pool, void *pointer)
return NULL;
}
-static inline gint
-__mutex_spin (rspamd_mempool_mutex_t * mutex)
-{
- /* check spin count */
- if (g_atomic_int_dec_and_test (&mutex->spin)) {
- /* This may be deadlock, so check owner of this lock */
- if (mutex->owner == getpid ()) {
- /* This mutex was locked by calling process, so it is just double lock and we can easily unlock it */
- g_atomic_int_set (&mutex->spin, MUTEX_SPIN_COUNT);
- return 0;
- }
- else if (kill (mutex->owner, 0) == -1) {
- /* Owner process was not found, so release lock */
- g_atomic_int_set (&mutex->spin, MUTEX_SPIN_COUNT);
- return 0;
- }
- /* Spin again */
- g_atomic_int_set (&mutex->spin, MUTEX_SPIN_COUNT);
- }
-
-#ifdef HAVE_SCHED_YIELD
- (void)sched_yield ();
-#elif defined(HAVE_NANOSLEEP)
- struct timespec ts;
- ts.tv_sec = 0;
- ts.tv_nsec = MUTEX_SLEEP_TIME;
- /* Spin */
- while (nanosleep (&ts, &ts) == -1 && errno == EINTR) ;
-#else
-# error No methods to spin are defined
-#endif
- return 1;
-}
-
-static void
-memory_pool_mutex_spin (rspamd_mempool_mutex_t * mutex)
-{
- while (!g_atomic_int_compare_and_exchange (&mutex->lock, 0, 1)) {
- if (!__mutex_spin (mutex)) {
- return;
- }
- }
-}
-
/* Simple implementation of spinlock */
void
rspamd_mempool_lock_shared (rspamd_mempool_t * pool, void *pointer)
@@ -718,6 +674,54 @@ rspamd_mempool_suggest_size (void)
#endif
}
+#ifndef HAVE_PTHREAD_PROCESS_SHARED
+/*
+ * Own emulation
+ */
+static inline gint
+__mutex_spin (rspamd_mempool_mutex_t * mutex)
+{
+ /* check spin count */
+ if (g_atomic_int_dec_and_test (&mutex->spin)) {
+ /* This may be deadlock, so check owner of this lock */
+ if (mutex->owner == getpid ()) {
+ /* This mutex was locked by calling process, so it is just double lock and we can easily unlock it */
+ g_atomic_int_set (&mutex->spin, MUTEX_SPIN_COUNT);
+ return 0;
+ }
+ else if (kill (mutex->owner, 0) == -1) {
+ /* Owner process was not found, so release lock */
+ g_atomic_int_set (&mutex->spin, MUTEX_SPIN_COUNT);
+ return 0;
+ }
+ /* Spin again */
+ g_atomic_int_set (&mutex->spin, MUTEX_SPIN_COUNT);
+ }
+
+#ifdef HAVE_SCHED_YIELD
+ (void)sched_yield ();
+#elif defined(HAVE_NANOSLEEP)
+ struct timespec ts;
+ ts.tv_sec = 0;
+ ts.tv_nsec = MUTEX_SLEEP_TIME;
+ /* Spin */
+ while (nanosleep (&ts, &ts) == -1 && errno == EINTR) ;
+#else
+# error No methods to spin are defined
+#endif
+ return 1;
+}
+
+static void
+memory_pool_mutex_spin (rspamd_mempool_mutex_t * mutex)
+{
+ while (!g_atomic_int_compare_and_exchange (&mutex->lock, 0, 1)) {
+ if (!__mutex_spin (mutex)) {
+ return;
+ }
+ }
+}
+
rspamd_mempool_mutex_t *
rspamd_mempool_get_mutex (rspamd_mempool_t * pool)
{
@@ -798,6 +802,89 @@ rspamd_mempool_wunlock_rwlock (rspamd_mempool_rwlock_t * lock)
{
rspamd_mempool_unlock_mutex (lock->__w_lock);
}
+#else
+
+/*
+ * Pthread bases shared mutexes
+ */
+rspamd_mempool_mutex_t *
+rspamd_mempool_get_mutex (rspamd_mempool_t * pool)
+{
+ rspamd_mempool_mutex_t *res;
+ pthread_mutexattr_t mattr;
+
+ if (pool != NULL) {
+ res =
+ rspamd_mempool_alloc_shared (pool, sizeof (rspamd_mempool_mutex_t));
+
+ pthread_mutexattr_init (&mattr);
+ pthread_mutexattr_setpshared (&mattr, PTHREAD_PROCESS_SHARED);
+ pthread_mutex_init (res, &mattr);
+ rspamd_mempool_add_destructor (pool,
+ (rspamd_mempool_destruct_t)pthread_mutex_destroy, res);
+
+ return res;
+ }
+ return NULL;
+}
+
+void
+rspamd_mempool_lock_mutex (rspamd_mempool_mutex_t * mutex)
+{
+ pthread_mutex_lock (mutex);
+}
+
+void
+rspamd_mempool_unlock_mutex (rspamd_mempool_mutex_t * mutex)
+{
+ pthread_mutex_unlock (mutex);
+}
+
+rspamd_mempool_rwlock_t *
+rspamd_mempool_get_rwlock (rspamd_mempool_t * pool)
+{
+ rspamd_mempool_rwlock_t *res;
+ pthread_rwlockattr_t mattr;
+
+ if (pool != NULL) {
+ res =
+ rspamd_mempool_alloc_shared (pool, sizeof (rspamd_mempool_rwlock_t));
+
+ pthread_rwlockattr_init (&mattr);
+ pthread_rwlockattr_setpshared (&mattr, PTHREAD_PROCESS_SHARED);
+ pthread_rwlock_init (res, &mattr);
+ rspamd_mempool_add_destructor (pool,
+ (rspamd_mempool_destruct_t)pthread_rwlock_destroy, res);
+
+ return res;
+ }
+ return NULL;
+}
+
+void
+rspamd_mempool_rlock_rwlock (rspamd_mempool_rwlock_t * lock)
+{
+ pthread_rwlock_rdlock (lock);
+}
+
+void
+rspamd_mempool_wlock_rwlock (rspamd_mempool_rwlock_t * lock)
+{
+ pthread_rwlock_wrlock (lock);
+}
+
+void
+rspamd_mempool_runlock_rwlock (rspamd_mempool_rwlock_t * lock)
+{
+ pthread_rwlock_unlock (lock);
+}
+
+void
+rspamd_mempool_wunlock_rwlock (rspamd_mempool_rwlock_t * lock)
+{
+ pthread_rwlock_unlock (lock);
+}
+#endif
void
rspamd_mempool_set_variable (rspamd_mempool_t *pool,
diff --git a/src/libutil/mem_pool.h b/src/libutil/mem_pool.h
index 6d59e27c7..7403ced29 100644
--- a/src/libutil/mem_pool.h
+++ b/src/libutil/mem_pool.h
@@ -13,7 +13,9 @@
#define RSPAMD_MEM_POOL_H
#include "config.h"
-
+#ifdef HAVE_PTHREAD_PROCESS_SHARED
+#include <pthread.h>
+#endif
struct f_str_s;
@@ -29,11 +31,23 @@ typedef void (*rspamd_mempool_destruct_t)(void *ptr);
/**
* Pool mutex structure
*/
+#ifndef HAVE_PTHREAD_PROCESS_SHARED
typedef struct memory_pool_mutex_s {
gint lock;
pid_t owner;
guint spin;
} rspamd_mempool_mutex_t;
+/**
+ * Rwlock for locking shared memory regions
+ */
+typedef struct memory_pool_rwlock_s {
+ rspamd_mempool_mutex_t *__r_lock; /**< read mutex (private) */
+ rspamd_mempool_mutex_t *__w_lock; /**< write mutex (private) */
+} rspamd_mempool_rwlock_t;
+#else
+typedef pthread_mutex_t rspamd_mempool_mutex_t;
+typedef pthread_rwlock_t rspamd_mempool_rwlock_t;
+#endif
/**
* Pool page structure
@@ -95,13 +109,7 @@ typedef struct memory_pool_stat_s {
guint oversized_chunks; /**< oversized chunks */
} rspamd_mempool_stat_t;
-/**
- * Rwlock for locking shared memory regions
- */
-typedef struct memory_pool_rwlock_s {
- rspamd_mempool_mutex_t *__r_lock; /**< read mutex (private) */
- rspamd_mempool_mutex_t *__w_lock; /**< write mutex (private) */
-} rspamd_mempool_rwlock_t;
+
/**
* Allocate new memory poll