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 41 pthread_create_fptr = dlsym(RTLD_NEXT, "pthread_create"); 42 if (pthread_create_fptr == NULL) { 43 malloc_write("<jemalloc>: Error in dlsym(RTLD_NEXT, " 44 "\"pthread_create\")\n"); 45 abort(); 46 } 47 48 isthreaded = true; 49} 50 51JEMALLOC_EXPORT int 52pthread_create(pthread_t *__restrict thread, 53 const pthread_attr_t *__restrict attr, void *(*start_routine)(void *), 54 void *__restrict arg) 55{ 56 static pthread_once_t once_control = PTHREAD_ONCE_INIT; 57 58 pthread_once(&once_control, pthread_create_once); 59 60 return (pthread_create_fptr(thread, attr, start_routine, arg)); 61} 62#endif 63 64/******************************************************************************/ 65 66#ifdef JEMALLOC_MUTEX_INIT_CB 67JEMALLOC_EXPORT int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex, 68 void *(calloc_cb)(size_t, size_t)); 69#endif 70 71bool 72malloc_mutex_init(malloc_mutex_t *mutex, const char *name, witness_rank_t rank) 73{ 74 75#ifdef _WIN32 76# if _WIN32_WINNT >= 0x0600 77 InitializeSRWLock(&mutex->lock); 78# else 79 if (!InitializeCriticalSectionAndSpinCount(&mutex->lock, 80 _CRT_SPINCOUNT)) 81 return (true); 82# endif 83#elif (defined(JEMALLOC_OS_UNFAIR_LOCK)) 84 mutex->lock = OS_UNFAIR_LOCK_INIT; 85#elif (defined(JEMALLOC_OSSPIN)) 86 mutex->lock = 0; 87#elif (defined(JEMALLOC_MUTEX_INIT_CB)) 88 if (postpone_init) { 89 mutex->postponed_next = postponed_mutexes; 90 postponed_mutexes = mutex; 91 } else { 92 if (_pthread_mutex_init_calloc_cb(&mutex->lock, 93 bootstrap_calloc) != 0) 94 return (true); 95 } 96#else 97 pthread_mutexattr_t attr; 98 99 if (pthread_mutexattr_init(&attr) != 0) 100 return (true); 101 pthread_mutexattr_settype(&attr, MALLOC_MUTEX_TYPE); 102 if (pthread_mutex_init(&mutex->lock, &attr) != 0) { 103 pthread_mutexattr_destroy(&attr); 104 return (true); 105 } 106 pthread_mutexattr_destroy(&attr); 107#endif 108 if (config_debug) 109 witness_init(&mutex->witness, name, rank, NULL); 110 return (false); 111} 112 113void 114malloc_mutex_prefork(tsdn_t *tsdn, malloc_mutex_t *mutex) 115{ 116 117 malloc_mutex_lock(tsdn, mutex); 118} 119 120void 121malloc_mutex_postfork_parent(tsdn_t *tsdn, malloc_mutex_t *mutex) 122{ 123 124 malloc_mutex_unlock(tsdn, mutex); 125} 126 127void 128malloc_mutex_postfork_child(tsdn_t *tsdn, malloc_mutex_t *mutex) 129{ 130 131#ifdef JEMALLOC_MUTEX_INIT_CB 132 malloc_mutex_unlock(tsdn, mutex); 133#else 134 if (malloc_mutex_init(mutex, mutex->witness.name, 135 mutex->witness.rank)) { 136 malloc_printf("<jemalloc>: Error re-initializing mutex in " 137 "child\n"); 138 if (opt_abort) 139 abort(); 140 } 141#endif 142} 143 144bool 145malloc_mutex_boot(void) 146{ 147 148#ifdef JEMALLOC_MUTEX_INIT_CB 149 postpone_init = false; 150 while (postponed_mutexes != NULL) { 151 if (_pthread_mutex_init_calloc_cb(&postponed_mutexes->lock, 152 bootstrap_calloc) != 0) 153 return (true); 154 postponed_mutexes = postponed_mutexes->postponed_next; 155 } 156#endif 157 return (false); 158} 159