Skip to content

Commit ff1d146

Browse files
committed
update comments and revert mitigation for active ICF + g_TrapReturningThreads
1 parent dfa6322 commit ff1d146

File tree

1 file changed

+21
-1
lines changed

1 file changed

+21
-1
lines changed

src/coreclr/vm/gccover.cpp

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1293,6 +1293,16 @@ void RemoveGcCoverageInterrupt(TADDR instrPtr, BYTE * savedInstrPtr, GCCoverageI
12931293
FlushInstructionCache(GetCurrentProcess(), (LPCVOID)instrPtr, 4);
12941294
}
12951295

1296+
// A managed thread (T) can race with the GC as follows:
1297+
// 1) Current thread T is in preemptive mode, GC happens, starts scanning T's stack.
1298+
// 2) The Jitted code puts thread T to cooperative mode, as part of PInvoke epilog.
1299+
// 3) Jitted code checks g_TrapReturningThreads, calls CORINFO_HELP_STOP_FOR_GC()
1300+
// 4) If any of the code that does #3 is interruptible, we may hit GCStress trap and start
1301+
// another round of GCStress while in Cooperative mode.
1302+
// 5) Now, thread T can modify the stack (ex: RedirectionFrame setup) while the GC thread is scanning it.
1303+
//
1304+
// This race is now mitigated below. Where we won't initiate a stress mode GC
1305+
// for a thread in cooperative mode with an active ICF, if g_TrapReturningThreads is true.
12961306
BOOL OnGcCoverageInterrupt(PCONTEXT regs)
12971307
{
12981308
PCODE controlPc = GetIP(regs);
@@ -1324,12 +1334,22 @@ BOOL OnGcCoverageInterrupt(PCONTEXT regs)
13241334
}
13251335

13261336
// The thread is in preemptive mode. Normally, it should not be able to trigger GC.
1337+
// Besides the GC may be already happening and scanning our stack.
13271338
if (!pThread->PreemptiveGCDisabled())
13281339
{
13291340
RemoveGcCoverageInterrupt(instrPtr, savedInstrPtr, gcCover, offset);
13301341
return TRUE;
13311342
}
13321343

1344+
// If we're supposed to stop for GC,
1345+
// and there's an active ICF, don't initiate a stress GC.
1346+
Frame* pFrame = pThread->GetFrame();
1347+
if (g_TrapReturningThreads && InlinedCallFrame::FrameHasActiveCall(pFrame))
1348+
{
1349+
RemoveGcCoverageInterrupt(instrPtr, savedInstrPtr, gcCover, offset);
1350+
return TRUE;
1351+
}
1352+
13331353
#ifdef _DEBUG
13341354
if (g_pConfig->SkipGCCoverage(pMD->GetModule()->GetSimpleName()))
13351355
{
@@ -1338,7 +1358,7 @@ BOOL OnGcCoverageInterrupt(PCONTEXT regs)
13381358
}
13391359
#endif
13401360

1341-
#if defined(USE_REDIRECT_FOR_GCSTRESS) && !defined(TARGET_UNIX)
1361+
#ifdef USE_REDIRECT_FOR_GCSTRESS
13421362
// If we're unable to redirect, then we simply won't test GC at this location.
13431363
if (Thread::UseRedirectForGcStress())
13441364
{

0 commit comments

Comments
 (0)