diff --git a/include/mimalloc/prim.h b/include/mimalloc/prim.h index bddd66e9..b0ddc2d0 100644 --- a/include/mimalloc/prim.h +++ b/include/mimalloc/prim.h @@ -208,19 +208,20 @@ static inline void mi_prim_tls_slot_set(size_t slot, void* value) mi_attr_noexce #elif _WIN32 && MI_WIN_USE_FIXED_TLS && !defined(MI_WIN_USE_FLS) // On windows we can store the thread-local heap at a fixed TLS slot to avoid -// thread-local initialization checks in the fast path. This uses a fixed location -// in the TCB though (last user-reserved slot by default) which may clash with other applications. - +// thread-local initialization checks in the fast path. +// We always use the second user TLS slot (the first one is always allocated already), +// and at initialization (`windows/prim.c`) we call TlsAlloc and verify +// we indeed get the second slot (and fail otherwise). +// Todo: we could make the Tls slot completely dynamic but that would require +// an extra read of the static Tls slot instead of using a constant offset. #define MI_HAS_TLS_SLOT 2 // 2 = we can reliably initialize the slot (saving a test on each malloc) #if MI_WIN_USE_FIXED_TLS > 1 #define MI_TLS_SLOT (MI_WIN_USE_FIXED_TLS) #elif MI_SIZE_SIZE == 4 -#define MI_TLS_SLOT (0x710) // Last user-reserved slot -// #define MI_TLS_SLOT (0xF0C) // Last TlsSlot (might clash with other app reserved slot) +#define MI_TLS_SLOT (0x0E18) // Second User TLS slot #else -#define MI_TLS_SLOT (0x888) // Last user-reserved slot -// #define MI_TLS_SLOT (0x1678) // Last TlsSlot (might clash with other app reserved slot) +#define MI_TLS_SLOT (0x1488) // Second User TLS slot #endif static inline void* mi_prim_tls_slot(size_t slot) mi_attr_noexcept { diff --git a/src/prim/windows/prim.c b/src/prim/windows/prim.c index a080f4bc..7daa09ef 100644 --- a/src/prim/windows/prim.c +++ b/src/prim/windows/prim.c @@ -631,8 +631,20 @@ static void NTAPI mi_win_main(PVOID module, DWORD reason, LPVOID reserved) { MI_UNUSED(reserved); MI_UNUSED(module); #if MI_TLS_SLOT >= 2 - if ((reason==DLL_PROCESS_ATTACH || reason==DLL_THREAD_ATTACH) && mi_prim_get_default_heap() == NULL) { - _mi_heap_set_default_direct((mi_heap_t*)&_mi_heap_empty); + if (reason==DLL_PROCESS_ATTACH) { + const DWORD tls_slot = TlsAlloc(); + if (tls_slot != 1) { + _mi_error_message(EFAULT, "unable to allocate the second TLS slot (rebuild without MI_WIN_USE_FIXED_TLS?)\n"); + } + } + if (reason==DLL_PROCESS_ATTACH || reason==DLL_THREAD_ATTACH) { + if (mi_prim_get_default_heap() == NULL) { + _mi_heap_set_default_direct((mi_heap_t*)&_mi_heap_empty); + } + #if MI_DEBUG + void* const p = TlsGetValue(1); + mi_assert_internal(p == (void*)&_mi_heap_empty); + #endif } #endif if (reason==DLL_PROCESS_ATTACH) {