diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index c5eaacd0c168e..92c4e47efcadd 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -1751,6 +1751,7 @@ struct TlsDestructionMonitor GCX_COOP_NO_DTOR_END(); } thread->DetachThread(TRUE); + DeleteThreadLocalMemory(); } ThreadDetaching(); @@ -1767,6 +1768,35 @@ void EnsureTlsDestructionMonitor() tls_destructionMonitor.Activate(); } +#ifdef _MSC_VER +__declspec(thread) ThreadStaticBlockInfo t_ThreadStatics; +#else +__thread ThreadStaticBlockInfo t_ThreadStatics; +#endif // _MSC_VER + +// Delete the thread local memory only if we the current thread +// is the one executing this code. If we do not guard it, it will +// end up deleting the thread local memory of the calling thread. +void DeleteThreadLocalMemory() +{ + t_NonGCThreadStaticBlocksSize = 0; + t_GCThreadStaticBlocksSize = 0; + + t_ThreadStatics.NonGCMaxThreadStaticBlocks = 0; + t_ThreadStatics.GCMaxThreadStaticBlocks = 0; + + if (t_ThreadStatics.NonGCThreadStaticBlocks != nullptr) + { + delete[] t_ThreadStatics.NonGCThreadStaticBlocks; + t_ThreadStatics.NonGCThreadStaticBlocks = nullptr; + } + if (t_ThreadStatics.GCThreadStaticBlocks != nullptr) + { + delete[] t_ThreadStatics.GCThreadStaticBlocks; + t_ThreadStatics.GCThreadStaticBlocks = nullptr; + } +} + #ifdef DEBUGGING_SUPPORTED // // InitializeDebugger initialized the Runtime-side COM+ Debugging Services diff --git a/src/coreclr/vm/ceemain.h b/src/coreclr/vm/ceemain.h index 1404a5a04237f..85efc8d0a9c78 100644 --- a/src/coreclr/vm/ceemain.h +++ b/src/coreclr/vm/ceemain.h @@ -47,6 +47,8 @@ void ThreadDetaching(); void EnsureTlsDestructionMonitor(); +void DeleteThreadLocalMemory(); + void SetLatchedExitCode (INT32 code); INT32 GetLatchedExitCode (void); diff --git a/src/coreclr/vm/jithelpers.cpp b/src/coreclr/vm/jithelpers.cpp index 3156e9807ec7a..084da1007a9de 100644 --- a/src/coreclr/vm/jithelpers.cpp +++ b/src/coreclr/vm/jithelpers.cpp @@ -1779,24 +1779,13 @@ HCIMPL1(void*, JIT_GetGCThreadStaticBase_Helper, MethodTable * pMT) } HCIMPLEND -struct ThreadStaticBlockInfo -{ - uint32_t NonGCMaxThreadStaticBlocks; - void** NonGCThreadStaticBlocks; - - uint32_t GCMaxThreadStaticBlocks; - void** GCThreadStaticBlocks; -}; - #ifdef _MSC_VER -__declspec(selectany) __declspec(thread) ThreadStaticBlockInfo t_ThreadStatics; -__declspec(selectany) __declspec(thread) uint32_t t_NonGCThreadStaticBlocksSize; -__declspec(selectany) __declspec(thread) uint32_t t_GCThreadStaticBlocksSize; +__declspec(thread) uint32_t t_NonGCThreadStaticBlocksSize; +__declspec(thread) uint32_t t_GCThreadStaticBlocksSize; #else -EXTERN_C __thread ThreadStaticBlockInfo t_ThreadStatics; -EXTERN_C __thread uint32_t t_NonGCThreadStaticBlocksSize; -EXTERN_C __thread uint32_t t_GCThreadStaticBlocksSize; -#endif +__thread uint32_t t_NonGCThreadStaticBlocksSize; +__thread uint32_t t_GCThreadStaticBlocksSize; +#endif // !_MSC_VER // *** This helper corresponds to both CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE and // CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR. Even though we always check diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 1a844f7da4db0..b6bb44cc329d6 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -69,24 +69,9 @@ EXTERN_C uint32_t _tls_index; #endif -struct ThreadStaticBlockInfo -{ - uint32_t NonGCMaxThreadStaticBlocks; - void** NonGCThreadStaticBlocks; - - uint32_t GCMaxThreadStaticBlocks; - void** GCThreadStaticBlocks; -}; -#ifdef _MSC_VER -__declspec(selectany) __declspec(thread) ThreadStaticBlockInfo t_ThreadStatics; -__declspec(selectany) __declspec(thread) uint32_t t_NonGCThreadStaticBlocksSize; -__declspec(selectany) __declspec(thread) uint32_t t_GCThreadStaticBlocksSize; -#else +#ifndef _MSC_VER extern "C" void* __tls_get_addr(void* ti); -__thread ThreadStaticBlockInfo t_ThreadStatics; -__thread uint32_t t_NonGCThreadStaticBlocksSize; -__thread uint32_t t_GCThreadStaticBlocksSize; -#endif // _MSC_VER +#endif // !_MSC_VER // The Stack Overflow probe takes place in the COOPERATIVE_TRANSITION_BEGIN() macro // diff --git a/src/coreclr/vm/jitinterface.h b/src/coreclr/vm/jitinterface.h index 49350450a3d62..d1ae48e2df5ca 100644 --- a/src/coreclr/vm/jitinterface.h +++ b/src/coreclr/vm/jitinterface.h @@ -101,6 +101,25 @@ BOOL LoadDynamicInfoEntry(Module *currentModule, #endif // TARGET_X86 +// thread local struct to store the "thread static blocks" +struct ThreadStaticBlockInfo +{ + uint32_t NonGCMaxThreadStaticBlocks; + void** NonGCThreadStaticBlocks; + + uint32_t GCMaxThreadStaticBlocks; + void** GCThreadStaticBlocks; +}; + +#ifdef _MSC_VER +EXTERN_C __declspec(thread) ThreadStaticBlockInfo t_ThreadStatics; +EXTERN_C __declspec(thread) uint32_t t_NonGCThreadStaticBlocksSize; +EXTERN_C __declspec(thread) uint32_t t_GCThreadStaticBlocksSize; +#else +EXTERN_C __thread ThreadStaticBlockInfo t_ThreadStatics; +EXTERN_C __thread uint32_t t_NonGCThreadStaticBlocksSize; +EXTERN_C __thread uint32_t t_GCThreadStaticBlocksSize; +#endif // _MSC_VER // // JIT HELPER ALIASING FOR PORTABILITY.