1#define JEMALLOC_MUTEX_C_ 2#include "jemalloc/internal/jemalloc_internal.h" 3 4#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32) 5#include <dlfcn.h> 6#endif 7 8#ifndef _CRT_SPINCOUNT 9#define _CRT_SPINCOUNT 4000 10#endif 11 12/******************************************************************************/ 13/* Data. */ 14 15#ifdef JEMALLOC_LAZY_LOCK 16bool isthreaded = false; 17#endif 18#ifdef JEMALLOC_MUTEX_INIT_CB 19static bool postpone_init = true; 20static malloc_mutex_t *postponed_mutexes = NULL; 21#endif 22 23#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32) 24static void pthread_create_once(void); 25#endif 26 27/******************************************************************************/ 28/* 29 * We intercept pthread_create() calls in order to toggle isthreaded if the 30 * process goes multi-threaded. 31 */ 32 33#if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32) 34static int (*pthread_create_fptr)(pthread_t *__restrict, const pthread_attr_t *, 35 void *(*)(void *), void *__restrict); 36 37static void 38pthread_create_once(void) 39{ 40 pthread_create_fptr = dlsym(RTLD_NEXT, "pthread_create"); 41 if (pthread_create_fptr == NULL) { 42 malloc_write("<jemalloc>: Error in dlsym(RTLD_NEXT, " 43 "\"pthread_create\")\n"); 44 abort(); 45 } 46 47 isthreaded = true; 48} 49 50JEMALLOC_EXPORT int 51pthread_create(pthread_t *__restrict thread, 52 const pthread_attr_t *__restrict attr, void *(*start_routine)(void *), 53 void *__restrict arg) 54{ 55 static pthread_once_t once_control = PTHREAD_ONCE_INIT; 56 57 pthread_once(&once_control, pthread_create_once); 58 59 return (pthread_create_fptr(thread, attr, start_routine, arg)); 60} 61#endif 62 63/******************************************************************************/ 64 65#ifdef JEMALLOC_MUTEX_INIT_CB 66JEMALLOC_EXPORT int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex, 67 void *(calloc_cb)(size_t, size_t)); 68#endif 69 70bool 71malloc_mutex_init(malloc_mutex_t *mutex, const char *name, witness_rank_t rank) 72{ 73#ifdef _WIN32 74# if _WIN32_WINNT >= 0x0600 75 InitializeSRWLock(&mutex->lock); 76# else 77 if (!InitializeCriticalSectionAndSpinCount(&mutex->lock, 78 _CRT_SPINCOUNT)) 79 return (true); 80# endif 81#elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) 82 mutex->lock = OS_UNFAIR_LOCK_INIT; 83#elif (defined(JEMALLOC_OSSPIN)) 84 mutex->lock = 0; 85#elif (defined(JEMALLOC_MUTEX_INIT_CB)) 86 if (postpone_init) { 87 mutex->postponed_next = postponed_mutexes; 88 postponed_mutexes = mutex; 89 } else { 90 if (_pthread_mutex_init_calloc_cb(&mutex->lock, 91 bootstrap_calloc) != 0) 92 return (true); 93 } 94#else 95 pthread_mutexattr_t attr; 96 97 if (pthread_mutexattr_init(&attr) != 0) 98 return (true); 99 pthread_mutexattr_settype(&attr, MALLOC_MUTEX_TYPE); 100 if (pthread_mutex_init(&mutex->lock, &attr) != 0) { 101 pthread_mutexattr_destroy(&attr); 102 return (true); 103 } 104 pthread_mutexattr_destroy(&attr); 105#endif 106 if (config_debug) 107 witness_init(&mutex->witness, name, rank, NULL, NULL); 108 return (false); 109} 110 111void 112malloc_mutex_prefork(tsdn_t *tsdn, malloc_mutex_t *mutex) 113{ 114 malloc_mutex_lock(tsdn, mutex); 115} 116 117void 118malloc_mutex_postfork_parent(tsdn_t *tsdn, malloc_mutex_t *mutex) 119{ 120 malloc_mutex_unlock(tsdn, mutex); 121} 122 123void 124malloc_mutex_postfork_child(tsdn_t *tsdn, malloc_mutex_t *mutex) 125{ 126#ifdef JEMALLOC_MUTEX_INIT_CB 127 malloc_mutex_unlock(tsdn, mutex); 128#else 129 if (malloc_mutex_init(mutex, mutex->witness.name, 130 mutex->witness.rank)) { 131 malloc_printf("<jemalloc>: Error re-initializing mutex in " 132 "child\n"); 133 if (opt_abort) 134 abort(); 135 } 136#endif 137} 138 139bool 140malloc_mutex_boot(void) 141{ 142#ifdef JEMALLOC_MUTEX_INIT_CB 143 postpone_init = false; 144 while (postponed_mutexes != NULL) { 145 if (_pthread_mutex_init_calloc_cb(&postponed_mutexes->lock, 146 bootstrap_calloc) != 0) 147 return (true); 148 postponed_mutexes = postponed_mutexes->postponed_next; 149 } 150#endif 151 return (false); 152} 153