Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid reporting frozen segments in GetGenerationBounds #85727

Merged
merged 10 commits into from
Jul 1, 2023
Merged
6 changes: 3 additions & 3 deletions src/coreclr/gc/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46166,15 +46166,15 @@ void gc_heap::descr_generations_to_profiler (gen_walk_fn fn, void *context)
for (int curr_gen_number = total_generation_count-1; curr_gen_number >= 0; curr_gen_number--)
{
generation* gen = hp->generation_of (curr_gen_number);
heap_segment* seg = generation_start_segment (gen);
heap_segment* seg = heap_segment_rw (generation_start_segment (gen));
#ifdef USE_REGIONS
while (seg)
{
fn(context, curr_gen_number, heap_segment_mem (seg),
heap_segment_allocated (seg),
heap_segment_reserved (seg));

seg = heap_segment_next (seg);
seg = heap_segment_next_rw (seg);
}
#else
while (seg && (seg != hp->ephemeral_heap_segment))
Expand All @@ -46190,7 +46190,7 @@ void gc_heap::descr_generations_to_profiler (gen_walk_fn fn, void *context)
(curr_gen_number > max_generation) ?
heap_segment_reserved (seg) : heap_segment_allocated (seg));

seg = heap_segment_next (seg);
seg = heap_segment_next_rw (seg);
}

if (seg)
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/gc/gcee.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ void GCHeap::ReportGenerationBounds()
{
g_theGCHeap->DiagDescrGenerations([](void*, int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved)
{
ASSERT((0 <= generation) && (generation <= poh_generation));
uint64_t range = static_cast<uint64_t>(rangeEnd - rangeStart);
uint64_t rangeReserved = static_cast<uint64_t>(rangeEndReserved - rangeStart);
FIRE_EVENT(GCGenerationRange, (uint8_t)generation, rangeStart, range, rangeReserved);
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/gc/gceventstatus.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,9 +174,9 @@ class GCEventStatus
fprintf(stderr, "GCHeapSurvivalAndMovement ");
}

if (keyword & GCEventKeyword_GCHeapCollect)
if (keyword & GCEventKeyword_ManagedHeapCollect)
{
fprintf(stderr, "GCHeapCollect ");
fprintf(stderr, "ManagedHeapCollect ");
}

if (keyword & GCEventKeyword_GCHeapAndTypeNames)
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/gc/gcinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ enum GCEventKeyword
GCEventKeyword_GCHeapDump = 0x100000,
GCEventKeyword_GCSampledObjectAllocationHigh = 0x200000,
GCEventKeyword_GCHeapSurvivalAndMovement = 0x400000,
GCEventKeyword_GCHeapCollect = 0x800000,
GCEventKeyword_ManagedHeapCollect = 0x800000,
GCEventKeyword_GCHeapAndTypeNames = 0x1000000,
GCEventKeyword_GCSampledObjectAllocationLow = 0x2000000,
GCEventKeyword_All = GCEventKeyword_GC
Expand All @@ -287,7 +287,7 @@ enum GCEventKeyword
| GCEventKeyword_GCHeapDump
| GCEventKeyword_GCSampledObjectAllocationHigh
| GCEventKeyword_GCHeapSurvivalAndMovement
| GCEventKeyword_GCHeapCollect
| GCEventKeyword_ManagedHeapCollect
| GCEventKeyword_GCHeapAndTypeNames
| GCEventKeyword_GCSampledObjectAllocationLow
};
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/eventtrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,7 @@ void ETW::GCLog::EndMovedReferences(size_t profilingContext,
}

/***************************************************************************/
/* This implements the public runtime provider's GCHeapCollectKeyword. It
/* This implements the public runtime provider's ManagedHeapCollectKeyword. It
performs a full, gen-2, blocking GC.
/***************************************************************************/
void ETW::GCLog::ForceGC(LONGLONG l64ClientSequenceNumber)
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/nativeaot/Runtime/gcrhenv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ uint32_t EtwCallback(uint32_t IsEnabled, RH_ETW_CONTEXT * pContext)
GCHeapUtilities::GetGCHeap()->DiagTraceGCSegments();
}

// Special check for the runtime provider's GCHeapCollectKeyword. Profilers
// Special check for the runtime provider's ManagedHeapCollectKeyword. Profilers
// flick this to force a full GC.
if (IsEnabled &&
(pContext->RegistrationHandle == Microsoft_Windows_Redhawk_GC_PublicHandle) &&
GCHeapUtilities::IsGCHeapInitialized() &&
((pContext->MatchAnyKeyword & CLR_GCHEAPCOLLECT_KEYWORD) != 0))
((pContext->MatchAnyKeyword & CLR_MANAGEDHEAPCOLLECT_KEYWORD) != 0))
{
// Profilers may (optionally) specify extra data in the filter parameter
// to log with the GCStart event.
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/nativeaot/Runtime/rheventtrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
#define CLR_GCHEAPDUMP_KEYWORD 0x100000
#define CLR_GCHEAPALLOC_KEYWORD 0x200000
#define CLR_GCHEAPSURVIVALANDMOVEMENT_KEYWORD 0x400000
#define CLR_GCHEAPCOLLECT_KEYWORD 0x800000
#define CLR_MANAGEDHEAPCOLLECT_KEYWORD 0x800000
#define CLR_GCHEAPANDTYPENAMES_KEYWORD 0x1000000
#define CLR_PERFTRACK_KEYWORD 0x20000000
#define CLR_STACK_KEYWORD 0x40000000
Expand Down
8 changes: 4 additions & 4 deletions src/coreclr/vm/ClrEtwAll.man
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@
message="$(string.RuntimePublisher.GCSampledObjectAllocationHighKeywordMessage)" symbol="CLR_GCHEAPALLOCHIGH_KEYWORD"/>
<keyword name="GCHeapSurvivalAndMovementKeyword" mask="0x400000"
message="$(string.RuntimePublisher.GCHeapSurvivalAndMovementKeywordMessage)" symbol="CLR_GCHEAPSURVIVALANDMOVEMENT_KEYWORD"/>
<keyword name="GCHeapCollectKeyword" mask="0x800000"
message="$(string.RuntimePublisher.GCHeapCollectKeyword)" symbol="CLR_GCHEAPCOLLECT_KEYWORD"/>
<keyword name="ManagedHeapCollectKeyword" mask="0x800000"
message="$(string.RuntimePublisher.ManagedHeapCollectKeyword)" symbol="CLR_MANAGEDHEAPCOLLECT_KEYWORD"/>
<keyword name="GCHeapAndTypeNamesKeyword" mask="0x1000000"
message="$(string.RuntimePublisher.GCHeapAndTypeNamesKeyword)" symbol="CLR_GCHEAPANDTYPENAMES_KEYWORD"/>
<keyword name="GCSampledObjectAllocationLowKeyword" mask="0x2000000"
Expand Down Expand Up @@ -3415,7 +3415,7 @@
symbol="GCBulkRootStaticVar" message="$(string.RuntimePublisher.GCBulkRootStaticVarEventMessage)"/>

<event value="39" version="0" level="win:LogAlways" template="GCDynamicEvent"
keywords= "GCKeyword GCHandleKeyword GCHeapDumpKeyword GCSampledObjectAllocationHighKeyword GCHeapSurvivalAndMovementKeyword GCHeapCollectKeyword GCHeapAndTypeNamesKeyword GCSampledObjectAllocationLowKeyword"
keywords= "GCKeyword GCHandleKeyword GCHeapDumpKeyword GCSampledObjectAllocationHighKeyword GCHeapSurvivalAndMovementKeyword ManagedHeapCollectKeyword GCHeapAndTypeNamesKeyword GCSampledObjectAllocationLowKeyword"
opcode="GCDynamicEvent"
task="GarbageCollection"
symbol="GCDynamicEvent"/>
Expand Down Expand Up @@ -9074,7 +9074,7 @@
<string id="RuntimePublisher.GCSampledObjectAllocationHighKeywordMessage" value="GCSampledObjectAllocationHigh" />
<string id="RuntimePublisher.GCSampledObjectAllocationLowKeywordMessage" value="GCSampledObjectAllocationLow" />
<string id="RuntimePublisher.GCHeapSurvivalAndMovementKeywordMessage" value="GCHeapSurvivalAndMovement" />
<string id="RuntimePublisher.GCHeapCollectKeyword" value="GCHeapCollect" />
<string id="RuntimePublisher.ManagedHeapCollectKeyword" value="ManagedHeapCollect" />
<string id="RuntimePublisher.GCHeapAndTypeNamesKeyword" value="GCHeapAndTypeNames" />
<string id="RuntimePublisher.GCHandleKeywordMessage" value="GCHandle" />
<string id="RuntimePublisher.ThreadTransferKeywordMessage" value="ThreadTransfer" />
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/vm/eventtrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -851,7 +851,7 @@ VOID ETW::GCLog::EndMovedReferences(size_t profilingContext, BOOL fAllowProfApiN
}

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

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

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

// Special check for the runtime provider's GCHeapCollectKeyword. Profilers
// Special check for the runtime provider's ManagedHeapCollectKeyword. Profilers
// flick this to force a full GC.
if (g_fEEStarted && !g_fEEShutDown && bIsPublicTraceHandle &&
((MatchAnyKeyword & CLR_GCHEAPCOLLECT_KEYWORD) != 0))
((MatchAnyKeyword & CLR_MANAGEDHEAPCOLLECT_KEYWORD) != 0))
{
// Profilers may (optionally) specify extra data in the filter parameter
// to log with the GCStart event.
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/vm/proftoeeinterfaceimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7689,7 +7689,7 @@ HRESULT ProfToEEInterfaceImpl::GetNonGCHeapBounds(ULONG cObjectRanges,
ranges[segIdx].rangeStart = (ObjectID)firstObj;

// Total size reserved for a segment
ranges[segIdx].rangeLengthReserved = (UINT_PTR)segments[segIdx]->m_Size;
ranges[segIdx].rangeLengthReserved = (UINT_PTR)segments[segIdx]->m_Size - sizeof(ObjHeader);
cshung marked this conversation as resolved.
Show resolved Hide resolved

// Size of the segment that is currently in use
ranges[segIdx].rangeLength = (UINT_PTR)(segments[segIdx]->m_pCurrent - firstObj);
Expand Down
77 changes: 69 additions & 8 deletions src/tests/profiler/native/nongcheap/nongcheap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

#include "nongcheap.h"
#include <vector>

GUID NonGcHeapProfiler::GetClsid()
{
Expand Down Expand Up @@ -59,46 +60,106 @@ HRESULT NonGcHeapProfiler::GarbageCollectionFinished()

_garbageCollections++;

const int MAX_NON_GC_HEAP_SEGMENTS = 16;
COR_PRF_NONGC_HEAP_RANGE segments[MAX_NON_GC_HEAP_SEGMENTS];
std::vector<ULONG> segment_starts;
std::vector<ULONG> segment_ends;
const int MAX_SEGMENTS = 16;
COR_PRF_NONGC_HEAP_RANGE nongc_segments[MAX_SEGMENTS];
COR_PRF_GC_GENERATION_RANGE gc_segments[MAX_SEGMENTS];
ULONG segCount;
ObjectID firstObj = 0;
HRESULT hr = pCorProfilerInfo->GetNonGCHeapBounds(MAX_NON_GC_HEAP_SEGMENTS, &segCount, segments);
HRESULT hr = pCorProfilerInfo->GetNonGCHeapBounds(MAX_SEGMENTS, &segCount, nongc_segments);
if (FAILED(hr))
{
printf("GetNonGCHeapBounds returned an error\n!");
_failures++;
}
else if (segCount == 0 || segCount > MAX_NON_GC_HEAP_SEGMENTS)
else if (segCount == 0 || segCount > MAX_SEGMENTS)
{
printf("GetNonGCHeapBounds: invalid segCount (%u)\n!", segCount);
_failures++;
}
else
{
// Save very first object ID to compare with EnumerateNonGCObjects
firstObj = segments[0].rangeStart;
firstObj = nongc_segments[0].rangeStart;

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

if ((ULONG)segments[i].rangeLength > (ULONG)segments[i].rangeLengthReserved)
if ((ULONG)nongc_segments[i].rangeLength > (ULONG)nongc_segments[i].rangeLengthReserved)
{
printf("GetNonGCHeapBounds: rangeLength > rangeLengthReserved");
_failures++;
}

if (!segments[i].rangeStart)
if (!nongc_segments[i].rangeStart)
{
printf("GetNonGCHeapBounds: rangeStart is null");
_failures++;
}
segment_starts.emplace_back((ULONG)nongc_segments[i].rangeStart);
segment_ends.emplace_back((ULONG)nongc_segments[i].rangeStart + (ULONG)nongc_segments[i].rangeLengthReserved);
}
printf("\n");
}
hr = pCorProfilerInfo->GetGenerationBounds(MAX_SEGMENTS, &segCount, gc_segments);
if (FAILED(hr))
{
printf("GetGenerationBounds returned an error\n!");
_failures++;
}
else if (segCount == 0 || segCount > MAX_SEGMENTS)
{
printf("GetGenerationBounds: invalid segCount (%u)\n!", segCount);
_failures++;
}
else
{
printf("\nGetGenerationBounds (segCount = %u):\n", segCount);
for (ULONG i = 0; i < segCount; i++)
{
printf("\tseg#%u, rangeStart=%p, rangeLength=%u, rangeLengthReserved=%u\n",
i, (void*)gc_segments[i].rangeStart, (ULONG)gc_segments[i].rangeLength, (ULONG)gc_segments[i].rangeLengthReserved);

if ((ULONG)gc_segments[i].rangeLength > (ULONG)gc_segments[i].rangeLengthReserved)
{
printf("GetGenerationBounds: rangeLength > rangeLengthReserved");
_failures++;
}

if (!gc_segments[i].rangeStart)
{
printf("GetGenerationBounds: rangeStart is null");
_failures++;
}
segment_starts.emplace_back((ULONG)gc_segments[i].rangeStart);
segment_ends.emplace_back((ULONG)gc_segments[i].rangeStart + (ULONG)gc_segments[i].rangeLengthReserved);
}
printf("\n");
}
sort(segment_starts.begin(), segment_starts.end());
sort(segment_ends.begin(), segment_ends.end());
for (size_t i = 0; i < segment_starts.size() - 1; i++)
{
if (segment_starts[i] == segment_starts[i+1])
{
printf("Duplicated segment starts");
_failures++;
}
if (segment_ends[i] == segment_ends[i+1])
{
printf("Duplicated segment ends");
_failures++;
}
if (segment_ends[i] > segment_starts[i+1])
{
printf("Overlapping segments\n");
_failures++;
}
}

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