mutex.c revision 277317
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 70#pragma weak _pthread_mutex_init_calloc_cb 71int 72_pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex, 73 void *(calloc_cb)(size_t, size_t)) 74{ 75 76 return (((int (*)(pthread_mutex_t *, void *(*)(size_t, size_t))) 77 __libc_interposing[INTERPOS__pthread_mutex_init_calloc_cb])( 78 mutex, calloc_cb)); 79} 80#endif 81 82bool 83malloc_mutex_init(malloc_mutex_t *mutex) 84{ 85 86#ifdef _WIN32 87 if (!InitializeCriticalSectionAndSpinCount(&mutex->lock, 88 _CRT_SPINCOUNT)) 89 return (true); 90#elif (defined(JEMALLOC_OSSPIN)) 91 mutex->lock = 0; 92#elif (defined(JEMALLOC_MUTEX_INIT_CB)) 93 if (postpone_init) { 94 mutex->postponed_next = postponed_mutexes; 95 postponed_mutexes = mutex; 96 } else { 97 if (_pthread_mutex_init_calloc_cb(&mutex->lock, base_calloc) != 98 0) 99 return (true); 100 } 101#else 102 pthread_mutexattr_t attr; 103 104 if (pthread_mutexattr_init(&attr) != 0) 105 return (true); 106 pthread_mutexattr_settype(&attr, MALLOC_MUTEX_TYPE); 107 if (pthread_mutex_init(&mutex->lock, &attr) != 0) { 108 pthread_mutexattr_destroy(&attr); 109 return (true); 110 } 111 pthread_mutexattr_destroy(&attr); 112#endif 113 return (false); 114} 115 116void 117malloc_mutex_prefork(malloc_mutex_t *mutex) 118{ 119 120 malloc_mutex_lock(mutex); 121} 122 123void 124malloc_mutex_postfork_parent(malloc_mutex_t *mutex) 125{ 126 127 malloc_mutex_unlock(mutex); 128} 129 130void 131malloc_mutex_postfork_child(malloc_mutex_t *mutex) 132{ 133 134#ifdef JEMALLOC_MUTEX_INIT_CB 135 malloc_mutex_unlock(mutex); 136#else 137 if (malloc_mutex_init(mutex)) { 138 malloc_printf("<jemalloc>: Error re-initializing mutex in " 139 "child\n"); 140 if (opt_abort) 141 abort(); 142 } 143#endif 144} 145 146bool 147malloc_mutex_first_thread(void) 148{ 149 150#ifdef JEMALLOC_MUTEX_INIT_CB 151 postpone_init = false; 152 while (postponed_mutexes != NULL) { 153 if (_pthread_mutex_init_calloc_cb(&postponed_mutexes->lock, 154 base_calloc) != 0) 155 return (true); 156 postponed_mutexes = postponed_mutexes->postponed_next; 157 } 158#endif 159 return (false); 160} 161 162bool 163mutex_boot(void) 164{ 165 166#ifndef JEMALLOC_MUTEX_INIT_CB 167 return (malloc_mutex_first_thread()); 168#else 169 return (false); 170#endif 171} 172