Skip to content

Commit eab49b9

Browse files
committed
RS deletion correction and comments on a whole schema
1 parent 25e5c2e commit eab49b9

3 files changed

Lines changed: 187 additions & 59 deletions

File tree

src/coreclr/inc/dacvars.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@
7878
DEFINE_DACVAR(LONG, ExecutionManager__m_dwForbidDeletionCounter, ExecutionManager::m_dwForbidDeletionCounter)
7979
DEFINE_DACVAR(PTR_RangeSectionHandleHeader, ExecutionManager__m_RangeSectionHandleReaderHeader, ExecutionManager::m_RangeSectionHandleReaderHeader)
8080
DEFINE_DACVAR(PTR_RangeSectionHandleHeader, ExecutionManager__m_RangeSectionHandleWriterHeader, ExecutionManager::m_RangeSectionHandleWriterHeader)
81-
DEFINE_DACVAR_VOLATILE(PTR_RangeSection, ExecutionManager__m_RangeSectionPendingDeletion, ExecutionManager::m_RangeSectionPendingDeletion)
8281
DEFINE_DACVAR(PTR_EECodeManager, ExecutionManager__m_pDefaultCodeMan, ExecutionManager::m_pDefaultCodeMan)
8382

8483
DEFINE_DACVAR(PTR_EEJitManager, ExecutionManager__m_pEEJitManager, ExecutionManager::m_pEEJitManager)

src/coreclr/vm/codeman.cpp

Lines changed: 67 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ SPTR_IMPL(ReadyToRunJitManager, ExecutionManager, m_pReadyToRunJitManager);
5252
SVAL_IMPL_INIT(LONG, ExecutionManager, m_dwForbidDeletionCounter, 0);
5353
SPTR_IMPL_INIT(RangeSectionHandleHeader, ExecutionManager, m_RangeSectionHandleReaderHeader, nullptr);
5454
SPTR_IMPL_INIT(RangeSectionHandleHeader, ExecutionManager, m_RangeSectionHandleWriterHeader, nullptr);
55-
VOLATILE_SPTR_IMPL_INIT(RangeSection, ExecutionManager, m_RangeSectionPendingDeletion, nullptr);
5655

5756
#ifndef DACCESS_COMPILE
5857

@@ -678,14 +677,10 @@ ExecutionManager::ForbidDeletionHolder::~ForbidDeletionHolder()
678677

679678
//---------------------------------------------------------------------------------------
680679
//
681-
// ReaderLockHolder::ReaderLockHolder takes the reader lock, checks for the writer lock
682-
// and either aborts if the writer lock is held, or yields until the writer lock is released,
683-
// keeping the reader lock. This is normally called in the constructor for the
684-
// ReaderLockHolder.
685-
//
686-
// The writer cannot be taken if there are any readers. The WriterLockHolder functions take the
687-
// writer lock and check for any readers. If there are any, the WriterLockHolder functions
688-
// release the writer and yield to wait for the readers to be done.
680+
// ReaderLockHolder::ReaderLockHolder Increments rh->count.
681+
// This is normally called in the constructor for the ReaderLockHolder.
682+
// Always succeeds and never yields.
683+
// Detailed explanation provided in codeman.h on top of the document.
689684

690685
ExecutionManager::ReaderLockHolder::ReaderLockHolder(HostCallPreference pref): m_pref(pref)
691686
{
@@ -713,7 +708,8 @@ ExecutionManager::ReaderLockHolder::ReaderLockHolder(HostCallPreference pref): m
713708

714709
//---------------------------------------------------------------------------------------
715710
//
716-
// See code:ExecutionManager::ReaderLockHolder::ReaderLockHolder. This just decrements the reader count.
711+
// Decrements the reader count.
712+
// Detailed explanation provided in codeman.h on top of the document.
717713

718714
ExecutionManager::ReaderLockHolder::~ReaderLockHolder()
719715
{
@@ -738,19 +734,15 @@ ExecutionManager::ReaderLockHolder::~ReaderLockHolder()
738734
{
739735
//we are here in relatively rare case
740736
//such code executes once per swap of arrays,
741-
//so we should not worry about enormous amount
742-
//of m_RangeSectionPendingDeletion accesses
743737
if (m_pref == AllowHostCalls)
744738
{
745-
while((RangeSection*)m_RangeSectionPendingDeletion != NULL)
739+
if(h->pDelete != NULL)
746740
{
747-
RangeSection* pNext = ((RangeSection*)m_RangeSectionPendingDeletion)->pNextPendingDeletion;
748741
#if defined(TARGET_AMD64)
749-
if (((RangeSection*)m_RangeSectionPendingDeletion)->pUnwindInfoTable != 0)
750-
delete ((RangeSection*)m_RangeSectionPendingDeletion)->pUnwindInfoTable;
742+
if (h->pDelete->pUnwindInfoTable != 0)
743+
delete (h->pDelete->pUnwindInfoTable);
751744
#endif // defined(TARGET_AMD64)
752-
delete (RangeSection*)m_RangeSectionPendingDeletion;
753-
m_RangeSectionPendingDeletion = pNext;
745+
delete h->pDelete;
754746
}
755747
}
756748

@@ -763,6 +755,11 @@ ExecutionManager::ReaderLockHolder::~ReaderLockHolder()
763755
}
764756

765757

758+
//---------------------------------------------------------------------------------------
759+
//
760+
// WriterLockHolder::WriterLockHolder wraps wh->rh substitution logic
761+
// Detailed explanation provided in codeman.h on top of the document.
762+
766763
ExecutionManager::WriterLockHolder::WriterLockHolder(int purpose): m_purpose(purpose)
767764
{
768765
CONTRACTL {
@@ -793,6 +790,11 @@ ExecutionManager::WriterLockHolder::WriterLockHolder(int purpose): m_purpose(pur
793790
EE_LOCK_TAKEN((void*)h);
794791
}
795792

793+
//---------------------------------------------------------------------------------------
794+
//
795+
// WriterLockHolder::~WriterLockHolder wraps wh->rh substitution logic
796+
// Detailed explanation provided in codeman.h on top of the document.
797+
796798
ExecutionManager::WriterLockHolder::~WriterLockHolder()
797799
{
798800
LIMITED_METHOD_CONTRACT;
@@ -837,15 +839,13 @@ ExecutionManager::WriterLockHolder::~WriterLockHolder()
837839
if (count == 1)// h->count == 0, all readers left, we've just removed EM's unit,
838840
//now attach the header to writer's slot:
839841
{
840-
while((RangeSection*)m_RangeSectionPendingDeletion != NULL)
842+
if(old_rh->pDelete != NULL)
841843
{
842-
RangeSection* pNext = ((RangeSection*)m_RangeSectionPendingDeletion)->pNextPendingDeletion;
843844
#if defined(TARGET_AMD64)
844-
if (((RangeSection*)m_RangeSectionPendingDeletion)->pUnwindInfoTable != 0)
845-
delete ((RangeSection*)m_RangeSectionPendingDeletion)->pUnwindInfoTable;
845+
if (old_rh->pDelete->pUnwindInfoTable != 0)
846+
delete (old_rh->pDelete->pUnwindInfoTable);
846847
#endif // defined(TARGET_AMD64)
847-
delete (RangeSection*)m_RangeSectionPendingDeletion;
848-
m_RangeSectionPendingDeletion = pNext;
848+
delete old_rh->pDelete;
849849
}
850850

851851
VolatileStore(&m_RangeSectionHandleWriterHeader, old_rh);
@@ -864,7 +864,6 @@ ExecutionManager::WriterLockHolder::~WriterLockHolder()
864864
}
865865
#else
866866

867-
// For DAC builds we never actually take the lock.
868867
// Note: Throws
869868
ExecutionManager::ReaderLockHolder::ReaderLockHolder(HostCallPreference pref)
870869
{
@@ -910,21 +909,30 @@ ExecutionManager::ForbidDeletionHolder::~ForbidDeletionHolder()
910909
//-----------------------------------------------------------------------------
911910
912911
==============================================================================
913-
ExecutionManger::ReaderLockHolder and ExecutionManger::WriterLockHolder
914-
Protects the callers of ExecutionManager::GetRangeSection from heap deletions
915-
while walking RangeSections. You need to take a reader lock before reading the
916-
values: m_CodeRangeList and hold it while walking the lists
912+
ExecutionManger::ReaderLockHolder, ExecutionManger::WriterLockHolder
913+
and ExecutionManger::ForbidDeletionHolder
914+
protect the callers of ExecutionManager::GetRangeSection from heap deletions
915+
while walking RangeSections. You need to initialize a ForbidDeletionHolder
916+
if someone simultaneously may call DeleteRange
917+
918+
Detailed explanation provided in codeman.h on top of the document.
917919
918-
Uses ReaderLockHolder (allows multiple reeaders with no writers)
920+
921+
Uses ReaderLockHolder
919922
-----------------------------------------
920-
ExecutionManager::FindCodeRange
921-
ExecutionManager::FindZapModule
922-
ExecutionManager::EnumMemoryRegions
923+
ExecutionManager::GetRangeSection
923924
924-
Uses WriterLockHolder (allows single writer and no readers)
925+
Uses WriterLockHolder
925926
-----------------------------------------
926-
ExecutionManager::AddRangeHelper
927-
ExecutionManager::DeleteRangeHelper
927+
ExecutionManager::AddRangeSection
928+
ExecutionManager::DeleteRange
929+
930+
Uses ForbidDeletionHolder
931+
-----------------------------------------
932+
ExecutionManager::IsManagedCodeWithLock
933+
ExecutionManager::IsManagedCode
934+
ExecutionManager::FindZapModule
935+
ExecutionManager::FindReadyToRunModule
928936
929937
*/
930938

@@ -1087,10 +1095,10 @@ IJitManager::IJitManager()
10871095
#endif // #ifndef DACCESS_COMPILE
10881096

10891097
// When we unload an appdomain, we need to make sure that any threads that are crawling through
1090-
// our heap or rangelist are out. For cooperative-mode threads, we know that they will have
1098+
// our heap list or range storage are out. For cooperative-mode threads, we know that they will have
10911099
// been stopped when we suspend the EE so they won't be touching an element that is about to be deleted.
10921100
// However for pre-emptive mode threads, they could be stalled right on top of the element we want
1093-
// to delete, so we need to apply the reader lock to them and wait for them to drain.
1101+
// to delete, so we need to apply the ForbidDeletionHolder to them and wait for them to drain.
10941102
ExecutionManager::ScanFlag ExecutionManager::GetScanFlags()
10951103
{
10961104
CONTRACTL {
@@ -2419,7 +2427,7 @@ void CodeFragmentHeap::RealBackoutMem(void *pMem
24192427
//**************************************************************************
24202428

24212429
LoaderCodeHeap::LoaderCodeHeap()
2422-
: m_LoaderHeap(NULL, // RangeList *pRangeList
2430+
: m_LoaderHeap(NULL,
24232431
TRUE), // BOOL fMakeExecutable
24242432
m_cbMinNextPad(0)
24252433
{
@@ -4730,8 +4738,8 @@ BOOL ExecutionManager::IsManagedCode(PCODE currentPC, HostCallPreference hostCal
47304738
}
47314739

47324740
//**************************************************************************
4733-
// Assumes that the ExecutionManager reader/writer lock is taken or that
4734-
// it is safe not to take it. //TODO edit comment
4741+
// Assumes that the ExecutionManager ForbidDeletionHolder is taken or that
4742+
// it is safe not to take it.
47354743
BOOL ExecutionManager::IsManagedCodeWorker(PCODE currentPC, HostCallPreference pref)
47364744
{
47374745
CONTRACTL {
@@ -4772,7 +4780,7 @@ BOOL ExecutionManager::IsManagedCodeWorker(PCODE currentPC, HostCallPreference p
47724780
}
47734781

47744782
//**************************************************************************
4775-
// Assumes that it is safe not to take it the ExecutionManager reader/writer lock
4783+
// Assumes that it is safe not to take the ForbidDeletionHolder
47764784
BOOL ExecutionManager::IsReadyToRunCode(PCODE currentPC)
47774785
{
47784786
CONTRACTL{
@@ -5130,12 +5138,14 @@ void ExecutionManager::AddRangeSection(RangeSection *pRS)
51305138
wh->array[0].pRS = pRS;
51315139
wh->count = 0;
51325140
wh->last_used_index = 0;
5141+
wh->pDelete = nullptr;
51335142

51345143
RangeSectionHandleHeader *rh = new RangeSectionHandleHeader();
51355144
rh->capacity = wh->capacity;
51365145
rh->size = wh->size;
51375146
rh->count = 1; //EM's unit
51385147
rh->last_used_index = wh->last_used_index;
5148+
rh->pDelete = nullptr;
51395149
rh->array = new RangeSectionHandle[rh->capacity];
51405150

51415151
rh->array[0] = wh->array[0];
@@ -5192,6 +5202,7 @@ void ExecutionManager::AddRangeSection(RangeSection *pRS)
51925202
wh->array[size].LowAddress = pRS->LowAddress;
51935203
wh->array[size].pRS = pRS;
51945204
wh->size = size + 1;
5205+
wh->pDelete = nullptr;
51955206
//last used index was not changed by this operation
51965207
return; //assume that ~WriterLockHolder() executes before ~CrstHolder()
51975208
}
@@ -5206,11 +5217,13 @@ void ExecutionManager::AddRangeSection(RangeSection *pRS)
52065217
wh->array[index].LowAddress = pRS->LowAddress;
52075218
wh->array[index].pRS = pRS;
52085219
wh->size = size + 1;
5220+
wh->pDelete = nullptr;
52095221
int ri = VolatileLoad(&(rh->last_used_index));
52105222
if (ri >= index)
52115223
wh->last_used_index = ri + 1;
52125224
return;
52135225
}
5226+
wh->pDelete = nullptr;
52145227
return;
52155228
}
52165229

@@ -5253,24 +5266,28 @@ void ExecutionManager::DeleteRange(TADDR pStartRange)
52535266
} CONTRACTL_END;
52545267

52555268
{
5256-
// Acquire the Crst before unlinking a RangeList.
5257-
// NOTE: The Crst must be acquired BEFORE we grab the writer lock, as the
5258-
// writer lock forces us into a forbid suspend thread region, and it's illegal
5259-
// to enter a Crst after the forbid suspend thread region is entered
5269+
// Acquire the Crst to protect writers from each other.
5270+
// NOTE: The Crst must be acquired BEFORE we grab the wlh, as the
5271+
// wlh us into a forbid suspend thread region, and it's illegal
5272+
// to enter a Crst after the forbid suspend thread region is entered.
5273+
// Also wlh acts as a wrapper of reader/writer header interchanging
5274+
// logic and depends on Crst to allow only one wlh accessor at a time.
52605275
CrstHolder ch(&m_RangeCrst);
52615276

5262-
// Acquire the WriterLock and prevent any readers from walking the RangeList.
5263-
// This also forces us to enter a forbid suspend thread region, to prevent
5277+
// Acquirnig the wlh DOES NOT prevent any readers from walking the RangeSectionStorage.
5278+
// Wlh forces us to enter a forbid suspend thread region, to prevent
52645279
// hijacking profilers from grabbing this thread and walking it (the walk may
52655280
// require the reader lock, which would cause a deadlock).
5281+
5282+
// Detailed explanation of rlh/wlh/fdh model provided in codeman.h on top of the document.
5283+
52665284
WriterLockHolder wlh(1); //1 for deletion purpose
52675285
RangeSectionHandleHeader *rh = VolatileLoad(&m_RangeSectionHandleReaderHeader);
52685286
int index = FindRangeSectionHandleHelper(rh, pStartRange);
52695287

52705288
if (index >= 0)
52715289
{
5272-
rh->array[index].pRS->pNextPendingDeletion = (RangeSection*)m_RangeSectionPendingDeletion;
5273-
m_RangeSectionPendingDeletion = rh->array[index].pRS;
5290+
wlh.h->pDelete = rh->array[index].pRS;
52745291
DeleteRangeSection(wlh.h, rh, index);
52755292
}
52765293
}

0 commit comments

Comments
 (0)