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

Reply via email to