Skip to content

Commit d64c06f

Browse files
cshungnoahfalk
andauthored
Avoid reporting frozen segments in GetGenerationBounds (#85727)
Co-authored-by: Noah Falk <[email protected]>
1 parent 876ab61 commit d64c06f

File tree

11 files changed

+91
-29
lines changed

11 files changed

+91
-29
lines changed

src/coreclr/gc/gc.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46166,15 +46166,15 @@ void gc_heap::descr_generations_to_profiler (gen_walk_fn fn, void *context)
4616646166
for (int curr_gen_number = total_generation_count-1; curr_gen_number >= 0; curr_gen_number--)
4616746167
{
4616846168
generation* gen = hp->generation_of (curr_gen_number);
46169-
heap_segment* seg = generation_start_segment (gen);
46169+
heap_segment* seg = heap_segment_rw (generation_start_segment (gen));
4617046170
#ifdef USE_REGIONS
4617146171
while (seg)
4617246172
{
4617346173
fn(context, curr_gen_number, heap_segment_mem (seg),
4617446174
heap_segment_allocated (seg),
4617546175
heap_segment_reserved (seg));
4617646176

46177-
seg = heap_segment_next (seg);
46177+
seg = heap_segment_next_rw (seg);
4617846178
}
4617946179
#else
4618046180
while (seg && (seg != hp->ephemeral_heap_segment))
@@ -46190,7 +46190,7 @@ void gc_heap::descr_generations_to_profiler (gen_walk_fn fn, void *context)
4619046190
(curr_gen_number > max_generation) ?
4619146191
heap_segment_reserved (seg) : heap_segment_allocated (seg));
4619246192

46193-
seg = heap_segment_next (seg);
46193+
seg = heap_segment_next_rw (seg);
4619446194
}
4619546195

4619646196
if (seg)

src/coreclr/gc/gcee.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ void GCHeap::ReportGenerationBounds()
6262
{
6363
g_theGCHeap->DiagDescrGenerations([](void*, int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved)
6464
{
65+
ASSERT((0 <= generation) && (generation <= poh_generation));
6566
uint64_t range = static_cast<uint64_t>(rangeEnd - rangeStart);
6667
uint64_t rangeReserved = static_cast<uint64_t>(rangeEndReserved - rangeStart);
6768
FIRE_EVENT(GCGenerationRange, (uint8_t)generation, rangeStart, range, rangeReserved);

src/coreclr/gc/gceventstatus.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,9 +174,9 @@ class GCEventStatus
174174
fprintf(stderr, "GCHeapSurvivalAndMovement ");
175175
}
176176

177-
if (keyword & GCEventKeyword_GCHeapCollect)
177+
if (keyword & GCEventKeyword_ManagedHeapCollect)
178178
{
179-
fprintf(stderr, "GCHeapCollect ");
179+
fprintf(stderr, "ManagedHeapCollect ");
180180
}
181181

182182
if (keyword & GCEventKeyword_GCHeapAndTypeNames)

src/coreclr/gc/gcinterface.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ enum GCEventKeyword
277277
GCEventKeyword_GCHeapDump = 0x100000,
278278
GCEventKeyword_GCSampledObjectAllocationHigh = 0x200000,
279279
GCEventKeyword_GCHeapSurvivalAndMovement = 0x400000,
280-
GCEventKeyword_GCHeapCollect = 0x800000,
280+
GCEventKeyword_ManagedHeapCollect = 0x800000,
281281
GCEventKeyword_GCHeapAndTypeNames = 0x1000000,
282282
GCEventKeyword_GCSampledObjectAllocationLow = 0x2000000,
283283
GCEventKeyword_All = GCEventKeyword_GC
@@ -287,7 +287,7 @@ enum GCEventKeyword
287287
| GCEventKeyword_GCHeapDump
288288
| GCEventKeyword_GCSampledObjectAllocationHigh
289289
| GCEventKeyword_GCHeapSurvivalAndMovement
290-
| GCEventKeyword_GCHeapCollect
290+
| GCEventKeyword_ManagedHeapCollect
291291
| GCEventKeyword_GCHeapAndTypeNames
292292
| GCEventKeyword_GCSampledObjectAllocationLow
293293
};

src/coreclr/nativeaot/Runtime/eventtrace.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ void ETW::GCLog::EndMovedReferences(size_t profilingContext,
417417
}
418418

419419
/***************************************************************************/
420-
/* This implements the public runtime provider's GCHeapCollectKeyword. It
420+
/* This implements the public runtime provider's ManagedHeapCollectKeyword. It
421421
performs a full, gen-2, blocking GC.
422422
/***************************************************************************/
423423
void ETW::GCLog::ForceGC(LONGLONG l64ClientSequenceNumber)

src/coreclr/nativeaot/Runtime/gcrhenv.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,12 @@ uint32_t EtwCallback(uint32_t IsEnabled, RH_ETW_CONTEXT * pContext)
8787
GCHeapUtilities::GetGCHeap()->DiagTraceGCSegments();
8888
}
8989

90-
// Special check for the runtime provider's GCHeapCollectKeyword. Profilers
90+
// Special check for the runtime provider's ManagedHeapCollectKeyword. Profilers
9191
// flick this to force a full GC.
9292
if (IsEnabled &&
9393
(pContext->RegistrationHandle == Microsoft_Windows_Redhawk_GC_PublicHandle) &&
9494
GCHeapUtilities::IsGCHeapInitialized() &&
95-
((pContext->MatchAnyKeyword & CLR_GCHEAPCOLLECT_KEYWORD) != 0))
95+
((pContext->MatchAnyKeyword & CLR_MANAGEDHEAPCOLLECT_KEYWORD) != 0))
9696
{
9797
// Profilers may (optionally) specify extra data in the filter parameter
9898
// to log with the GCStart event.

src/coreclr/nativeaot/Runtime/rheventtrace.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
#define CLR_GCHEAPDUMP_KEYWORD 0x100000
4141
#define CLR_GCHEAPALLOC_KEYWORD 0x200000
4242
#define CLR_GCHEAPSURVIVALANDMOVEMENT_KEYWORD 0x400000
43-
#define CLR_GCHEAPCOLLECT_KEYWORD 0x800000
43+
#define CLR_MANAGEDHEAPCOLLECT_KEYWORD 0x800000
4444
#define CLR_GCHEAPANDTYPENAMES_KEYWORD 0x1000000
4545
#define CLR_PERFTRACK_KEYWORD 0x20000000
4646
#define CLR_STACK_KEYWORD 0x40000000

src/coreclr/vm/ClrEtwAll.man

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@
5757
message="$(string.RuntimePublisher.GCSampledObjectAllocationHighKeywordMessage)" symbol="CLR_GCHEAPALLOCHIGH_KEYWORD"/>
5858
<keyword name="GCHeapSurvivalAndMovementKeyword" mask="0x400000"
5959
message="$(string.RuntimePublisher.GCHeapSurvivalAndMovementKeywordMessage)" symbol="CLR_GCHEAPSURVIVALANDMOVEMENT_KEYWORD"/>
60-
<keyword name="GCHeapCollectKeyword" mask="0x800000"
61-
message="$(string.RuntimePublisher.GCHeapCollectKeyword)" symbol="CLR_GCHEAPCOLLECT_KEYWORD"/>
60+
<keyword name="ManagedHeapCollectKeyword" mask="0x800000"
61+
message="$(string.RuntimePublisher.ManagedHeapCollectKeyword)" symbol="CLR_MANAGEDHEAPCOLLECT_KEYWORD"/>
6262
<keyword name="GCHeapAndTypeNamesKeyword" mask="0x1000000"
6363
message="$(string.RuntimePublisher.GCHeapAndTypeNamesKeyword)" symbol="CLR_GCHEAPANDTYPENAMES_KEYWORD"/>
6464
<keyword name="GCSampledObjectAllocationLowKeyword" mask="0x2000000"
@@ -3415,7 +3415,7 @@
34153415
symbol="GCBulkRootStaticVar" message="$(string.RuntimePublisher.GCBulkRootStaticVarEventMessage)"/>
34163416

34173417
<event value="39" version="0" level="win:LogAlways" template="GCDynamicEvent"
3418-
keywords= "GCKeyword GCHandleKeyword GCHeapDumpKeyword GCSampledObjectAllocationHighKeyword GCHeapSurvivalAndMovementKeyword GCHeapCollectKeyword GCHeapAndTypeNamesKeyword GCSampledObjectAllocationLowKeyword"
3418+
keywords= "GCKeyword GCHandleKeyword GCHeapDumpKeyword GCSampledObjectAllocationHighKeyword GCHeapSurvivalAndMovementKeyword ManagedHeapCollectKeyword GCHeapAndTypeNamesKeyword GCSampledObjectAllocationLowKeyword"
34193419
opcode="GCDynamicEvent"
34203420
task="GarbageCollection"
34213421
symbol="GCDynamicEvent"/>
@@ -9074,7 +9074,7 @@
90749074
<string id="RuntimePublisher.GCSampledObjectAllocationHighKeywordMessage" value="GCSampledObjectAllocationHigh" />
90759075
<string id="RuntimePublisher.GCSampledObjectAllocationLowKeywordMessage" value="GCSampledObjectAllocationLow" />
90769076
<string id="RuntimePublisher.GCHeapSurvivalAndMovementKeywordMessage" value="GCHeapSurvivalAndMovement" />
9077-
<string id="RuntimePublisher.GCHeapCollectKeyword" value="GCHeapCollect" />
9077+
<string id="RuntimePublisher.ManagedHeapCollectKeyword" value="ManagedHeapCollect" />
90789078
<string id="RuntimePublisher.GCHeapAndTypeNamesKeyword" value="GCHeapAndTypeNames" />
90799079
<string id="RuntimePublisher.GCHandleKeywordMessage" value="GCHandle" />
90809080
<string id="RuntimePublisher.ThreadTransferKeywordMessage" value="ThreadTransfer" />

src/coreclr/vm/eventtrace.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -851,7 +851,7 @@ VOID ETW::GCLog::EndMovedReferences(size_t profilingContext, BOOL fAllowProfApiN
851851
}
852852

853853
/***************************************************************************/
854-
/* This implements the public runtime provider's GCHeapCollectKeyword. It
854+
/* This implements the public runtime provider's ManagedHeapCollectKeyword. It
855855
performs a full, gen-2, blocking GC. */
856856
/***************************************************************************/
857857
VOID ETW::GCLog::ForceGC(LONGLONG l64ClientSequenceNumber)
@@ -4326,10 +4326,10 @@ void InitializeEventTracing()
43264326
// that ultimately funnels them all into a common handler.
43274327

43284328
#if defined(HOST_UNIX)
4329-
// CLR_GCHEAPCOLLECT_KEYWORD is defined by the generated ETW manifest on Windows.
4329+
// CLR_MANAGEDHEAPCOLLECT_KEYWORD is defined by the generated ETW manifest on Windows.
43304330
// On non-Windows, we need to make sure that this is defined. Given that we can't change
43314331
// the value due to compatibility, we specify it here rather than generating defines based on the manifest.
4332-
#define CLR_GCHEAPCOLLECT_KEYWORD 0x800000
4332+
#define CLR_MANAGEDHEAPCOLLECT_KEYWORD 0x800000
43334333
#endif // defined(HOST_UNIX)
43344334

43354335
// CallbackProviderIndex provides a quick identification of which provider triggered the
@@ -4417,10 +4417,10 @@ VOID EtwCallbackCommon(
44174417
GCHeapUtilities::RecordEventStateChange(bIsPublicTraceHandle, keywords, level);
44184418
}
44194419

4420-
// Special check for the runtime provider's GCHeapCollectKeyword. Profilers
4420+
// Special check for the runtime provider's ManagedHeapCollectKeyword. Profilers
44214421
// flick this to force a full GC.
44224422
if (g_fEEStarted && !g_fEEShutDown && bIsPublicTraceHandle &&
4423-
((MatchAnyKeyword & CLR_GCHEAPCOLLECT_KEYWORD) != 0))
4423+
((MatchAnyKeyword & CLR_MANAGEDHEAPCOLLECT_KEYWORD) != 0))
44244424
{
44254425
// Profilers may (optionally) specify extra data in the filter parameter
44264426
// to log with the GCStart event.

src/coreclr/vm/proftoeeinterfaceimpl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7689,7 +7689,7 @@ HRESULT ProfToEEInterfaceImpl::GetNonGCHeapBounds(ULONG cObjectRanges,
76897689
ranges[segIdx].rangeStart = (ObjectID)firstObj;
76907690

76917691
// Total size reserved for a segment
7692-
ranges[segIdx].rangeLengthReserved = (UINT_PTR)segments[segIdx]->m_Size;
7692+
ranges[segIdx].rangeLengthReserved = (UINT_PTR)segments[segIdx]->m_Size - sizeof(ObjHeader);
76937693

76947694
// Size of the segment that is currently in use
76957695
ranges[segIdx].rangeLength = (UINT_PTR)(segments[segIdx]->m_pCurrent - firstObj);

src/tests/profiler/native/nongcheap/nongcheap.cpp

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
#include "nongcheap.h"
5+
#include <vector>
56

67
GUID NonGcHeapProfiler::GetClsid()
78
{
@@ -59,46 +60,106 @@ HRESULT NonGcHeapProfiler::GarbageCollectionFinished()
5960

6061
_garbageCollections++;
6162

62-
const int MAX_NON_GC_HEAP_SEGMENTS = 16;
63-
COR_PRF_NONGC_HEAP_RANGE segments[MAX_NON_GC_HEAP_SEGMENTS];
63+
std::vector<ULONG> segment_starts;
64+
std::vector<ULONG> segment_ends;
65+
const int MAX_SEGMENTS = 16;
66+
COR_PRF_NONGC_HEAP_RANGE nongc_segments[MAX_SEGMENTS];
67+
COR_PRF_GC_GENERATION_RANGE gc_segments[MAX_SEGMENTS];
6468
ULONG segCount;
6569
ObjectID firstObj = 0;
66-
HRESULT hr = pCorProfilerInfo->GetNonGCHeapBounds(MAX_NON_GC_HEAP_SEGMENTS, &segCount, segments);
70+
HRESULT hr = pCorProfilerInfo->GetNonGCHeapBounds(MAX_SEGMENTS, &segCount, nongc_segments);
6771
if (FAILED(hr))
6872
{
6973
printf("GetNonGCHeapBounds returned an error\n!");
7074
_failures++;
7175
}
72-
else if (segCount == 0 || segCount > MAX_NON_GC_HEAP_SEGMENTS)
76+
else if (segCount == 0 || segCount > MAX_SEGMENTS)
7377
{
7478
printf("GetNonGCHeapBounds: invalid segCount (%u)\n!", segCount);
7579
_failures++;
7680
}
7781
else
7882
{
7983
// Save very first object ID to compare with EnumerateNonGCObjects
80-
firstObj = segments[0].rangeStart;
84+
firstObj = nongc_segments[0].rangeStart;
8185

8286
printf("\nGetNonGCHeapBounds (segCount = %u):\n", segCount);
8387
for (ULONG i = 0; i < segCount; i++)
8488
{
8589
printf("\tseg#%u, rangeStart=%p, rangeLength=%u, rangeLengthReserved=%u\n",
86-
i, (void*)segments[i].rangeStart, (ULONG)segments[i].rangeLength, (ULONG)segments[i].rangeLengthReserved);
90+
i, (void*)nongc_segments[i].rangeStart, (ULONG)nongc_segments[i].rangeLength, (ULONG)nongc_segments[i].rangeLengthReserved);
8791

88-
if ((ULONG)segments[i].rangeLength > (ULONG)segments[i].rangeLengthReserved)
92+
if ((ULONG)nongc_segments[i].rangeLength > (ULONG)nongc_segments[i].rangeLengthReserved)
8993
{
9094
printf("GetNonGCHeapBounds: rangeLength > rangeLengthReserved");
9195
_failures++;
9296
}
9397

94-
if (!segments[i].rangeStart)
98+
if (!nongc_segments[i].rangeStart)
9599
{
96100
printf("GetNonGCHeapBounds: rangeStart is null");
97101
_failures++;
98102
}
103+
segment_starts.emplace_back((ULONG)nongc_segments[i].rangeStart);
104+
segment_ends.emplace_back((ULONG)nongc_segments[i].rangeStart + (ULONG)nongc_segments[i].rangeLengthReserved);
99105
}
100106
printf("\n");
101107
}
108+
hr = pCorProfilerInfo->GetGenerationBounds(MAX_SEGMENTS, &segCount, gc_segments);
109+
if (FAILED(hr))
110+
{
111+
printf("GetGenerationBounds returned an error\n!");
112+
_failures++;
113+
}
114+
else if (segCount == 0 || segCount > MAX_SEGMENTS)
115+
{
116+
printf("GetGenerationBounds: invalid segCount (%u)\n!", segCount);
117+
_failures++;
118+
}
119+
else
120+
{
121+
printf("\nGetGenerationBounds (segCount = %u):\n", segCount);
122+
for (ULONG i = 0; i < segCount; i++)
123+
{
124+
printf("\tseg#%u, rangeStart=%p, rangeLength=%u, rangeLengthReserved=%u\n",
125+
i, (void*)gc_segments[i].rangeStart, (ULONG)gc_segments[i].rangeLength, (ULONG)gc_segments[i].rangeLengthReserved);
126+
127+
if ((ULONG)gc_segments[i].rangeLength > (ULONG)gc_segments[i].rangeLengthReserved)
128+
{
129+
printf("GetGenerationBounds: rangeLength > rangeLengthReserved");
130+
_failures++;
131+
}
132+
133+
if (!gc_segments[i].rangeStart)
134+
{
135+
printf("GetGenerationBounds: rangeStart is null");
136+
_failures++;
137+
}
138+
segment_starts.emplace_back((ULONG)gc_segments[i].rangeStart);
139+
segment_ends.emplace_back((ULONG)gc_segments[i].rangeStart + (ULONG)gc_segments[i].rangeLengthReserved);
140+
}
141+
printf("\n");
142+
}
143+
sort(segment_starts.begin(), segment_starts.end());
144+
sort(segment_ends.begin(), segment_ends.end());
145+
for (size_t i = 0; i < segment_starts.size() - 1; i++)
146+
{
147+
if (segment_starts[i] == segment_starts[i+1])
148+
{
149+
printf("Duplicated segment starts");
150+
_failures++;
151+
}
152+
if (segment_ends[i] == segment_ends[i+1])
153+
{
154+
printf("Duplicated segment ends");
155+
_failures++;
156+
}
157+
if (segment_ends[i] > segment_starts[i+1])
158+
{
159+
printf("Overlapping segments\n");
160+
_failures++;
161+
}
162+
}
102163

103164
// Let's make sure we got the same number of objects as we got from the callback
104165
// by testing the EnumerateNonGCObjects API.

0 commit comments

Comments
 (0)