From 893a0ed7c8c11962524ba6f2adeb304d038be2a9 Mon Sep 17 00:00:00 2001 From: Jason Evans Date: Fri, 18 Mar 2011 19:30:18 -0700 Subject: [PATCH] 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. --- jemalloc/configure.ac | 15 +++++++++++ jemalloc/include/jemalloc/internal/atomic.h | 18 ++++++++----- .../jemalloc/internal/jemalloc_internal.h.in | 2 +- jemalloc/include/jemalloc/internal/mutex.h | 26 ++++++++++++++++--- jemalloc/include/jemalloc/jemalloc_defs.h.in | 6 +++++ jemalloc/src/jemalloc.c | 8 +++++- jemalloc/src/mutex.c | 6 +++++ 7 files changed, 69 insertions(+), 12 deletions(-) diff --git a/jemalloc/configure.ac b/jemalloc/configure.ac index c40d22fd..412d3d1b 100644 --- a/jemalloc/configure.ac +++ b/jemalloc/configure.ac @@ -792,6 +792,21 @@ if test "x${osatomic}" = "xyes" ; then AC_DEFINE([JEMALLOC_OSATOMIC]) fi +dnl ============================================================================ +dnl Check for spinlock(3) operations as provided on Darwin. + +JE_COMPILABLE([Darwin OSSpin*()], [ +#include +#include +], [ + 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. diff --git a/jemalloc/include/jemalloc/internal/atomic.h b/jemalloc/include/jemalloc/internal/atomic.h index 089affa8..f1f0c2b2 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 f660bc8b..fc944a8c 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 #endif diff --git a/jemalloc/include/jemalloc/internal/mutex.h b/jemalloc/include/jemalloc/internal/mutex.h index dcca01ed..62947ced 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 @@ JEMALLOC_INLINE void 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 @@ JEMALLOC_INLINE void 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 c08c5a2c..d8c81d7c 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 0efafdea..dccce6b4 100644 --- a/jemalloc/src/jemalloc.c +++ b/jemalloc/src/jemalloc.c @@ -28,7 +28,13 @@ static bool malloc_initialized = false; 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 3ecb18a3..ca89ef1c 100644 --- a/jemalloc/src/mutex.c +++ b/jemalloc/src/mutex.c @@ -55,6 +55,9 @@ pthread_create(pthread_t *__restrict thread, 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 @@ malloc_mutex_init(malloc_mutex_t *mutex) } pthread_mutexattr_destroy(&attr); +#endif return (false); } @@ -77,8 +81,10 @@ void malloc_mutex_destroy(malloc_mutex_t *mutex) { +#ifndef JEMALLOC_OSSPIN if (pthread_mutex_destroy(mutex) != 0) { malloc_write(": Error in pthread_mutex_destroy()\n"); abort(); } +#endif }