Skip to content

Commit

Permalink
Move various thread-local objects that were used in self-contained pl…
Browse files Browse the repository at this point in the history
…aces out of Thread (#99989)
  • Loading branch information
jkoritzinsky authored Mar 22, 2024
1 parent 8fd3b7a commit 1a36949
Show file tree
Hide file tree
Showing 16 changed files with 89 additions and 508 deletions.
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;
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

0 comments on commit 1a36949

Please sign in to comment.