]> git.proxmox.com Git - rustc.git/blob - src/jemalloc/src/tsd.c
Merge tag 'upstream-tar/1.0.0_0alpha'
[rustc.git] / src / jemalloc / src / tsd.c
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 malloc_tsd_data(, , tsd_t, TSD_INITIALIZER)
11
12 /******************************************************************************/
13
14 void *
15 malloc_tsd_malloc(size_t size)
16 {
17
18 /* Avoid choose_arena() in order to dodge bootstrapping issues. */
19 return (arena_malloc(NULL, arenas[0], CACHELINE_CEILING(size), false,
20 false));
21 }
22
23 void
24 malloc_tsd_dalloc(void *wrapper)
25 {
26
27 idalloct(NULL, wrapper, false);
28 }
29
30 void
31 malloc_tsd_no_cleanup(void *arg)
32 {
33
34 not_reached();
35 }
36
37 #if defined(JEMALLOC_MALLOC_THREAD_CLEANUP) || defined(_WIN32)
38 #ifndef _WIN32
39 JEMALLOC_EXPORT
40 #endif
41 void
42 _malloc_thread_cleanup(void)
43 {
44 bool pending[MALLOC_TSD_CLEANUPS_MAX], again;
45 unsigned i;
46
47 for (i = 0; i < ncleanups; i++)
48 pending[i] = true;
49
50 do {
51 again = false;
52 for (i = 0; i < ncleanups; i++) {
53 if (pending[i]) {
54 pending[i] = cleanups[i]();
55 if (pending[i])
56 again = true;
57 }
58 }
59 } while (again);
60 }
61 #endif
62
63 void
64 malloc_tsd_cleanup_register(bool (*f)(void))
65 {
66
67 assert(ncleanups < MALLOC_TSD_CLEANUPS_MAX);
68 cleanups[ncleanups] = f;
69 ncleanups++;
70 }
71
72 void
73 tsd_cleanup(void *arg)
74 {
75 tsd_t *tsd = (tsd_t *)arg;
76
77 switch (tsd->state) {
78 case tsd_state_nominal:
79 #define O(n, t) \
80 n##_cleanup(tsd);
81 MALLOC_TSD
82 #undef O
83 tsd->state = tsd_state_purgatory;
84 tsd_set(tsd);
85 break;
86 case tsd_state_purgatory:
87 /*
88 * The previous time this destructor was called, we set the
89 * state to tsd_state_purgatory so that other destructors
90 * wouldn't cause re-creation of the tsd. This time, do
91 * nothing, and do not request another callback.
92 */
93 break;
94 case tsd_state_reincarnated:
95 /*
96 * Another destructor deallocated memory after this destructor
97 * was called. Reset state to tsd_state_purgatory and request
98 * another callback.
99 */
100 tsd->state = tsd_state_purgatory;
101 tsd_set(tsd);
102 break;
103 default:
104 not_reached();
105 }
106 }
107
108 bool
109 malloc_tsd_boot(void)
110 {
111
112 ncleanups = 0;
113 if (tsd_boot())
114 return (true);
115 return (false);
116 }
117
118 #ifdef _WIN32
119 static BOOL WINAPI
120 _tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
121 {
122
123 switch (fdwReason) {
124 #ifdef JEMALLOC_LAZY_LOCK
125 case DLL_THREAD_ATTACH:
126 isthreaded = true;
127 break;
128 #endif
129 case DLL_THREAD_DETACH:
130 _malloc_thread_cleanup();
131 break;
132 default:
133 break;
134 }
135 return (true);
136 }
137
138 #ifdef _MSC_VER
139 # ifdef _M_IX86
140 # pragma comment(linker, "/INCLUDE:__tls_used")
141 # else
142 # pragma comment(linker, "/INCLUDE:_tls_used")
143 # endif
144 # pragma section(".CRT$XLY",long,read)
145 #endif
146 JEMALLOC_SECTION(".CRT$XLY") JEMALLOC_ATTR(used)
147 static const BOOL (WINAPI *tls_callback)(HINSTANCE hinstDLL,
148 DWORD fdwReason, LPVOID lpvReserved) = _tls_callback;
149 #endif
150
151 #if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \
152 !defined(_WIN32))
153 void *
154 tsd_init_check_recursion(tsd_init_head_t *head, tsd_init_block_t *block)
155 {
156 pthread_t self = pthread_self();
157 tsd_init_block_t *iter;
158
159 /* Check whether this thread has already inserted into the list. */
160 malloc_mutex_lock(&head->lock);
161 ql_foreach(iter, &head->blocks, link) {
162 if (iter->thread == self) {
163 malloc_mutex_unlock(&head->lock);
164 return (iter->data);
165 }
166 }
167 /* Insert block into list. */
168 ql_elm_new(block, link);
169 block->thread = self;
170 ql_tail_insert(&head->blocks, block, link);
171 malloc_mutex_unlock(&head->lock);
172 return (NULL);
173 }
174
175 void
176 tsd_init_finish(tsd_init_head_t *head, tsd_init_block_t *block)
177 {
178
179 malloc_mutex_lock(&head->lock);
180 ql_remove(&head->blocks, block, link);
181 malloc_mutex_unlock(&head->lock);
182 }
183 #endif