Repository: dotnet/runtime
File: src/coreclr/vm/finalizerthread.cpp (C++)

Code before:
    if (g_pConfig->FastGCStressLevel())
    {
        GetFinalizerThread()->m_GCOnTransitionsOK = FALSE;
    }
#endif
    GetFinalizerThread()->EnablePreemptiveGC();
#ifdef _DEBUG
    if (g_pConfig->FastGCStressLevel())
    {
        GetFinalizerThread()->m_GCOnTransitionsOK = TRUE;
    }
#endif
#if 0
    // Setting the event here, instead of at the bottom of the loop, could
    // cause us to skip draining the Q, if the request is made as soon as
    // the app starts running.
    SignalFinalizationDone();
#endif //0

    WaitForFinalizerEvent (hEventFinalizer);

    // Process pending finalizer work items from the GC first.
    FinalizerWorkItem* pWork = GCHeapUtilities::GetGCHeap()->GetExtraWorkForFinalization();
    while (pWork != NULL)
    {
        FinalizerWorkItem* pNext = pWork->next;
        pWork->callback(pWork);
        pWork = pNext;
    }

#if defined(__linux__) && defined(FEATURE_EVENT_TRACE)
    if (g_TriggerHeapDump && (minipal_lowres_ticks() > (LastHeapDumpTime + LINUX_HEAP_DUMP_TIME_OUT)))
    {
        s_forcedGCInProgress = true;
        GetFinalizerThread()->DisablePreemptiveGC();
        GCHeapUtilities::GetGCHeap()->GarbageCollect(2, false, collection_blocking);
        GetFinalizerThread()->EnablePreemptiveGC();
        s_forcedGCInProgress = false;

        LastHeapDumpTime = minipal_lowres_ticks();
        g_TriggerHeapDump = FALSE;
    }
#endif
    if (gcGenAnalysisState == GcGenAnalysisState::Done)
    {
        gcGenAnalysisState = GcGenAnalysisState::Disabled;
        if (gcGenAnalysisTrace)
        {
#ifdef FEATURE_PERFTRACING
            EventPipeAdapter::Disable(gcGenAnalysisEventPipeSessionId);
#ifdef GEN_ANALYSIS_STRESS

Review comment (bug):
This runs with MODE_PREEMPTIVE here (due to `GetFinalizerThread()->EnablePreemptiveGC` above), but MODE_COOPERATIVE on the wasm path. I think we want to run it in the same mode in both cases. Move `GetFinalizerThread()->EnablePreemptive` and the debug-only ifdefs around it before the wasm-specific ifdef?

Code after:
    {
        GetFinalizerThread()->m_GCOnTransitionsOK = FALSE;
    }
#endif
    GetFinalizerThread()->EnablePreemptiveGC();
#ifdef _DEBUG
    if (g_pConfig->FastGCStressLevel())
    {
        GetFinalizerThread()->m_GCOnTransitionsOK = TRUE;
    }
#endif

#ifndef TARGET_WASM
#if 0
    // Setting the event here, instead of at the bottom of the loop, could
    // cause us to skip draining the Q, if the request is made as soon as
    // the app starts running.
    SignalFinalizationDone();
#endif //0

    // Wait for work to do...
    WaitForFinalizerEvent (hEventFinalizer);

#endif // !TARGET_WASM

    // Process pending finalizer work items from the GC first.
    FinalizerWorkItem* pWork = GCHeapUtilities::GetGCHeap()->GetExtraWorkForFinalization();
    while (pWork != NULL)
    {
        FinalizerWorkItem* pNext = pWork->next;
        pWork->callback(pWork);
        pWork = pNext;
    }

#ifndef TARGET_WASM
#if defined(__linux__) && defined(FEATURE_EVENT_TRACE)
    if (g_TriggerHeapDump && (minipal_lowres_ticks() > (LastHeapDumpTime + LINUX_HEAP_DUMP_TIME_OUT)))
    {
        s_forcedGCInProgress = true;
        GetFinalizerThread()->DisablePreemptiveGC();
        GCHeapUtilities::GetGCHeap()->GarbageCollect(2, false, collection_blocking);
        GetFinalizerThread()->EnablePreemptiveGC();
        s_forcedGCInProgress = false;

        LastHeapDumpTime = minipal_lowres_ticks();
        g_TriggerHeapDump = FALSE;
    }
#endif
    if (gcGenAnalysisState == GcGenAnalysisState::Done)
    {
        gcGenAnalysisState = GcGenAnalysisState::Disabled;