Home | History | Annotate | Download | only in src
      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
     16 bool isthreaded = false;
     17 #endif
     18 #ifdef JEMALLOC_MUTEX_INIT_CB
     19 static bool		postpone_init = true;
     20 static malloc_mutex_t	*postponed_mutexes = NULL;
     21 #endif
     22 
     23 #if defined(JEMALLOC_LAZY_LOCK) && !defined(_WIN32)
     24 static 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)
     34 static int (*pthread_create_fptr)(pthread_t *__restrict, const pthread_attr_t *,
     35     void *(*)(void *), void *__restrict);
     36 
     37 static void
     38 pthread_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 
     51 JEMALLOC_EXPORT int
     52 pthread_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
     67 JEMALLOC_EXPORT int	_pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex,
     68     void *(calloc_cb)(size_t, size_t));
     69 #endif
     70 
     71 bool
     72 malloc_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 
    109 void
    110 malloc_mutex_prefork(malloc_mutex_t *mutex)
    111 {
    112 
    113 	malloc_mutex_lock(mutex);
    114 }
    115 
    116 void
    117 malloc_mutex_postfork_parent(malloc_mutex_t *mutex)
    118 {
    119 
    120 	malloc_mutex_unlock(mutex);
    121 }
    122 
    123 void
    124 malloc_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 
    139 bool
    140 mutex_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