From 3d629b1387f90a28f81199760def73edccea5b27 Mon Sep 17 00:00:00 2001 From: Peter Sollich Date: Tue, 1 Sep 2020 15:11:15 +0200 Subject: [PATCH] Backport fix for issue 41413 to release/5.0. --- src/coreclr/src/gc/gc.cpp | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/src/coreclr/src/gc/gc.cpp b/src/coreclr/src/gc/gc.cpp index 34c983521b614f..704eea7eccb266 100644 --- a/src/coreclr/src/gc/gc.cpp +++ b/src/coreclr/src/gc/gc.cpp @@ -37853,15 +37853,26 @@ size_t GCHeap::ApproxTotalBytesInUse(BOOL small_heap_only) size_t totsize = 0; enter_spin_lock (&pGenGCHeap->gc_lock); - heap_segment* eph_seg = generation_allocation_segment (pGenGCHeap->generation_of (0)); - // Get small block heap size info - totsize = (pGenGCHeap->alloc_allocated - heap_segment_mem (eph_seg)); - heap_segment* seg1 = generation_start_segment (pGenGCHeap->generation_of (max_generation)); - while (seg1 != eph_seg) - { - totsize += heap_segment_allocated (seg1) - - heap_segment_mem (seg1); - seg1 = heap_segment_next (seg1); + // the complication with the following code is that background GC may + // remove the ephemeral segment while we are iterating + // if so, we retry a couple times and ultimately may report a slightly wrong result + for (int tries = 1; tries <= 3; tries++) + { + heap_segment* eph_seg = generation_allocation_segment (pGenGCHeap->generation_of (0)); + // Get small block heap size info + totsize = (pGenGCHeap->alloc_allocated - heap_segment_mem (eph_seg)); + heap_segment* seg1 = generation_start_segment (pGenGCHeap->generation_of (max_generation)); + while ((seg1 != eph_seg) && (seg1 != nullptr) && (seg1 != pGenGCHeap->freeable_soh_segment)) + { + if (!heap_segment_decommitted_p (seg1)) + { + totsize += heap_segment_allocated (seg1) - + heap_segment_mem (seg1); + } + seg1 = heap_segment_next (seg1); + } + if (seg1 == eph_seg) + break; } //discount the fragmentation