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
10/******************************************************************************/
11
12void *
13malloc_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
20void
21malloc_tsd_dalloc(void *wrapper)
22{
23
24	idalloct(wrapper, false);
25}
26
27void
28malloc_tsd_no_cleanup(void *arg)
29{
30
31	not_reached();
32}
33
34#if defined(JEMALLOC_MALLOC_THREAD_CLEANUP) || defined(_WIN32)
35#ifndef _WIN32
36JEMALLOC_EXPORT
37#endif
38void
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
60void
61malloc_tsd_cleanup_register(bool (*f)(void))
62{
63
64	assert(ncleanups < MALLOC_TSD_CLEANUPS_MAX);
65	cleanups[ncleanups] = f;
66	ncleanups++;
67}
68
69void
70malloc_tsd_boot(void)
71{
72
73	ncleanups = 0;
74}
75
76#ifdef _WIN32
77static BOOL WINAPI
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
104JEMALLOC_SECTION(".CRT$XLY") JEMALLOC_ATTR(used)
105static 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))
111void *
112tsd_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
133void
134tsd_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