1234370Sjasone#define JEMALLOC_MUTEX_C_ 2234370Sjasone#include "jemalloc/internal/jemalloc_internal.h" 3234370Sjasone 4235238Sjasone#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32) 5234370Sjasone#include <dlfcn.h> 6234370Sjasone#endif 7234370Sjasone 8235238Sjasone#ifndef _CRT_SPINCOUNT 9235238Sjasone#define _CRT_SPINCOUNT 4000 10235238Sjasone#endif 11235238Sjasone 12234370Sjasone/******************************************************************************/ 13234370Sjasone/* Data. */ 14234370Sjasone 15234370Sjasone#ifdef JEMALLOC_LAZY_LOCK 16234370Sjasonebool isthreaded = false; 17234370Sjasone#endif 18234370Sjasone#ifdef JEMALLOC_MUTEX_INIT_CB 19234370Sjasonestatic bool postpone_init = true; 20234370Sjasonestatic malloc_mutex_t *postponed_mutexes = NULL; 21234370Sjasone#endif 22234370Sjasone 23235238Sjasone#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32) 24234370Sjasonestatic void pthread_create_once(void); 25234370Sjasone#endif 26234370Sjasone 27234370Sjasone/******************************************************************************/ 28234370Sjasone/* 29234370Sjasone * We intercept pthread_create() calls in order to toggle isthreaded if the 30234370Sjasone * process goes multi-threaded. 31234370Sjasone */ 32234370Sjasone 33235238Sjasone#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32) 34234370Sjasonestatic int (*pthread_create_fptr)(pthread_t *__restrict, const pthread_attr_t *, 35234370Sjasone void *(*)(void *), void *__restrict); 36234370Sjasone 37234370Sjasonestatic void 38234370Sjasonepthread_create_once(void) 39234370Sjasone{ 40234370Sjasone 41234370Sjasone pthread_create_fptr = dlsym(RTLD_NEXT, "pthread_create"); 42234370Sjasone if (pthread_create_fptr == NULL) { 43234370Sjasone malloc_write("<jemalloc>: Error in dlsym(RTLD_NEXT, " 44234370Sjasone "\"pthread_create\")\n"); 45234370Sjasone abort(); 46234370Sjasone } 47234370Sjasone 48234370Sjasone isthreaded = true; 49234370Sjasone} 50234370Sjasone 51235238SjasoneJEMALLOC_EXPORT int 52234370Sjasonepthread_create(pthread_t *__restrict thread, 53234370Sjasone const pthread_attr_t *__restrict attr, void *(*start_routine)(void *), 54234370Sjasone void *__restrict arg) 55234370Sjasone{ 56234370Sjasone static pthread_once_t once_control = PTHREAD_ONCE_INIT; 57234370Sjasone 58234370Sjasone pthread_once(&once_control, pthread_create_once); 59234370Sjasone 60234370Sjasone return (pthread_create_fptr(thread, attr, start_routine, arg)); 61234370Sjasone} 62234370Sjasone#endif 63234370Sjasone 64234370Sjasone/******************************************************************************/ 65234370Sjasone 66234370Sjasone#ifdef JEMALLOC_MUTEX_INIT_CB 67242844SjasoneJEMALLOC_EXPORT int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex, 68234370Sjasone void *(calloc_cb)(size_t, size_t)); 69234370Sjasone 70234370Sjasone__weak_reference(_pthread_mutex_init_calloc_cb_stub, 71234370Sjasone _pthread_mutex_init_calloc_cb); 72234370Sjasone 73234370Sjasoneint 74234370Sjasone_pthread_mutex_init_calloc_cb_stub(pthread_mutex_t *mutex, 75234370Sjasone void *(calloc_cb)(size_t, size_t)) 76234370Sjasone{ 77234370Sjasone 78234370Sjasone return (0); 79234370Sjasone} 80234370Sjasone#endif 81234370Sjasone 82234370Sjasonebool 83234370Sjasonemalloc_mutex_init(malloc_mutex_t *mutex) 84234370Sjasone{ 85235238Sjasone 86235238Sjasone#ifdef _WIN32 87235238Sjasone if (!InitializeCriticalSectionAndSpinCount(&mutex->lock, 88235238Sjasone _CRT_SPINCOUNT)) 89235238Sjasone return (true); 90235238Sjasone#elif (defined(JEMALLOC_OSSPIN)) 91234370Sjasone mutex->lock = 0; 92234370Sjasone#elif (defined(JEMALLOC_MUTEX_INIT_CB)) 93234370Sjasone if (postpone_init) { 94234370Sjasone mutex->postponed_next = postponed_mutexes; 95234370Sjasone postponed_mutexes = mutex; 96234370Sjasone } else { 97234370Sjasone if (_pthread_mutex_init_calloc_cb(&mutex->lock, base_calloc) != 98234370Sjasone 0) 99234370Sjasone return (true); 100234370Sjasone } 101234370Sjasone#else 102234370Sjasone pthread_mutexattr_t attr; 103234370Sjasone 104234370Sjasone if (pthread_mutexattr_init(&attr) != 0) 105234370Sjasone return (true); 106234370Sjasone pthread_mutexattr_settype(&attr, MALLOC_MUTEX_TYPE); 107234370Sjasone if (pthread_mutex_init(&mutex->lock, &attr) != 0) { 108234370Sjasone pthread_mutexattr_destroy(&attr); 109234370Sjasone return (true); 110234370Sjasone } 111234370Sjasone pthread_mutexattr_destroy(&attr); 112234370Sjasone#endif 113234370Sjasone return (false); 114234370Sjasone} 115234370Sjasone 116234370Sjasonevoid 117234370Sjasonemalloc_mutex_prefork(malloc_mutex_t *mutex) 118234370Sjasone{ 119234370Sjasone 120234370Sjasone malloc_mutex_lock(mutex); 121234370Sjasone} 122234370Sjasone 123234370Sjasonevoid 124234370Sjasonemalloc_mutex_postfork_parent(malloc_mutex_t *mutex) 125234370Sjasone{ 126234370Sjasone 127234370Sjasone malloc_mutex_unlock(mutex); 128234370Sjasone} 129234370Sjasone 130234370Sjasonevoid 131234370Sjasonemalloc_mutex_postfork_child(malloc_mutex_t *mutex) 132234370Sjasone{ 133234370Sjasone 134234370Sjasone#ifdef JEMALLOC_MUTEX_INIT_CB 135234370Sjasone malloc_mutex_unlock(mutex); 136234370Sjasone#else 137234370Sjasone if (malloc_mutex_init(mutex)) { 138234370Sjasone malloc_printf("<jemalloc>: Error re-initializing mutex in " 139234370Sjasone "child\n"); 140234370Sjasone if (opt_abort) 141234370Sjasone abort(); 142234370Sjasone } 143234370Sjasone#endif 144234370Sjasone} 145234370Sjasone 146234370Sjasonebool 147234370Sjasonemutex_boot(void) 148234370Sjasone{ 149234370Sjasone 150234370Sjasone#ifdef JEMALLOC_MUTEX_INIT_CB 151234370Sjasone postpone_init = false; 152234370Sjasone while (postponed_mutexes != NULL) { 153234370Sjasone if (_pthread_mutex_init_calloc_cb(&postponed_mutexes->lock, 154234370Sjasone base_calloc) != 0) 155234370Sjasone return (true); 156234370Sjasone postponed_mutexes = postponed_mutexes->postponed_next; 157234370Sjasone } 158234370Sjasone#endif 159234370Sjasone return (false); 160234370Sjasone} 161