Home | History | Annotate | Download | only in internal
      1 #ifdef JEMALLOC_INTERNAL_TSD_WIN_H
      2 #error This file should be included only once, by tsd.h.
      3 #endif
      4 #define JEMALLOC_INTERNAL_TSD_WIN_H
      5 
      6 typedef struct {
      7 	bool initialized;
      8 	tsd_t val;
      9 } tsd_wrapper_t;
     10 
     11 extern DWORD tsd_tsd;
     12 extern tsd_wrapper_t tsd_boot_wrapper;
     13 extern bool tsd_booted;
     14 
     15 /* Initialization/cleanup. */
     16 JEMALLOC_ALWAYS_INLINE bool
     17 tsd_cleanup_wrapper(void) {
     18 	DWORD error = GetLastError();
     19 	tsd_wrapper_t *wrapper = (tsd_wrapper_t *)TlsGetValue(tsd_tsd);
     20 	SetLastError(error);
     21 
     22 	if (wrapper == NULL) {
     23 		return false;
     24 	}
     25 
     26 	if (wrapper->initialized) {
     27 		wrapper->initialized = false;
     28 		tsd_cleanup(&wrapper->val);
     29 		if (wrapper->initialized) {
     30 			/* Trigger another cleanup round. */
     31 			return true;
     32 		}
     33 	}
     34 	malloc_tsd_dalloc(wrapper);
     35 	return false;
     36 }
     37 
     38 JEMALLOC_ALWAYS_INLINE void
     39 tsd_wrapper_set(tsd_wrapper_t *wrapper) {
     40 	if (!TlsSetValue(tsd_tsd, (void *)wrapper)) {
     41 		malloc_write("<jemalloc>: Error setting TSD\n");
     42 		abort();
     43 	}
     44 }
     45 
     46 JEMALLOC_ALWAYS_INLINE tsd_wrapper_t *
     47 tsd_wrapper_get(bool init) {
     48 	DWORD error = GetLastError();
     49 	tsd_wrapper_t *wrapper = (tsd_wrapper_t *) TlsGetValue(tsd_tsd);
     50 	SetLastError(error);
     51 
     52 	if (init && unlikely(wrapper == NULL)) {
     53 		wrapper = (tsd_wrapper_t *)
     54 		    malloc_tsd_malloc(sizeof(tsd_wrapper_t));
     55 		if (wrapper == NULL) {
     56 			malloc_write("<jemalloc>: Error allocating TSD\n");
     57 			abort();
     58 		} else {
     59 			wrapper->initialized = false;
     60 			/* MSVC is finicky about aggregate initialization. */
     61 			tsd_t tsd_initializer = TSD_INITIALIZER;
     62 			wrapper->val = tsd_initializer;
     63 		}
     64 		tsd_wrapper_set(wrapper);
     65 	}
     66 	return wrapper;
     67 }
     68 
     69 JEMALLOC_ALWAYS_INLINE bool
     70 tsd_boot0(void) {
     71 	tsd_tsd = TlsAlloc();
     72 	if (tsd_tsd == TLS_OUT_OF_INDEXES) {
     73 		return true;
     74 	}
     75 	malloc_tsd_cleanup_register(&tsd_cleanup_wrapper);
     76 	tsd_wrapper_set(&tsd_boot_wrapper);
     77 	tsd_booted = true;
     78 	return false;
     79 }
     80 
     81 JEMALLOC_ALWAYS_INLINE void
     82 tsd_boot1(void) {
     83 	tsd_wrapper_t *wrapper;
     84 	wrapper = (tsd_wrapper_t *)
     85 	    malloc_tsd_malloc(sizeof(tsd_wrapper_t));
     86 	if (wrapper == NULL) {
     87 		malloc_write("<jemalloc>: Error allocating TSD\n");
     88 		abort();
     89 	}
     90 	tsd_boot_wrapper.initialized = false;
     91 	tsd_cleanup(&tsd_boot_wrapper.val);
     92 	wrapper->initialized = false;
     93 	tsd_t initializer = TSD_INITIALIZER;
     94 	wrapper->val = initializer;
     95 	tsd_wrapper_set(wrapper);
     96 }
     97 JEMALLOC_ALWAYS_INLINE bool
     98 tsd_boot(void) {
     99 	if (tsd_boot0()) {
    100 		return true;
    101 	}
    102 	tsd_boot1();
    103 	return false;
    104 }
    105 
    106 JEMALLOC_ALWAYS_INLINE bool
    107 tsd_booted_get(void) {
    108 	return tsd_booted;
    109 }
    110 
    111 JEMALLOC_ALWAYS_INLINE bool
    112 tsd_get_allocates(void) {
    113 	return true;
    114 }
    115 
    116 /* Get/set. */
    117 JEMALLOC_ALWAYS_INLINE tsd_t *
    118 tsd_get(bool init) {
    119 	tsd_wrapper_t *wrapper;
    120 
    121 	assert(tsd_booted);
    122 	wrapper = tsd_wrapper_get(init);
    123 	if (tsd_get_allocates() && !init && wrapper == NULL) {
    124 		return NULL;
    125 	}
    126 	return &wrapper->val;
    127 }
    128 
    129 JEMALLOC_ALWAYS_INLINE void
    130 tsd_set(tsd_t *val) {
    131 	tsd_wrapper_t *wrapper;
    132 
    133 	assert(tsd_booted);
    134 	wrapper = tsd_wrapper_get(true);
    135 	if (likely(&wrapper->val != val)) {
    136 		wrapper->val = *(val);
    137 	}
    138 	wrapper->initialized = true;
    139 }
    140