Skip to content

Commit

Permalink
[release/8.0] Free the tls memory on thread termination (#95439)
Browse files Browse the repository at this point in the history
* Free the tls memory

* zero the size variables

* fix linux build errors

* Move ThreadStaticBlockInfo definition in jitinterface.h

* cleanup and consolidate TLS variables

* Address review feedback

* reset t_NonGCThreadStaticBlocksSize and conditional check the nullptr

* Delete tls memory from detach thread

* Call DeleteThreadLocalMemory() from TlsDestructionMonitor

---------

Co-authored-by: Kunal Pathak <Kunal.Pathak@microsoft.com>
  • Loading branch information
github-actions[bot] and kunalspathak authored Nov 30, 2023
1 parent 89a2364 commit a6e4834
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 33 deletions.
30 changes: 30 additions & 0 deletions src/coreclr/vm/ceemain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1752,6 +1752,7 @@ struct TlsDestructionMonitor
GCX_COOP_NO_DTOR_END();
}
thread->DetachThread(TRUE);
DeleteThreadLocalMemory();
}

ThreadDetaching();
Expand All @@ -1768,6 +1769,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
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/vm/ceemain.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ void ThreadDetaching();

void EnsureTlsDestructionMonitor();

void DeleteThreadLocalMemory();

void SetLatchedExitCode (INT32 code);
INT32 GetLatchedExitCode (void);

Expand Down
21 changes: 5 additions & 16 deletions src/coreclr/vm/jithelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1777,24 +1777,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
Expand Down
19 changes: 2 additions & 17 deletions src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
//
Expand Down
19 changes: 19 additions & 0 deletions src/coreclr/vm/jitinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit a6e4834

Please # to comment.