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 _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_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 return (false); 107} 108 109void 110malloc_mutex_prefork(malloc_mutex_t *mutex) 111{ 112 113 malloc_mutex_lock(mutex); 114} 115 116void 117malloc_mutex_postfork_parent(malloc_mutex_t *mutex) 118{ 119 120 malloc_mutex_unlock(mutex); 121} 122 123void 124malloc_mutex_postfork_child(malloc_mutex_t *mutex) 125{ 126 127#ifdef JEMALLOC_MUTEX_INIT_CB 128 malloc_mutex_unlock(mutex); 129#else 130 if (malloc_mutex_init(mutex)) { 131 malloc_printf("<jemalloc>: Error re-initializing mutex in " 132 "child\n"); 133 if (opt_abort) 134 abort(); 135 } 136#endif 137} 138 139bool 140mutex_boot(void) 141{ 142 143#ifdef JEMALLOC_MUTEX_INIT_CB 144 postpone_init = false; 145 while (postponed_mutexes != NULL) { 146 if (_pthread_mutex_init_calloc_cb(&postponed_mutexes->lock, 147 bootstrap_calloc) != 0) 148 return (true); 149 postponed_mutexes = postponed_mutexes->postponed_next; 150 } 151#endif 152 return (false); 153} 154