From 1cb5adf9a0b46560e433d63af902ffd0c9b2a74e Mon Sep 17 00:00:00 2001 From: vsadov <8218165+VSadov@users.noreply.github.com> Date: Tue, 19 Aug 2025 02:06:08 -0700 Subject: [PATCH 1/2] Throttle finalization a bit when doing GC stress. --- src/coreclr/vm/finalizerthread.cpp | 41 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/src/coreclr/vm/finalizerthread.cpp b/src/coreclr/vm/finalizerthread.cpp index 0ad3d680bcd8bc..e091fb39d3b187 100644 --- a/src/coreclr/vm/finalizerthread.cpp +++ b/src/coreclr/vm/finalizerthread.cpp @@ -176,6 +176,26 @@ OBJECTREF FinalizerThread::GetNextFinalizableObject() if (fQuitFinalizer) return NULL; +#ifdef _DEBUG + if (g_pConfig->GetGCStressLevel() > 1) + { + // Throttle finalizing to one item per msec, or so, when running GC stress. + // This is to prevent cases where finalizers rearm themselves and + // do allocations or whatever else that triggers GC under stress. + // As a result couple of such things can occupy finalizer loop continuously + // while rearming and finalizing the same objects, which adds little + // to the coverage, but makes everything else move slower. + // NOTE: under GC stress most allocations of finalizable objects + // would trigger a GC, thus 1 item/msec should not be too slow for + // regular not re-arming finalizables. + GetFinalizerThread()->m_GCOnTransitionsOK = FALSE; + GetFinalizerThread()->EnablePreemptiveGC(); + ClrSleepEx(1, false); + GetFinalizerThread()->DisablePreemptiveGC(); + GetFinalizerThread()->m_GCOnTransitionsOK = TRUE; + } +#endif //_DEBUG + OBJECTREF obj = ObjectToOBJECTREF(GCHeapUtilities::GetGCHeap()->GetNextFinalizable()); if (obj == NULL) return NULL; @@ -432,27 +452,6 @@ VOID FinalizerThread::FinalizerThreadWorker(void *args) GetFinalizerThread()->DisablePreemptiveGC(); -#ifdef _DEBUG - // workaround. make finalization very lazy for gcstress 3 or 4. - // only do finalization if the system is quiescent - if (g_pConfig->GetGCStressLevel() > 1) - { - size_t last_gc_count; - DWORD dwSwitchCount = 0; - - do - { - last_gc_count = GCHeapUtilities::GetGCHeap()->CollectionCount(0); - GetFinalizerThread()->m_GCOnTransitionsOK = FALSE; - GetFinalizerThread()->EnablePreemptiveGC(); - __SwitchToThread (0, ++dwSwitchCount); - GetFinalizerThread()->DisablePreemptiveGC(); - // If no GCs happened, then we assume we are quiescent - GetFinalizerThread()->m_GCOnTransitionsOK = TRUE; - } while (GCHeapUtilities::GetGCHeap()->CollectionCount(0) - last_gc_count > 0); - } -#endif //_DEBUG - // we might want to do some extra work on the finalizer thread // check and do it if (HaveExtraWorkForFinalizer()) From 446901e7777fdc22ce7807a9777bad9216ccf3d6 Mon Sep 17 00:00:00 2001 From: vsadov <8218165+VSadov@users.noreply.github.com> Date: Fri, 22 Aug 2025 17:07:11 -0700 Subject: [PATCH 2/2] fix indentation --- src/coreclr/vm/finalizerthread.cpp | 34 +++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/coreclr/vm/finalizerthread.cpp b/src/coreclr/vm/finalizerthread.cpp index e091fb39d3b187..ef5949ec055404 100644 --- a/src/coreclr/vm/finalizerthread.cpp +++ b/src/coreclr/vm/finalizerthread.cpp @@ -177,23 +177,23 @@ OBJECTREF FinalizerThread::GetNextFinalizableObject() return NULL; #ifdef _DEBUG - if (g_pConfig->GetGCStressLevel() > 1) - { - // Throttle finalizing to one item per msec, or so, when running GC stress. - // This is to prevent cases where finalizers rearm themselves and - // do allocations or whatever else that triggers GC under stress. - // As a result couple of such things can occupy finalizer loop continuously - // while rearming and finalizing the same objects, which adds little - // to the coverage, but makes everything else move slower. - // NOTE: under GC stress most allocations of finalizable objects - // would trigger a GC, thus 1 item/msec should not be too slow for - // regular not re-arming finalizables. - GetFinalizerThread()->m_GCOnTransitionsOK = FALSE; - GetFinalizerThread()->EnablePreemptiveGC(); - ClrSleepEx(1, false); - GetFinalizerThread()->DisablePreemptiveGC(); - GetFinalizerThread()->m_GCOnTransitionsOK = TRUE; - } + if (g_pConfig->GetGCStressLevel() > 1) + { + // Throttle finalizing to one item per msec, or so, when running GC stress. + // This is to prevent cases where finalizers rearm themselves and + // do allocations or whatever else that triggers GC under stress. + // As a result couple of such things can occupy finalizer loop continuously + // while rearming and finalizing the same objects, which adds little + // to the coverage, but makes everything else move slower. + // NOTE: under GC stress most allocations of finalizable objects + // would trigger a GC, thus 1 item/msec should not be too slow for + // regular not re-arming finalizables. + GetFinalizerThread()->m_GCOnTransitionsOK = FALSE; + GetFinalizerThread()->EnablePreemptiveGC(); + ClrSleepEx(1, false); + GetFinalizerThread()->DisablePreemptiveGC(); + GetFinalizerThread()->m_GCOnTransitionsOK = TRUE; + } #endif //_DEBUG OBJECTREF obj = ObjectToOBJECTREF(GCHeapUtilities::GetGCHeap()->GetNextFinalizable());