mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-09 17:44:48 +09:00
Fix race condition in nongcheap.cpp test (#105658)
This commit is contained in:
parent
bcbca94ce9
commit
7f10eeada7
3 changed files with 56 additions and 14 deletions
|
@ -141,20 +141,22 @@ namespace Profiler.Tests
|
|||
return 100;
|
||||
}
|
||||
|
||||
public const string ProfilerName = "Profiler";
|
||||
|
||||
public static string GetProfilerPath()
|
||||
{
|
||||
string profilerName;
|
||||
if (TestLibrary.Utilities.IsWindows)
|
||||
{
|
||||
profilerName = "Profiler.dll";
|
||||
profilerName = $"{ProfilerName}.dll";
|
||||
}
|
||||
else if (TestLibrary.Utilities.IsLinux)
|
||||
{
|
||||
profilerName = "libProfiler.so";
|
||||
profilerName = $"lib{ProfilerName}.so";
|
||||
}
|
||||
else
|
||||
{
|
||||
profilerName = "libProfiler.dylib";
|
||||
profilerName = $"lib{ProfilerName}.dylib";
|
||||
}
|
||||
|
||||
string profilerPath = Path.Combine(Environment.CurrentDirectory, profilerName);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace Profiler.Tests
|
||||
|
@ -26,16 +27,28 @@ namespace Profiler.Tests
|
|||
int gen = GC.GetGeneration("string7");
|
||||
if (gen != int.MaxValue)
|
||||
throw new Exception("object is expected to be in a non-gc heap for this test to work");
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
private static void InvokeGc()
|
||||
{
|
||||
// Notify the profiler that we're done with the allocations
|
||||
// It's a sort of workaround for possible race conditions between
|
||||
// GarbageCollectionFinished and ObjectAllocated
|
||||
NotifyNongcAllocationsFinished();
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||
static void Consume(object o) {}
|
||||
static void Consume(object o) { }
|
||||
|
||||
public static int RunTest(String[] args)
|
||||
[DllImport(ProfilerTestRunner.ProfilerName)]
|
||||
private static extern void NotifyNongcAllocationsFinished();
|
||||
|
||||
public static int RunTest(String[] args)
|
||||
{
|
||||
AllocateNonGcHeapObjects();
|
||||
InvokeGc();
|
||||
Console.WriteLine("Test Passed");
|
||||
return 100;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,12 @@
|
|||
#include "nongcheap.h"
|
||||
#include <vector>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define DLLEXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define DLLEXPORT __attribute__((visibility("default")))
|
||||
#endif // _MSC_VER
|
||||
|
||||
GUID NonGcHeapProfiler::GetClsid()
|
||||
{
|
||||
// {EF0D191C-3FC7-4311-88AF-E474CBEB2859}
|
||||
|
@ -11,8 +17,17 @@ GUID NonGcHeapProfiler::GetClsid()
|
|||
return clsid;
|
||||
}
|
||||
|
||||
std::atomic<bool> _allocationsFinished;
|
||||
|
||||
extern "C" DLLEXPORT void NotifyNongcAllocationsFinished()
|
||||
{
|
||||
printf("NotifyNongcAllocationsFinished is invoked.\n");
|
||||
_allocationsFinished = true;
|
||||
}
|
||||
|
||||
HRESULT NonGcHeapProfiler::Initialize(IUnknown* pICorProfilerInfoUnk)
|
||||
{
|
||||
_allocationsFinished = false;
|
||||
Profiler::Initialize(pICorProfilerInfoUnk);
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
|
@ -20,7 +35,7 @@ HRESULT NonGcHeapProfiler::Initialize(IUnknown* pICorProfilerInfoUnk)
|
|||
COR_PRF_ENABLE_OBJECT_ALLOCATED | COR_PRF_MONITOR_OBJECT_ALLOCATED,
|
||||
COR_PRF_HIGH_BASIC_GC)))
|
||||
{
|
||||
printf("FAIL: ICorProfilerInfo::SetEventMask2() failed hr=0x%x", hr);
|
||||
printf("FAIL: ICorProfilerInfo::SetEventMask2() failed hr=0x%x\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
@ -41,16 +56,22 @@ HRESULT STDMETHODCALLTYPE NonGcHeapProfiler::ObjectAllocated(ObjectID objectId,
|
|||
{
|
||||
// We expect GetObjectGeneration to return an error (CORPROF_E_NOT_GC_OBJECT)
|
||||
// for non-GC objects.
|
||||
printf("FAIL: GetObjectGeneration failed for nongc object: hr=0x%x\n", hr);
|
||||
_failures++;
|
||||
}
|
||||
_nonGcHeapObjects++;
|
||||
|
||||
if (gen.rangeLength != 0 || gen.rangeLengthReserved != 0 || gen.rangeStart != 0)
|
||||
{
|
||||
printf("FAIL: GetObjectGeneration returned unexpected values: rangeLength=%u, rangeLengthReserved=%u, rangeStart=%p\n",
|
||||
(uint32_t)gen.rangeLength, (uint32_t)gen.rangeLengthReserved, (void*)gen.rangeStart);
|
||||
_failures++;
|
||||
}
|
||||
|
||||
_nonGcHeapObjects++;
|
||||
}
|
||||
else if (FAILED(hr))
|
||||
{
|
||||
printf("FAIL: GetObjectGeneration failed: hr=0x%x\n", hr);
|
||||
_failures++;
|
||||
}
|
||||
return S_OK;
|
||||
|
@ -60,6 +81,12 @@ HRESULT NonGcHeapProfiler::GarbageCollectionFinished()
|
|||
{
|
||||
SHUTDOWNGUARD();
|
||||
|
||||
if (!_allocationsFinished)
|
||||
{
|
||||
printf("Ignoring this GarbageCollectionFinished: NotifyNongcAllocationsFinished has not been invoked yet.\n");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
_garbageCollections++;
|
||||
|
||||
std::vector<uint64_t> segment_starts;
|
||||
|
@ -93,13 +120,13 @@ HRESULT NonGcHeapProfiler::GarbageCollectionFinished()
|
|||
|
||||
if (nongc_segments[i].rangeLength > nongc_segments[i].rangeLengthReserved)
|
||||
{
|
||||
printf("FAIL: GetNonGCHeapBounds: rangeLength > rangeLengthReserved");
|
||||
printf("FAIL: GetNonGCHeapBounds: rangeLength > rangeLengthReserved\n");
|
||||
_failures++;
|
||||
}
|
||||
|
||||
if (!nongc_segments[i].rangeStart)
|
||||
{
|
||||
printf("FAIL: GetNonGCHeapBounds: rangeStart is null");
|
||||
printf("FAIL: GetNonGCHeapBounds: rangeStart is null\n");
|
||||
_failures++;
|
||||
}
|
||||
segment_starts.push_back(nongc_segments[i].rangeStart);
|
||||
|
@ -128,13 +155,13 @@ HRESULT NonGcHeapProfiler::GarbageCollectionFinished()
|
|||
|
||||
if (gc_segments[i].rangeLength > gc_segments[i].rangeLengthReserved)
|
||||
{
|
||||
printf("FAIL: GetGenerationBounds: rangeLength > rangeLengthReserved");
|
||||
printf("FAIL: GetGenerationBounds: rangeLength > rangeLengthReserved\n");
|
||||
_failures++;
|
||||
}
|
||||
|
||||
if (!gc_segments[i].rangeStart)
|
||||
{
|
||||
printf("FAIL: GetGenerationBounds: rangeStart is null");
|
||||
printf("FAIL: GetGenerationBounds: rangeStart is null\n");
|
||||
_failures++;
|
||||
}
|
||||
segment_starts.push_back(gc_segments[i].rangeStart);
|
||||
|
@ -154,12 +181,12 @@ HRESULT NonGcHeapProfiler::GarbageCollectionFinished()
|
|||
|
||||
if (segment_starts[i] == segment_starts[i+1])
|
||||
{
|
||||
printf("FAIL: Duplicated segment starts");
|
||||
printf("FAIL: Duplicated segment starts\n");
|
||||
_failures++;
|
||||
}
|
||||
if (segment_ends[i] == segment_ends[i+1])
|
||||
{
|
||||
printf("FAIL: Duplicated segment ends");
|
||||
printf("FAIL: Duplicated segment ends\n");
|
||||
_failures++;
|
||||
}
|
||||
if (segment_ends[i] > segment_starts[i+1])
|
||||
|
@ -211,7 +238,7 @@ HRESULT NonGcHeapProfiler::GarbageCollectionFinished()
|
|||
|
||||
if (nonGcObjectsEnumerated != _nonGcHeapObjects)
|
||||
{
|
||||
printf("FAIL: objectAllocated(%d) != _nonGcHeapObjects(%d)\n!", nonGcObjectsEnumerated, (int)_nonGcHeapObjects);
|
||||
printf("FAIL: nonGcObjectsEnumerated(%d) != _nonGcHeapObjects(%d)\n!", nonGcObjectsEnumerated, (int)_nonGcHeapObjects);
|
||||
_failures++;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue