174462Salfred#define	JEMALLOC_TSD_C_
274462Salfred#include "jemalloc/internal/jemalloc_internal.h"
3261046Smav
4261046Smav/******************************************************************************/
5261046Smav/* Data. */
6261046Smav
7261046Smavstatic unsigned ncleanups;
8261046Smavstatic malloc_tsd_cleanup_t cleanups[MALLOC_TSD_CLEANUPS_MAX];
9261046Smav
10261046Smav/******************************************************************************/
11261046Smav
12261046Smavvoid *
13261046Smavmalloc_tsd_malloc(size_t size)
14261046Smav{
15261046Smav
16261046Smav	/* Avoid choose_arena() in order to dodge bootstrapping issues. */
1774462Salfred	return (arena_malloc(arenas[0], size, false, false));
18261046Smav}
19261046Smav
20261046Smavvoid
21261046Smavmalloc_tsd_dalloc(void *wrapper)
22261046Smav{
23261046Smav
24261046Smav	idalloc(wrapper);
25261046Smav}
26261046Smav
27261046Smavvoid
28261046Smavmalloc_tsd_no_cleanup(void *arg)
2974462Salfred{
3074462Salfred
3174462Salfred	not_reached();
3274462Salfred}
3374462Salfred
3474462Salfred#if defined(JEMALLOC_MALLOC_THREAD_CLEANUP) || defined(_WIN32)
3574462Salfred#ifndef _WIN32
3674462SalfredJEMALLOC_EXPORT
3774462Salfred#endif
3874462Salfredvoid
3974462Salfred_malloc_thread_cleanup(void)
4092990Sobrien{
4192990Sobrien	bool pending[MALLOC_TSD_CLEANUPS_MAX], again;
4292990Sobrien	unsigned i;
4374462Salfred
4474462Salfred	for (i = 0; i < ncleanups; i++)
4574462Salfred		pending[i] = true;
4674462Salfred
4774462Salfred	do {
4874462Salfred		again = false;
4974462Salfred		for (i = 0; i < ncleanups; i++) {
5074462Salfred			if (pending[i]) {
5174462Salfred				pending[i] = cleanups[i]();
5274462Salfred				if (pending[i])
5374462Salfred					again = true;
54173763Sjb			}
5574462Salfred		}
5674462Salfred	} while (again);
5774462Salfred}
5874462Salfred#endif
5974462Salfred
6074462Salfredvoid
6174462Salfredmalloc_tsd_cleanup_register(bool (*f)(void))
6274462Salfred{
6374462Salfred
6474462Salfred	assert(ncleanups < MALLOC_TSD_CLEANUPS_MAX);
6574462Salfred	cleanups[ncleanups] = f;
6674462Salfred	ncleanups++;
6774462Salfred}
6874462Salfred
6974462Salfredvoid
7074462Salfredmalloc_tsd_boot(void)
7174462Salfred{
72173763Sjb
73173763Sjb	ncleanups = 0;
74173763Sjb}
7574462Salfred
7674462Salfred#ifdef _WIN32
7774462Salfredstatic BOOL WINAPI
7874462Salfred_tls_callback(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
7974462Salfred{
8074462Salfred
8174462Salfred	switch (fdwReason) {
8274462Salfred#ifdef JEMALLOC_LAZY_LOCK
8374462Salfred	case DLL_THREAD_ATTACH:
8474462Salfred		isthreaded = true;
8574462Salfred		break;
8674462Salfred#endif
8774462Salfred	case DLL_THREAD_DETACH:
8874462Salfred		_malloc_thread_cleanup();
8974462Salfred		break;
9074462Salfred	default:
91173763Sjb		break;
9274462Salfred	}
9374462Salfred	return (true);
9474462Salfred}
9574462Salfred
9674462Salfred#ifdef _MSC_VER
9774462Salfred#  ifdef _M_IX86
9874462Salfred#    pragma comment(linker, "/INCLUDE:__tls_used")
9974462Salfred#  else
10074462Salfred#    pragma comment(linker, "/INCLUDE:_tls_used")
10174462Salfred#  endif
10274462Salfred#  pragma section(".CRT$XLY",long,read)
10374462Salfred#endif
10474462SalfredJEMALLOC_SECTION(".CRT$XLY") JEMALLOC_ATTR(used)
10574462Salfredstatic const BOOL	(WINAPI *tls_callback)(HINSTANCE hinstDLL,
10674462Salfred    DWORD fdwReason, LPVOID lpvReserved) = _tls_callback;
10774462Salfred#endif
10874462Salfred