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