Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/coreclr/inc/CrstTypes.def
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,10 @@ Crst AssemblyLoader
AcquiredBefore DeadlockDetection UniqueStack DebuggerMutex
End

Crst AsyncContinuations
AcquiredBefore LeafLock
End

Crst AvailableClass
AcquiredBefore LoaderHeap
End
Expand Down
205 changes: 104 additions & 101 deletions src/coreclr/inc/crsttypes_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,107 +18,108 @@ enum CrstType
CrstAppDomainCache = 0,
CrstAssemblyList = 1,
CrstAssemblyLoader = 2,
CrstAvailableClass = 3,
CrstAvailableParamTypes = 4,
CrstCallStubCache = 5,
CrstCCompRC = 6,
CrstClassFactInfoHash = 7,
CrstClassInit = 8,
CrstClrNotification = 9,
CrstCodeFragmentHeap = 10,
CrstCodeVersioning = 11,
CrstCOMCallWrapper = 12,
CrstCOMWrapperCache = 13,
CrstDataTest1 = 14,
CrstDataTest2 = 15,
CrstDbgTransport = 16,
CrstDeadlockDetection = 17,
CrstDebuggerController = 18,
CrstDebuggerFavorLock = 19,
CrstDebuggerHeapExecMemLock = 20,
CrstDebuggerHeapLock = 21,
CrstDebuggerJitInfo = 22,
CrstDebuggerMutex = 23,
CrstDynamicIL = 24,
CrstDynamicMT = 25,
CrstEtwTypeLogHash = 26,
CrstEventPipe = 27,
CrstEventStore = 28,
CrstException = 29,
CrstExecutableAllocatorLock = 30,
CrstFCall = 31,
CrstFrozenObjectHeap = 32,
CrstFuncPtrStubs = 33,
CrstFusionAppCtx = 34,
CrstGCCover = 35,
CrstGenericDictionaryExpansion = 36,
CrstGlobalStrLiteralMap = 37,
CrstHandleTable = 38,
CrstIJWFixupData = 39,
CrstIJWHash = 40,
CrstILStubGen = 41,
CrstInlineTrackingMap = 42,
CrstInstMethodHashTable = 43,
CrstInterfaceDispatchGlobalLists = 44,
CrstInterop = 45,
CrstInteropData = 46,
CrstIsJMCMethod = 47,
CrstISymUnmanagedReader = 48,
CrstJit = 49,
CrstJitInlineTrackingMap = 50,
CrstJitPatchpoint = 51,
CrstJumpStubCache = 52,
CrstLeafLock = 53,
CrstListLock = 54,
CrstLoaderAllocator = 55,
CrstLoaderAllocatorReferences = 56,
CrstLoaderHeap = 57,
CrstManagedObjectWrapperMap = 58,
CrstMethodDescBackpatchInfoTracker = 59,
CrstMethodTableExposedObject = 60,
CrstModule = 61,
CrstModuleLookupTable = 62,
CrstMulticoreJitHash = 63,
CrstMulticoreJitManager = 64,
CrstNativeImageEagerFixups = 65,
CrstNativeImageLoad = 66,
CrstNotifyGdb = 67,
CrstPEImage = 68,
CrstPendingTypeLoadEntry = 69,
CrstPerfMap = 70,
CrstPgoData = 71,
CrstPinnedByrefValidation = 72,
CrstPinnedHeapHandleTable = 73,
CrstProfilerGCRefDataFreeList = 74,
CrstProfilingAPIStatus = 75,
CrstRCWCache = 76,
CrstRCWCleanupList = 77,
CrstReadyToRunEntryPointToMethodDescMap = 78,
CrstReflection = 79,
CrstReJITGlobalRequest = 80,
CrstSigConvert = 81,
CrstSingleUseLock = 82,
CrstStressLog = 83,
CrstStubCache = 84,
CrstStubDispatchCache = 85,
CrstSyncBlockCache = 86,
CrstSyncHashLock = 87,
CrstSystemDomain = 88,
CrstSystemDomainDelayedUnloadList = 89,
CrstThreadIdDispenser = 90,
CrstThreadLocalStorageLock = 91,
CrstThreadStore = 92,
CrstTieredCompilation = 93,
CrstTypeEquivalenceMap = 94,
CrstTypeIDMap = 95,
CrstUMEntryThunkCache = 96,
CrstUMEntryThunkFreeListLock = 97,
CrstUniqueStack = 98,
CrstUnresolvedClassLock = 99,
CrstUnwindInfoTableLock = 100,
CrstVSDIndirectionCellLock = 101,
CrstWrapperTemplate = 102,
kNumberOfCrstTypes = 103
CrstAsyncContinuations = 3,
CrstAvailableClass = 4,
CrstAvailableParamTypes = 5,
CrstCallStubCache = 6,
CrstCCompRC = 7,
CrstClassFactInfoHash = 8,
CrstClassInit = 9,
CrstClrNotification = 10,
CrstCodeFragmentHeap = 11,
CrstCodeVersioning = 12,
CrstCOMCallWrapper = 13,
CrstCOMWrapperCache = 14,
CrstDataTest1 = 15,
CrstDataTest2 = 16,
CrstDbgTransport = 17,
CrstDeadlockDetection = 18,
CrstDebuggerController = 19,
CrstDebuggerFavorLock = 20,
CrstDebuggerHeapExecMemLock = 21,
CrstDebuggerHeapLock = 22,
CrstDebuggerJitInfo = 23,
CrstDebuggerMutex = 24,
CrstDynamicIL = 25,
CrstDynamicMT = 26,
CrstEtwTypeLogHash = 27,
CrstEventPipe = 28,
CrstEventStore = 29,
CrstException = 30,
CrstExecutableAllocatorLock = 31,
CrstFCall = 32,
CrstFrozenObjectHeap = 33,
CrstFuncPtrStubs = 34,
CrstFusionAppCtx = 35,
CrstGCCover = 36,
CrstGenericDictionaryExpansion = 37,
CrstGlobalStrLiteralMap = 38,
CrstHandleTable = 39,
CrstIJWFixupData = 40,
CrstIJWHash = 41,
CrstILStubGen = 42,
CrstInlineTrackingMap = 43,
CrstInstMethodHashTable = 44,
CrstInterfaceDispatchGlobalLists = 45,
CrstInterop = 46,
CrstInteropData = 47,
CrstIsJMCMethod = 48,
CrstISymUnmanagedReader = 49,
CrstJit = 50,
CrstJitInlineTrackingMap = 51,
CrstJitPatchpoint = 52,
CrstJumpStubCache = 53,
CrstLeafLock = 54,
CrstListLock = 55,
CrstLoaderAllocator = 56,
CrstLoaderAllocatorReferences = 57,
CrstLoaderHeap = 58,
CrstManagedObjectWrapperMap = 59,
CrstMethodDescBackpatchInfoTracker = 60,
CrstMethodTableExposedObject = 61,
CrstModule = 62,
CrstModuleLookupTable = 63,
CrstMulticoreJitHash = 64,
CrstMulticoreJitManager = 65,
CrstNativeImageEagerFixups = 66,
CrstNativeImageLoad = 67,
CrstNotifyGdb = 68,
CrstPEImage = 69,
CrstPendingTypeLoadEntry = 70,
CrstPerfMap = 71,
CrstPgoData = 72,
CrstPinnedByrefValidation = 73,
CrstPinnedHeapHandleTable = 74,
CrstProfilerGCRefDataFreeList = 75,
CrstProfilingAPIStatus = 76,
CrstRCWCache = 77,
CrstRCWCleanupList = 78,
CrstReadyToRunEntryPointToMethodDescMap = 79,
CrstReflection = 80,
CrstReJITGlobalRequest = 81,
CrstSigConvert = 82,
CrstSingleUseLock = 83,
CrstStressLog = 84,
CrstStubCache = 85,
CrstStubDispatchCache = 86,
CrstSyncBlockCache = 87,
CrstSyncHashLock = 88,
CrstSystemDomain = 89,
CrstSystemDomainDelayedUnloadList = 90,
CrstThreadIdDispenser = 91,
CrstThreadLocalStorageLock = 92,
CrstThreadStore = 93,
CrstTieredCompilation = 94,
CrstTypeEquivalenceMap = 95,
CrstTypeIDMap = 96,
CrstUMEntryThunkCache = 97,
CrstUMEntryThunkFreeListLock = 98,
CrstUniqueStack = 99,
CrstUnresolvedClassLock = 100,
CrstUnwindInfoTableLock = 101,
CrstVSDIndirectionCellLock = 102,
CrstWrapperTemplate = 103,
kNumberOfCrstTypes = 104
};

#endif // __CRST_TYPES_INCLUDED
Expand All @@ -132,6 +133,7 @@ int g_rgCrstLevelMap[] =
9, // CrstAppDomainCache
2, // CrstAssemblyList
13, // CrstAssemblyLoader
2, // CrstAsyncContinuations
3, // CrstAvailableClass
4, // CrstAvailableParamTypes
3, // CrstCallStubCache
Expand Down Expand Up @@ -240,6 +242,7 @@ LPCSTR g_rgCrstNameMap[] =
"CrstAppDomainCache",
"CrstAssemblyList",
"CrstAssemblyLoader",
"CrstAsyncContinuations",
"CrstAvailableClass",
"CrstAvailableParamTypes",
"CrstCallStubCache",
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/asynccontinuations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ AsyncContinuationsManager::AsyncContinuationsManager(LoaderAllocator* allocator)
{
LIMITED_METHOD_CONTRACT;

m_layoutsLock.Init(CrstLeafLock);
m_layoutsLock.Init(CrstAsyncContinuations);
LockOwner lock = {&m_layoutsLock, IsOwnerOfCrst};
m_layouts.Init(16, &lock, m_allocator->GetLowFrequencyHeap());
}
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/vm/ceemain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -791,9 +791,9 @@ void EEStartupHelper()
// Cache the (potentially user-overridden) values now so they are accessible from asm routines
InitializeSpinConstants();

// Initialize EBR (Epoch-Based Reclamation) for HashMap's async mode.
// Initialize EBR (Epoch-Based Reclamation) for safe deferred deletion.
// This must be done before any HashMap is initialized with fAsyncMode=TRUE.
g_HashMapEbr.Init();
g_EbrCollector.Init();

StubManager::InitializeStubManagers();

Expand Down
12 changes: 7 additions & 5 deletions src/coreclr/vm/ebr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@ struct EbrTlsDestructor final
};
static thread_local EbrTlsDestructor t_ebrTlsDestructor;

// Global EBR collector for HashMap's async mode.
// If you want to add another usage for Ebr in the future, please consider
// the tradeoffs between creating multiple collectors or treating this as
// a single shared global collector.
EbrCollector g_HashMapEbr;
// Global EBR collector for safe deferred deletion of memory that may be
// concurrently accessed by reader threads.
//
// A single collector is used because each thread has a single thread-local
// EbrThreadData that can only be associated with one collector at a time.
EbrCollector g_EbrCollector;

// ============================================
// EbrCollector implementation
Expand Down Expand Up @@ -141,6 +142,7 @@ EbrCollector::GetOrCreateThreadData()
return pData;

_ASSERTE_ALL_BUILDS(pData->m_pCollector != DetachedCollector && "Attempt to reattach detached thread.");
_ASSERTE_ALL_BUILDS(pData->m_pCollector == nullptr && "Thread already registered with a different collector.");

pData->m_pCollector = this;

Expand Down
12 changes: 7 additions & 5 deletions src/coreclr/vm/ebr.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@
//
// Usage:
// // Startup:
// g_HashMapEbr.Init();
// g_EbrCollector.Init();
//
// // Reader/Writer thread:
// {
// EbrCriticalRegionHolder ebr(&g_HashMapEbr, m_fAsyncMode);
// EbrCriticalRegionHolder ebr(&g_EbrCollector, fAsyncMode);
// // ... access shared data safely ...
// // Objects queued for deletion will not be freed while any thread
// // is in a critical region that observed a prior epoch.
// }
//
// // Writer thread (inside critical region), after replacing shared pointer:
// g_HashMapEbr.QueueForDeletion(pOldData, deleteFn, sizeEstimate);
// g_EbrCollector.QueueForDeletion(pOldData, deleteFn, sizeEstimate);
//
// // Shutdown:
// The EBR collector doesn't support a shutdown feature. CoreCLR doesn't support
Expand Down Expand Up @@ -117,8 +117,10 @@ class EbrCollector final
Volatile<size_t> m_pendingSizeInBytes;
};

// Global EBR collector for HashMap's async mode.
extern EbrCollector g_HashMapEbr;
// Global EBR collector for safe deferred deletion of memory that may be
// concurrently accessed by reader threads (e.g. HashMap and EEHashTable
// bucket arrays during resize).
extern EbrCollector g_EbrCollector;

// RAII holder for EBR critical regions, analogous to GCX_COOP pattern.
// When fEnable is false, the holder is a no-op.
Expand Down
42 changes: 42 additions & 0 deletions src/coreclr/vm/eehash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,48 @@

#ifndef DACCESS_COMPILE

// ============================================================================
// Bucket array allocation helpers for EEHashTable.
// ============================================================================

// Allocate a zero-initialized bucket array with space for 'dwNumBuckets' buckets
// plus a reserved leading slot. Returns a pointer past the leading slot (matching
// the m_pBuckets convention), or NULL on failure.
EEHashEntry_t** AllocateEEHashBuckets(DWORD dwNumBuckets)
{
CONTRACTL
{
NOTHROW;
GC_NOTRIGGER;
}
CONTRACTL_END

DWORD dwNumBucketsPlusOne;
if (!ClrSafeInt<DWORD>::addition(dwNumBuckets, 1, dwNumBucketsPlusOne))
return NULL;

S_SIZE_T safeSize(sizeof(EEHashEntry_t*));
safeSize *= dwNumBucketsPlusOne;
if (safeSize.IsOverflow())
return NULL;

SIZE_T cbAlloc = safeSize.Value();
EEHashEntry_t** pBuckets = (EEHashEntry_t**) new (nothrow) BYTE[cbAlloc];
if (pBuckets == NULL)
return NULL;

memset(pBuckets, 0, cbAlloc);

// The first slot is reserved; usable buckets start after it.
return pBuckets + 1;
}

void FreeEEHashBuckets(EEHashEntry_t** pBuckets)
{
LIMITED_METHOD_CONTRACT;
delete[] (BYTE*)(pBuckets - 1);
}

// ============================================================================
// Unicode string hash table helper.
// ============================================================================
Expand Down
8 changes: 6 additions & 2 deletions src/coreclr/vm/eehash.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ struct EEHashTableIteration;

class GCHeap;

// Bucket array allocation helpers for EEHashTable.
EEHashEntry_t** AllocateEEHashBuckets(DWORD dwNumBuckets);
void FreeEEHashBuckets(EEHashEntry_t** pBuckets);

// Generic hash table.

template <class KeyType, class Helper, BOOL bDefaultCopyIsDeep>
Expand Down Expand Up @@ -94,7 +98,7 @@ class EEHashTableBase
// A fast inlinable flavor of GetValue that can return false instead of the actual item
// if there is race with updating of the hashtable. Callers of GetValueSpeculative
// should fall back to the slow GetValue if GetValueSpeculative returns false.
// Assumes that we are in cooperative mode already. For performance-sensitive codepaths.
// Uses EBR internally for safe concurrent access. For performance-sensitive codepaths.
BOOL GetValueSpeculative(KeyType pKey, HashDatum *pData);
BOOL GetValueSpeculative(KeyType pKey, HashDatum *pData, DWORD hashValue);

Expand Down Expand Up @@ -140,7 +144,7 @@ class EEHashTableBase
// A fast inlinable flavor of FindItem that can return null instead of the actual item
// if there is race with updating of the hashtable. Callers of FindItemSpeculative
// should fall back to the slow FindItem if FindItemSpeculative returns null.
// Assumes that we are in cooperative mode already. For performance-sensitive codepaths.
// Uses EBR internally for safe concurrent access. For performance-sensitive codepaths.
EEHashEntry_t * FindItemSpeculative(KeyType pKey, DWORD hashValue);

// Double buffer to fix the race condition of growhashtable (the update
Expand Down
Loading
Loading