Use OSSpinLock*() for locking on OS X.
pthread_mutex_lock() can call malloc() on OS X (!!!), which causes
deadlock. Work around this by using spinlocks that are built of more
primitive stuff.
diff --git a/jemalloc/configure.ac b/jemalloc/configure.ac
index c40d22f..412d3d1 100644
--- a/jemalloc/configure.ac
+++ b/jemalloc/configure.ac
@@ -793,6 +793,21 @@
fi
dnl ============================================================================
+dnl Check for spinlock(3) operations as provided on Darwin.
+
+JE_COMPILABLE([Darwin OSSpin*()], [
+#include <libkern/OSAtomic.h>
+#include <inttypes.h>
+], [
+ OSSpinLock lock = 0;
+ OSSpinLockLock(&lock);
+ OSSpinLockUnlock(&lock);
+], [osspin])
+if test "x${osspin}" = "xyes" ; then
+ AC_DEFINE([JEMALLOC_OSSPIN])
+fi
+
+dnl ============================================================================
dnl Check for allocator-related functions that should be wrapped.
AC_CHECK_FUNC([memalign],
diff --git a/jemalloc/include/jemalloc/internal/atomic.h b/jemalloc/include/jemalloc/internal/atomic.h
index 089affa..f1f0c2b 100644
--- a/jemalloc/include/jemalloc/internal/atomic.h
+++ b/jemalloc/include/jemalloc/internal/atomic.h
@@ -13,13 +13,19 @@
#define atomic_read_uint32(p) atomic_add_uint32(p, 0)
#if (LG_SIZEOF_PTR == 3)
-# define atomic_read_z(p) atomic_add_uint64(p, 0)
-# define atomic_add_z(p, x) atomic_add_uint64(p, x)
-# define atomic_sub_z(p, x) atomic_sub_uint64(p, x)
+# define atomic_read_z(p) \
+ (size_t)atomic_add_uint64((uint64_t *)p, (uint64_t)0)
+# define atomic_add_z(p, x) \
+ (size_t)atomic_add_uint64((uint64_t *)p, (uint64_t)x)
+# define atomic_sub_z(p, x) \
+ (size_t)atomic_sub_uint64((uint64_t *)p, (uint64_t)x)
#elif (LG_SIZEOF_PTR == 2)
-# define atomic_read_z(p) atomic_add_uint32(p, 0)
-# define atomic_add_z(p, x) atomic_add_uint32(p, x)
-# define atomic_sub_z(p, x) atomic_sub_uint32(p, x)
+# define atomic_read_z(p) \
+ (size_t)atomic_add_uint32((uint32_t *)p, (uint32_t)0)
+# define atomic_add_z(p, x) \
+ (size_t)atomic_add_uint32((uint32_t *)p, (uint32_t)x)
+# define atomic_sub_z(p, x) \
+ (size_t)atomic_sub_uint32((uint32_t *)p, (uint32_t)x)
#endif
#endif /* JEMALLOC_H_EXTERNS */
diff --git a/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in b/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in
index f660bc8..fc944a8 100644
--- a/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in
+++ b/jemalloc/include/jemalloc/internal/jemalloc_internal.h.in
@@ -33,7 +33,7 @@
#define JEMALLOC_MANGLE
#include "../jemalloc@install_suffix@.h"
-#ifdef JEMALLOC_OSATOMIC
+#if (defined(JEMALLOC_OSATOMIC) || defined(JEMALLOC_OSSPIN))
#include <libkern/OSAtomic.h>
#endif
diff --git a/jemalloc/include/jemalloc/internal/mutex.h b/jemalloc/include/jemalloc/internal/mutex.h
index dcca01e..62947ce 100644
--- a/jemalloc/include/jemalloc/internal/mutex.h
+++ b/jemalloc/include/jemalloc/internal/mutex.h
@@ -1,7 +1,11 @@
/******************************************************************************/
#ifdef JEMALLOC_H_TYPES
+#ifdef JEMALLOC_OSSPIN
+typedef OSSpinLock malloc_mutex_t;
+#else
typedef pthread_mutex_t malloc_mutex_t;
+#endif
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
# define MALLOC_MUTEX_INITIALIZER PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
@@ -41,17 +45,26 @@
malloc_mutex_lock(malloc_mutex_t *mutex)
{
- if (isthreaded)
+ if (isthreaded) {
+#ifdef JEMALLOC_OSSPIN
+ OSSpinLockLock(mutex);
+#else
pthread_mutex_lock(mutex);
+#endif
+ }
}
JEMALLOC_INLINE bool
malloc_mutex_trylock(malloc_mutex_t *mutex)
{
- if (isthreaded)
+ if (isthreaded) {
+#ifdef JEMALLOC_OSSPIN
+ return (OSSpinLockTry(mutex) == false);
+#else
return (pthread_mutex_trylock(mutex) != 0);
- else
+#endif
+ } else
return (false);
}
@@ -59,8 +72,13 @@
malloc_mutex_unlock(malloc_mutex_t *mutex)
{
- if (isthreaded)
+ if (isthreaded) {
+#ifdef JEMALLOC_OSSPIN
+ OSSpinLockUnlock(mutex);
+#else
pthread_mutex_unlock(mutex);
+#endif
+ }
}
#endif
diff --git a/jemalloc/include/jemalloc/jemalloc_defs.h.in b/jemalloc/include/jemalloc/jemalloc_defs.h.in
index c08c5a2..d8c81d7 100644
--- a/jemalloc/include/jemalloc/jemalloc_defs.h.in
+++ b/jemalloc/include/jemalloc/jemalloc_defs.h.in
@@ -30,6 +30,12 @@
*/
#undef JEMALLOC_OSATOMIC
+/*
+ * Defined if OSSpin*() functions are available, as provided by Darwin, and
+ * documented in the spinlock(3) manual page.
+ */
+#undef JEMALLOC_OSSPIN
+
/* Defined if __attribute__((...)) syntax is supported. */
#undef JEMALLOC_HAVE_ATTR
#ifdef JEMALLOC_HAVE_ATTR
diff --git a/jemalloc/src/jemalloc.c b/jemalloc/src/jemalloc.c
index 0efafde..dccce6b 100644
--- a/jemalloc/src/jemalloc.c
+++ b/jemalloc/src/jemalloc.c
@@ -28,7 +28,13 @@
static pthread_t malloc_initializer = (unsigned long)0;
/* Used to avoid initialization races. */
-static malloc_mutex_t init_lock = MALLOC_MUTEX_INITIALIZER;
+static malloc_mutex_t init_lock =
+#ifdef JEMALLOC_OSSPIN
+ 0
+#else
+ MALLOC_MUTEX_INITIALIZER
+#endif
+ ;
#ifdef DYNAMIC_PAGE_SHIFT
size_t pagesize;
diff --git a/jemalloc/src/mutex.c b/jemalloc/src/mutex.c
index 3ecb18a..ca89ef1 100644
--- a/jemalloc/src/mutex.c
+++ b/jemalloc/src/mutex.c
@@ -55,6 +55,9 @@
bool
malloc_mutex_init(malloc_mutex_t *mutex)
{
+#ifdef JEMALLOC_OSSPIN
+ *mutex = 0;
+#else
pthread_mutexattr_t attr;
if (pthread_mutexattr_init(&attr) != 0)
@@ -70,6 +73,7 @@
}
pthread_mutexattr_destroy(&attr);
+#endif
return (false);
}
@@ -77,8 +81,10 @@
malloc_mutex_destroy(malloc_mutex_t *mutex)
{
+#ifndef JEMALLOC_OSSPIN
if (pthread_mutex_destroy(mutex) != 0) {
malloc_write("<jemalloc>: Error in pthread_mutex_destroy()\n");
abort();
}
+#endif
}