Home | History | Annotate | Download | only in src
      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 *
     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
     21 malloc_tsd_dalloc(void *wrapper)
     22 {
     23 
     24 	idalloct(wrapper, false);
     25 }
     26 
     27 void
     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
     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
     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
     70 malloc_tsd_boot(void)
     71 {
     72 
     73 	ncleanups = 0;
     74 }
     75 
     76 #ifdef _WIN32
     77 static 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
    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 *
    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
    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