]> git.proxmox.com Git - rustc.git/blame - src/jemalloc/src/tsd.c
Imported Upstream version 1.0.0~0alpha
[rustc.git] / src / jemalloc / src / tsd.c
CommitLineData
970d7e83
LB
1#define JEMALLOC_TSD_C_
2#include "jemalloc/internal/jemalloc_internal.h"
3
4/******************************************************************************/
5/* Data. */
6
7static unsigned ncleanups;
8static malloc_tsd_cleanup_t cleanups[MALLOC_TSD_CLEANUPS_MAX];
9
1a4d82fc
JJ
10malloc_tsd_data(, , tsd_t, TSD_INITIALIZER)
11
970d7e83
LB
12/******************************************************************************/
13
14void *
15malloc_tsd_malloc(size_t size)
16{
17
18 /* Avoid choose_arena() in order to dodge bootstrapping issues. */
1a4d82fc
JJ
19 return (arena_malloc(NULL, arenas[0], CACHELINE_CEILING(size), false,
20 false));
970d7e83
LB
21}
22
23void
24malloc_tsd_dalloc(void *wrapper)
25{
26
1a4d82fc 27 idalloct(NULL, wrapper, false);
970d7e83
LB
28}
29
30void
31malloc_tsd_no_cleanup(void *arg)
32{
33
34 not_reached();
35}
36
37#if defined(JEMALLOC_MALLOC_THREAD_CLEANUP) || defined(_WIN32)
38#ifndef _WIN32
39JEMALLOC_EXPORT
40#endif
41void
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
63void
64malloc_tsd_cleanup_register(bool (*f)(void))
65{
66
67 assert(ncleanups < MALLOC_TSD_CLEANUPS_MAX);
68 cleanups[ncleanups] = f;
69 ncleanups++;
70}
71
72void
1a4d82fc
JJ
73tsd_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);
81MALLOC_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
108bool
970d7e83
LB
109malloc_tsd_boot(void)
110{
111
112 ncleanups = 0;
1a4d82fc
JJ
113 if (tsd_boot())
114 return (true);
115 return (false);
970d7e83
LB
116}
117
118#ifdef _WIN32
119static 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
146JEMALLOC_SECTION(".CRT$XLY") JEMALLOC_ATTR(used)
147static const BOOL (WINAPI *tls_callback)(HINSTANCE hinstDLL,
148 DWORD fdwReason, LPVOID lpvReserved) = _tls_callback;
149#endif
1a4d82fc
JJ
150
151#if (!defined(JEMALLOC_MALLOC_THREAD_CLEANUP) && !defined(JEMALLOC_TLS) && \
152 !defined(_WIN32))
153void *
154tsd_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
175void
176tsd_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