1 #define JEMALLOC_TSD_C_
2 #include "jemalloc/internal/jemalloc_internal.h"
3
4 /******************************************************************************/
5 /* Data. */
6
7 static unsigned ncleanups;
8 static malloc_tsd_cleanup_t cleanups[MALLOC_TSD_CLEANUPS_MAX];
9
10 /******************************************************************************/
11
12 void *
malloc_tsd_malloc(size_t size)13 malloc_tsd_malloc(size_t size)
14 {
15
16 /* Avoid choose_arena() in order to dodge bootstrapping issues. */
17 return (arena_malloc(arenas[0], size, false, false));
18 }
19
20 void
malloc_tsd_dalloc(void * wrapper)21 malloc_tsd_dalloc(void *wrapper)
22 {
23
24 idalloct(wrapper, false);
25 }
26
27 void
malloc_tsd_no_cleanup(void * arg)28 malloc_tsd_no_cleanup(void *arg)
29 {
30
31 not_reached();
32 }
33
34 #if defined(JEMALLOC_MALLOC_THREAD_CLEANUP) || defined(_WIN32)
35 #ifndef _WIN32
36 JEMALLOC_EXPORT
37 #endif
38 void
_malloc_thread_cleanup(void)39 _malloc_thread_cleanup(void)
40 {
41 bool pending[MALLOC_TSD_CLEANUPS_MAX], again;
42 unsigned i;
43
44 for (i = 0; i < ncleanups; i++)
45 pending[i] = true;
46
47 do {
48 again = false;
49 for (i = 0; i < ncleanups; i++) {
50 if (pending[i]) {
51 pending[i] = cleanups[i]();
52 if (pending[i])
53 again = true;
54 }
55 }
56 } while (again);
57 }
58 #endif
59
60 void
malloc_tsd_cleanup_register(bool (* f)(void))61 malloc_tsd_cleanup_register(bool (*f)(void))
62 {
63
64 assert(ncleanups < MALLOC_TSD_CLEANUPS_MAX);
65 cleanups[ncleanups] = f;
66 ncleanups++;
67 }
68
69 void
malloc_tsd_boot(void)70 malloc_tsd_boot(void)
71 {
72
73 ncleanups = 0;
74 }
75
76 #ifdef _WIN32
77 static BOOL WINAPI
_tls_callback(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)78 _tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
79 {
80
81 switch (fdwReason) {
82 #ifdef JEMALLOC_LAZY_LOCK
83 case DLL_THREAD_ATTACH:
84 isthreaded = true;
85 break;
86 #endif
87 case DLL_THREAD_DETACH:
88 _malloc_thread_cleanup();
89 break;
90 default:
91 break;
92 }
93 return (true);
94 }
95
96 #ifdef _MSC_VER
97 # ifdef _M_IX86
98 # pragma comment(linker, "/INCLUDE:__tls_used")
99 # else
100 # pragma comment(linker, "/INCLUDE:_tls_used")
101 # endif
102 # pragma section(".CRT$XLY",long,read)
103 #endif
104 JEMALLOC_SECTION(".CRT$XLY") JEMALLOC_ATTR(used)
105 static const BOOL (WINAPI *tls_callback)(HINSTANCE hinstDLL,
106 DWORD fdwReason, LPVOID lpvReserved) = _tls_callback;
107 #endif
108
109 #if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \
110 !defined(_WIN32))
111 void *
tsd_init_check_recursion(tsd_init_head_t * head,tsd_init_block_t * block)112 tsd_init_check_recursion(tsd_init_head_t *head, tsd_init_block_t *block)
113 {
114 pthread_t self = pthread_self();
115 tsd_init_block_t *iter;
116
117 /* Check whether this thread has already inserted into the list. */
118 malloc_mutex_lock(&head->lock);
119 ql_foreach(iter, &head->blocks, link) {
120 if (iter->thread == self) {
121 malloc_mutex_unlock(&head->lock);
122 return (iter->data);
123 }
124 }
125 /* Insert block into list. */
126 ql_elm_new(block, link);
127 block->thread = self;
128 ql_tail_insert(&head->blocks, block, link);
129 malloc_mutex_unlock(&head->lock);
130 return (NULL);
131 }
132
133 void
tsd_init_finish(tsd_init_head_t * head,tsd_init_block_t * block)134 tsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block)
135 {
136
137 malloc_mutex_lock(&head->lock);
138 ql_remove(&head->blocks, block, link);
139 malloc_mutex_unlock(&head->lock);
140 }
141 #endif
142