Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move various thread-local objects that were used in self-contained places out of Thread #99989

Merged
merged 7 commits into from
Mar 22, 2024
5 changes: 0 additions & 5 deletions src/coreclr/gc/env/gcenv.base.h
Original file line number Diff line number Diff line change
Expand Up @@ -388,11 +388,6 @@ inline void* ALIGN_DOWN(void* ptr, size_t alignment)
return reinterpret_cast<void*>(ALIGN_DOWN(as_size_t, alignment));
}

inline int GetRandomInt(int max)
{
return rand() % max;
}

typedef struct _PROCESSOR_NUMBER {
uint16_t Group;
uint8_t Number;
Expand Down
5 changes: 1 addition & 4 deletions src/coreclr/inc/random.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,7 @@
// 2) It can have multiple instantiations with different seeds
// 3) It behaves the same regardless of whether we build with VC++ or GCC
//
// If you are working in the VM, we have a convenience method: code:GetRandomInt. This usess a thread-local
// Random instance if a Thread object is available, and otherwise falls back to a global instance
// with a spin-lock.
//
// If you are working in the VM, we have a convenience method: code:GetRandomInt.

#ifndef _CLRRANDOM_H_
#define _CLRRANDOM_H_
Expand Down
8 changes: 4 additions & 4 deletions src/coreclr/vm/amd64/asmconstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,21 +108,21 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__ComPlusCallInfo__m_pILStub

#endif // FEATURE_COMINTEROP

#define OFFSETOF__Thread__m_fPreemptiveGCDisabled 0x0C
#define OFFSETOF__Thread__m_fPreemptiveGCDisabled 0x04
ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_fPreemptiveGCDisabled
== offsetof(Thread, m_fPreemptiveGCDisabled));
#define Thread_m_fPreemptiveGCDisabled OFFSETOF__Thread__m_fPreemptiveGCDisabled

#define OFFSETOF__Thread__m_pFrame 0x10
#define OFFSETOF__Thread__m_pFrame 0x08
ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_pFrame
== offsetof(Thread, m_pFrame));
#define Thread_m_pFrame OFFSETOF__Thread__m_pFrame


#define OFFSET__Thread__m_alloc_context__alloc_ptr 0x58
#define OFFSET__Thread__m_alloc_context__alloc_ptr 0x50
ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_ptr == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_ptr));

#define OFFSET__Thread__m_alloc_context__alloc_limit 0x60
#define OFFSET__Thread__m_alloc_context__alloc_limit 0x58
ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_limit == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_limit));

#define OFFSETOF__gc_alloc_context__alloc_ptr 0x0
Expand Down
22 changes: 13 additions & 9 deletions src/coreclr/vm/appdomain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2608,16 +2608,20 @@ void AppDomain::LoadDomainAssembly(DomainAssembly *pFile,

#ifndef DACCESS_COMPILE

FileLoadLevel AppDomain::GetThreadFileLoadLevel()
thread_local LoadLevelLimiter* LoadLevelLimiter::t_currentLoadLevelLimiter = nullptr;

namespace
{
WRAPPER_NO_CONTRACT;
if (GetThread()->GetLoadLevelLimiter() == NULL)
return FILE_ACTIVE;
else
return (FileLoadLevel)(GetThread()->GetLoadLevelLimiter()->GetLoadLevel()-1);
FileLoadLevel GetCurrentFileLoadLevel()
{
WRAPPER_NO_CONTRACT;
if (LoadLevelLimiter::GetCurrent() == NULL)
return FILE_ACTIVE;
else
return (FileLoadLevel)(LoadLevelLimiter::GetCurrent()->GetLoadLevel()-1);
}
}


Assembly *AppDomain::LoadAssembly(AssemblySpec* pIdentity,
PEAssembly * pPEAssembly,
FileLoadLevel targetLevel)
Expand Down Expand Up @@ -2710,7 +2714,7 @@ DomainAssembly *AppDomain::LoadDomainAssemblyInternal(AssemblySpec* pIdentity,
PRECONDITION(CheckPointer(pPEAssembly));
PRECONDITION(::GetAppDomain()==this);
POSTCONDITION(CheckPointer(RETVAL));
POSTCONDITION(RETVAL->GetLoadLevel() >= GetThreadFileLoadLevel()
POSTCONDITION(RETVAL->GetLoadLevel() >= GetCurrentFileLoadLevel()
|| RETVAL->GetLoadLevel() >= targetLevel);
POSTCONDITION(RETVAL->CheckNoError(targetLevel));
INJECT_FAULT(COMPlusThrowOM(););
Expand Down Expand Up @@ -2817,7 +2821,7 @@ DomainAssembly *AppDomain::LoadDomainAssembly(FileLoadLock *pLock, FileLoadLevel
STANDARD_VM_CHECK;
PRECONDITION(CheckPointer(pLock));
PRECONDITION(AppDomain::GetCurrentDomain() == this);
POSTCONDITION(RETVAL->GetLoadLevel() >= GetThreadFileLoadLevel()
POSTCONDITION(RETVAL->GetLoadLevel() >= GetCurrentFileLoadLevel()
|| RETVAL->GetLoadLevel() >= targetLevel);
POSTCONDITION(RETVAL->CheckNoError(targetLevel));
}
Expand Down
41 changes: 19 additions & 22 deletions src/coreclr/vm/appdomain.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ class StringLiteralMap;
class FrozenObjectHeapManager;
class MngStdInterfacesInfo;
class DomainAssembly;
class LoadLevelLimiter;
class TypeEquivalenceHashTable;

#ifdef FEATURE_COMINTEROP
Expand Down Expand Up @@ -815,44 +814,40 @@ typedef FileLoadLock::Holder FileLoadLockHolder;
typedef ListLockBase<NativeCodeVersion> JitListLock;
typedef ListLockEntryBase<NativeCodeVersion> JitListLockEntry;


#ifdef _MSC_VER
#pragma warning(push)
#pragma warning (disable: 4324) //sometimes 64bit compilers complain about alignment
#endif
class LoadLevelLimiter
class LoadLevelLimiter final
{
FileLoadLevel m_currentLevel;
static thread_local LoadLevelLimiter* t_currentLoadLevelLimiter;
jkotas marked this conversation as resolved.
Show resolved Hide resolved
FileLoadLevel m_currentLevel;
LoadLevelLimiter* m_previousLimit;
BOOL m_bActive;
bool m_bActive;

public:

LoadLevelLimiter()
: m_currentLevel(FILE_ACTIVE),
m_previousLimit(NULL),
m_bActive(FALSE)
m_previousLimit(nullptr),
m_bActive(false)
{
LIMITED_METHOD_CONTRACT;
}

void Activate()
{
WRAPPER_NO_CONTRACT;
m_previousLimit= GetThread()->GetLoadLevelLimiter();
if(m_previousLimit)
m_currentLevel=m_previousLimit->GetLoadLevel();
GetThread()->SetLoadLevelLimiter(this);
m_bActive=TRUE;
m_previousLimit = t_currentLoadLevelLimiter;
if (m_previousLimit)
m_currentLevel = m_previousLimit->GetLoadLevel();
t_currentLoadLevelLimiter = this;
m_bActive = true;
}

void Deactivate()
{
WRAPPER_NO_CONTRACT;
if (m_bActive)
{
GetThread()->SetLoadLevelLimiter(m_previousLimit);
m_bActive=FALSE;
t_currentLoadLevelLimiter = m_previousLimit;
m_bActive = false;
}
}

Expand Down Expand Up @@ -882,10 +877,13 @@ class LoadLevelLimiter
LIMITED_METHOD_CONTRACT;
m_currentLevel = level;
}

static LoadLevelLimiter* GetCurrent()
{
LIMITED_METHOD_CONTRACT;
return t_currentLoadLevelLimiter;
}
};
#ifdef _MSC_VER
#pragma warning (pop) //4324
#endif

#define OVERRIDE_LOAD_LEVEL_LIMIT(newLimit) \
LoadLevelLimiter __newLimit; \
Expand Down Expand Up @@ -1798,7 +1796,6 @@ class AppDomain : public BaseDomain
CHECK CheckLoading(DomainAssembly *pFile, FileLoadLevel level);

BOOL IsLoading(DomainAssembly *pFile, FileLoadLevel level);
static FileLoadLevel GetThreadFileLoadLevel();

void LoadDomainAssembly(DomainAssembly *pFile,
FileLoadLevel targetLevel);
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/arm/asmconstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,11 @@ ASMCONSTANTS_C_ASSERT(UnmanagedToManagedFrame__m_pvDatum == offsetof(UnmanagedTo

#endif // FEATURE_COMINTEROP

#define Thread__m_fPreemptiveGCDisabled 0x08
#define Thread__m_fPreemptiveGCDisabled 0x04
ASMCONSTANTS_C_ASSERT(Thread__m_fPreemptiveGCDisabled == offsetof(Thread, m_fPreemptiveGCDisabled));
#define Thread_m_fPreemptiveGCDisabled Thread__m_fPreemptiveGCDisabled

#define Thread__m_pFrame 0x0C
#define Thread__m_pFrame 0x08
ASMCONSTANTS_C_ASSERT(Thread__m_pFrame == offsetof(Thread, m_pFrame));
#define Thread_m_pFrame Thread__m_pFrame

Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/arm64/asmconstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@
#define DynamicHelperFrameFlags_ObjectArg 1
#define DynamicHelperFrameFlags_ObjectArg2 2

#define Thread__m_fPreemptiveGCDisabled 0x0C
#define Thread__m_pFrame 0x10
#define Thread__m_fPreemptiveGCDisabled 0x04
#define Thread__m_pFrame 0x08

ASMCONSTANTS_C_ASSERT(Thread__m_fPreemptiveGCDisabled == offsetof(Thread, m_fPreemptiveGCDisabled));
ASMCONSTANTS_C_ASSERT(Thread__m_pFrame == offsetof(Thread, m_pFrame));
Expand Down
15 changes: 8 additions & 7 deletions src/coreclr/vm/clsload.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3065,7 +3065,7 @@ TypeHandle ClassLoader::LoadTypeHandleForTypeKeyNoLock(const TypeKey *pTypeKey,
//
class PendingTypeLoadHolder
{
Thread * m_pThread;
static thread_local PendingTypeLoadHolder * t_pCurrent;
PendingTypeLoadTable::Entry * m_pEntry;
PendingTypeLoadHolder * m_pPrevious;

Expand All @@ -3074,26 +3074,25 @@ class PendingTypeLoadHolder
{
LIMITED_METHOD_CONTRACT;

m_pThread = GetThread();
m_pEntry = pEntry;

m_pPrevious = m_pThread->GetPendingTypeLoad();
m_pThread->SetPendingTypeLoad(this);
m_pPrevious = t_pCurrent;
t_pCurrent = this;
}

~PendingTypeLoadHolder()
{
LIMITED_METHOD_CONTRACT;

_ASSERTE(m_pThread->GetPendingTypeLoad() == this);
m_pThread->SetPendingTypeLoad(m_pPrevious);
_ASSERTE(t_pCurrent == this);
t_pCurrent = m_pPrevious;
}

static bool CheckForDeadLockOnCurrentThread(PendingTypeLoadTable::Entry * pEntry)
{
LIMITED_METHOD_CONTRACT;

PendingTypeLoadHolder * pCurrent = GetThread()->GetPendingTypeLoad();
PendingTypeLoadHolder * pCurrent = t_pCurrent;

while (pCurrent != NULL)
{
Expand All @@ -3107,6 +3106,8 @@ class PendingTypeLoadHolder
}
};

thread_local PendingTypeLoadHolder * PendingTypeLoadHolder::t_pCurrent = NULL;

//---------------------------------------------------------------------------------------
//
TypeHandle
Expand Down
6 changes: 3 additions & 3 deletions src/coreclr/vm/i386/asmconstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,13 +174,13 @@ ASMCONSTANTS_C_ASSERT(CORINFO_ArgumentException_ASM == CORINFO_ArgumentException



#define Thread_m_State 0x04
#define Thread_m_State 0x00
ASMCONSTANTS_C_ASSERT(Thread_m_State == offsetof(Thread, m_State))

#define Thread_m_fPreemptiveGCDisabled 0x08
#define Thread_m_fPreemptiveGCDisabled 0x04
ASMCONSTANTS_C_ASSERT(Thread_m_fPreemptiveGCDisabled == offsetof(Thread, m_fPreemptiveGCDisabled))

#define Thread_m_pFrame 0x0C
#define Thread_m_pFrame 0x08
ASMCONSTANTS_C_ASSERT(Thread_m_pFrame == offsetof(Thread, m_pFrame))


Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/loongarch64/asmconstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
#define DynamicHelperFrameFlags_ObjectArg 1
#define DynamicHelperFrameFlags_ObjectArg2 2

#define Thread__m_fPreemptiveGCDisabled 0x0C
#define Thread__m_pFrame 0x10
#define Thread__m_fPreemptiveGCDisabled 0x04
#define Thread__m_pFrame 0x08

ASMCONSTANTS_C_ASSERT(Thread__m_fPreemptiveGCDisabled == offsetof(Thread, m_fPreemptiveGCDisabled));
ASMCONSTANTS_C_ASSERT(Thread__m_pFrame == offsetof(Thread, m_pFrame));
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/riscv64/asmconstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@
#define DynamicHelperFrameFlags_ObjectArg 1
#define DynamicHelperFrameFlags_ObjectArg2 2

#define Thread__m_fPreemptiveGCDisabled 0x0C
#define Thread__m_pFrame 0x10
#define Thread__m_fPreemptiveGCDisabled 0x04
#define Thread__m_pFrame 0x08

ASMCONSTANTS_C_ASSERT(Thread__m_fPreemptiveGCDisabled == offsetof(Thread, m_fPreemptiveGCDisabled));
ASMCONSTANTS_C_ASSERT(Thread__m_pFrame == offsetof(Thread, m_pFrame));
Expand Down
17 changes: 13 additions & 4 deletions src/coreclr/vm/stackingallocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -427,24 +427,33 @@ void * __cdecl operator new[](size_t n, StackingAllocator * alloc, const NoThrow
return alloc->UnsafeAllocNoThrow((unsigned)n);
}

thread_local StackingAllocator* StackingAllocatorHolder::t_currentStackingAllocator = nullptr;

StackingAllocatorHolder::~StackingAllocatorHolder()
{
m_pStackingAllocator->Collapse(m_checkpointMarker);
if (m_owner)
{
m_thread->m_stackLocalAllocator = NULL;
t_currentStackingAllocator = NULL;
m_pStackingAllocator->~StackingAllocator();
}
}

StackingAllocatorHolder::StackingAllocatorHolder(StackingAllocator *pStackingAllocator, Thread *pThread, bool owner) :
StackingAllocatorHolder::StackingAllocatorHolder(StackingAllocator *pStackingAllocator, bool owner) :
m_pStackingAllocator(pStackingAllocator),
m_checkpointMarker(pStackingAllocator->GetCheckpoint()),
m_thread(pThread),
m_owner(owner)
{
_ASSERTE(pStackingAllocator != nullptr);
_ASSERTE((t_currentStackingAllocator == nullptr) == m_owner);
if (m_owner)
{
m_thread->m_stackLocalAllocator = pStackingAllocator;
t_currentStackingAllocator = pStackingAllocator;
}
}


StackingAllocator* StackingAllocatorHolder::GetCurrentThreadStackingAllocator()
{
return t_currentStackingAllocator;
}
20 changes: 13 additions & 7 deletions src/coreclr/vm/stackingallocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,14 +224,13 @@ private :
};

#define ACQUIRE_STACKING_ALLOCATOR(stackingAllocatorName) \
Thread *pThread__ACQUIRE_STACKING_ALLOCATOR = GetThread(); \
StackingAllocator *stackingAllocatorName = pThread__ACQUIRE_STACKING_ALLOCATOR->m_stackLocalAllocator; \
StackingAllocator *stackingAllocatorName = StackingAllocatorHolder::GetCurrentThreadStackingAllocator(); \
bool allocatorOwner__ACQUIRE_STACKING_ALLOCATOR = false; \
NewArrayHolder<char> heapAllocatedStackingBuffer__ACQUIRE_STACKING_ALLOCATOR; \
\
if (stackingAllocatorName == NULL) \
{ \
if (pThread__ACQUIRE_STACKING_ALLOCATOR->CheckCanUseStackAlloc()) \
if (GetThread()->CheckCanUseStackAlloc()) \
{ \
stackingAllocatorName = new (_alloca(sizeof(StackingAllocator))) StackingAllocator; \
} \
Expand All @@ -245,21 +244,28 @@ private :
}\
allocatorOwner__ACQUIRE_STACKING_ALLOCATOR = true; \
} \
StackingAllocatorHolder sah_ACQUIRE_STACKING_ALLOCATOR(stackingAllocatorName, pThread__ACQUIRE_STACKING_ALLOCATOR, allocatorOwner__ACQUIRE_STACKING_ALLOCATOR)
StackingAllocatorHolder sah_ACQUIRE_STACKING_ALLOCATOR(stackingAllocatorName, allocatorOwner__ACQUIRE_STACKING_ALLOCATOR)

class Thread;
class StackingAllocatorHolder
{
// Allocator used during marshaling for temporary buffers, much faster than
// heap allocation.
//
// Uses of this allocator should be effectively statically scoped, i.e. a "region"
// is started using a CheckPointHolder and GetCheckpoint, and this region can then be used for allocations
// from that point onwards, and then all memory is reclaimed when the static scope for the
// checkpoint is exited by the running thread.
static thread_local StackingAllocator* t_currentStackingAllocator;
StackingAllocator *m_pStackingAllocator;
void* m_checkpointMarker;
Thread* m_thread;
bool m_owner;

public:
~StackingAllocatorHolder();
StackingAllocatorHolder(StackingAllocator *pStackingAllocator, Thread *pThread, bool owner);
StackingAllocatorHolder(StackingAllocator *pStackingAllocator, bool owner);
StackingAllocator *GetStackingAllocator() { return m_pStackingAllocator; }
StackingAllocator &operator->() { return *m_pStackingAllocator; }
static StackingAllocator* GetCurrentThreadStackingAllocator();
};


Expand Down
Loading
Loading