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) 73{ 74 75#ifdef _WIN32 76 if (!InitializeCriticalSectionAndSpinCount(&mutex->lock, 77 _CRT_SPINCOUNT)) 78 return (true); 79#elif (defined(JEMALLOC_OSSPIN)) 80 mutex->lock = 0; 81#elif (defined(JEMALLOC_MUTEX_INIT_CB)) 82 if (postpone_init) { 83 mutex->postponed_next = postponed_mutexes; 84 postponed_mutexes = mutex; 85 } else { 86 if (_pthread_mutex_init_calloc_cb(&mutex->lock, 87 bootstrap_calloc) != 0) 88 return (true); 89 } 90#else 91 pthread_mutexattr_t attr; 92 93 if (pthread_mutexattr_init(&attr) != 0) 94 return (true); 95 pthread_mutexattr_settype(&attr, MALLOC_MUTEX_TYPE); 96 if (pthread_mutex_init(&mutex->lock, &attr) != 0) { 97 pthread_mutexattr_destroy(&attr); 98 return (true); 99 } 100 pthread_mutexattr_destroy(&attr); 101#endif 102 return (false); 103} 104 105void 106malloc_mutex_prefork(malloc_mutex_t *mutex) 107{ 108 109 malloc_mutex_lock(mutex); 110} 111 112void 113malloc_mutex_postfork_parent(malloc_mutex_t *mutex) 114{ 115 116 malloc_mutex_unlock(mutex); 117} 118 119void 120malloc_mutex_postfork_child(malloc_mutex_t *mutex) 121{ 122 123#ifdef JEMALLOC_MUTEX_INIT_CB 124 malloc_mutex_unlock(mutex); 125#else 126 if (malloc_mutex_init(mutex)) { 127 malloc_printf("<jemalloc>: Error re-initializing mutex in " 128 "child\n"); 129 if (opt_abort) 130 abort(); 131 } 132#endif 133} 134 135bool 136mutex_boot(void) 137{ 138 139#ifdef JEMALLOC_MUTEX_INIT_CB 140 postpone_init = false; 141 while (postponed_mutexes != NULL) { 142 if (_pthread_mutex_init_calloc_cb(&postponed_mutexes->lock, 143 bootstrap_calloc) != 0) 144 return (true); 145 postponed_mutexes = postponed_mutexes->postponed_next; 146 } 147#endif 148 return (false); 149} 150