Hi,
I noticed that the OSX version of the jemalloc uses spin locks and decided
to implement support for the pthread spin locks that can be used in Linux.
At least in my case there is huge benefit because I run a single thread in
a specific core that has not that much other activity and pthread mutex
lock contention seems to always schedule the thread away from execution,
so spin locking seems to give more stable result while adding bit more CPU
load. Most likely in more general case this would not be wanted, because
there would be more threads/processes running on same core and thus the
scheduling might give execution time for some other important threads like
the one having the lock taken.
What do you think, is this something that could be merged to the upstream?
My patch implements new configure script option --enable-pthread-spinlock
that turns on the pthread spin lock i.e. the spin locks are not used by
default because of the scheduling benefit with normal use.
Best regards,
Valtteri
diff --git a/configure.ac b/configure.ac
index 724bc1a..23f2c8c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -828,6 +828,22 @@ if test "x$enable_tcache" = "x1" ; then
fi
AC_SUBST([enable_tcache])
+dnl Enable pthread spinlocks
+AC_ARG_ENABLE([pthread-spinlock],
+ [AS_HELP_STRING([--enable-pthread-spinlock], [Enable pthread spinlock])],
+[if test "x$enable-pthread-spinlock" = "xno" ; then
+ enable_pthread_spinlock="0"
+else
+ enable_pthread_spinlock="1"
+fi
+],
+[enable_pthread_spinlock="0"]
+)
+if test "x$enable_spinlock" = "x1" ; then
+ AC_DEFINE([JEMALLOC_PTHREAD_SPINLOCK], [ ])
+fi
+AC_SUBST([enable_pthread_spinlock])
+
dnl Disable mremap() for huge realloc() by default.
AC_ARG_ENABLE([mremap],
[AS_HELP_STRING([--enable-mremap], [Enable mremap(2) for huge realloc()])],
@@ -1434,4 +1450,5 @@ AC_MSG_RESULT([munmap : ${enable_munmap}])
AC_MSG_RESULT([dss : ${enable_dss}])
AC_MSG_RESULT([lazy_lock : ${enable_lazy_lock}])
AC_MSG_RESULT([tls : ${enable_tls}])
+AC_MSG_RESULT([pthread-spinlock : ${enable_pthread_spinlock}])
AC_MSG_RESULT([===============================================================================])
diff --git a/include/jemalloc/internal/mutex.h b/include/jemalloc/internal/mutex.h
index de44e14..e8d8ff1 100644
--- a/include/jemalloc/internal/mutex.h
+++ b/include/jemalloc/internal/mutex.h
@@ -7,6 +7,8 @@ typedef struct malloc_mutex_s malloc_mutex_t;
# define MALLOC_MUTEX_INITIALIZER
#elif (defined(JEMALLOC_OSSPIN))
# define MALLOC_MUTEX_INITIALIZER {0}
+#elif (defined(JEMALLOC_PTHREAD_SPINLOCK))
+# define MALLOC_MUTEX_INITIALIZER (-1)
#elif (defined(JEMALLOC_MUTEX_INIT_CB))
# define MALLOC_MUTEX_INITIALIZER {PTHREAD_MUTEX_INITIALIZER, NULL}
#else
@@ -29,6 +31,8 @@ struct malloc_mutex_s {
CRITICAL_SECTION lock;
#elif (defined(JEMALLOC_OSSPIN))
OSSpinLock lock;
+#elif (defined(JEMALLOC_PTHREAD_SPINLOCK))
+ pthread_spinlock_t lock;
#elif (defined(JEMALLOC_MUTEX_INIT_CB))
pthread_mutex_t lock;
malloc_mutex_t *postponed_next;
@@ -73,6 +77,8 @@ malloc_mutex_lock(malloc_mutex_t *mutex)
EnterCriticalSection(&mutex->lock);
#elif (defined(JEMALLOC_OSSPIN))
OSSpinLockLock(&mutex->lock);
+#elif (defined(JEMALLOC_PTHREAD_SPINLOCK))
+ pthead_spin_lock(&mutex->lock);
#else
pthread_mutex_lock(&mutex->lock);
#endif
@@ -88,6 +94,8 @@ malloc_mutex_unlock(malloc_mutex_t *mutex)
LeaveCriticalSection(&mutex->lock);
#elif (defined(JEMALLOC_OSSPIN))
OSSpinLockUnlock(&mutex->lock);
+#elif (defined(JEMALLOC_PTHREAD_SPINLOCK))
+ pthread_spin_unlock(&mutex->lock);
#else
pthread_mutex_unlock(&mutex->lock);
#endif
diff --git a/src/mutex.c b/src/mutex.c
index 788eca3..1c565f3 100644
--- a/src/mutex.c
+++ b/src/mutex.c
@@ -78,6 +78,8 @@ malloc_mutex_init(malloc_mutex_t *mutex)
return (true);
#elif (defined(JEMALLOC_OSSPIN))
mutex->lock = 0;
+#elif (defined(JEMALLOC_PTHREAD_SPINLOCK))
+ pthread_spin_init(&mutex->lock, PTHREAD_PROCESS_PRIVATE);
#elif (defined(JEMALLOC_MUTEX_INIT_CB))
if (postpone_init) {
mutex->postponed_next = postponed_mutexes;
diff --git a/test/include/test/mtx.h b/test/include/test/mtx.h
index bbe822f..c2ae31f 100644
--- a/test/include/test/mtx.h
+++ b/test/include/test/mtx.h
@@ -10,6 +10,8 @@ typedef struct {
CRITICAL_SECTION lock;
#elif (defined(JEMALLOC_OSSPIN))
OSSpinLock lock;
+#elif (defined(JEMALLOC_PTHREAD_SPINLOCK))
+ pthread_spinlock_t lock;
#else
pthread_mutex_t lock;
#endif
diff --git a/test/src/mtx.c b/test/src/mtx.c
index 41b95d5..9545791 100644
--- a/test/src/mtx.c
+++ b/test/src/mtx.c
@@ -9,6 +9,8 @@ mtx_init(mtx_t *mtx)
return (true);
#elif (defined(JEMALLOC_OSSPIN))
mtx->lock = 0;
+#elif (defined(JEMALLOC_PTHREAD_SPINLOCK))
+ mtx->lock = MALLOC_MUTEX_INITIALIZER;
#else
pthread_mutexattr_t attr;
@@ -30,6 +32,7 @@ mtx_fini(mtx_t *mtx)
#ifdef _WIN32
#elif (defined(JEMALLOC_OSSPIN))
+#elif (defined(JEMALLOC_PTHREAD_SPINLOCK))
#else
pthread_mutex_destroy(&mtx->lock);
#endif
@@ -43,6 +46,8 @@ mtx_lock(mtx_t *mtx)
EnterCriticalSection(&mtx->lock);
#elif (defined(JEMALLOC_OSSPIN))
OSSpinLockLock(&mtx->lock);
+#elif (defined(JEMALLOC_PTHREAD_SPINLOCK))
+ pthread_spin_lock(&mtx->lock);
#else
pthread_mutex_lock(&mtx->lock);
#endif
@@ -56,6 +61,8 @@ mtx_unlock(mtx_t *mtx)
LeaveCriticalSection(&mtx->lock);
#elif (defined(JEMALLOC_OSSPIN))
OSSpinLockUnlock(&mtx->lock);
+#elif (defined(JEMALLOC_PTHREAD_SPINLOCK))
+ pthread_spin_unlock(&mtx->lock);
#else
pthread_mutex_unlock(&mtx->lock);
#endif
_______________________________________________
jemalloc-discuss mailing list
[email protected]
http://www.canonware.com/mailman/listinfo/jemalloc-discuss