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

Enable IOPack, IOEnqueue, and IODequeue on Windows #88894

Merged
merged 22 commits into from
Aug 9, 2023
Merged
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a8ed540
Testing IOPack
eduardo-vp Jul 13, 2023
8153deb
Add IOEnqueue event
eduardo-vp Jul 14, 2023
ed000ad
Add IODequeue event in NativeOverlappedCallback for Windows Threadpool
eduardo-vp Jul 24, 2023
d3ed46e
Search for ThreadPoolIOPack event
eduardo-vp Jul 25, 2023
bd58b31
Add EventPipeEventThreadPoolIOPack initialization
eduardo-vp Aug 1, 2023
4ae8996
Use EventLevel.Verbose, test fixed
eduardo-vp Aug 1, 2023
9cdf4a5
Add test to NativeAot CI runs + Evaluate WorkerThread events only in …
eduardo-vp Aug 2, 2023
70032d9
Fixed typo in runtime.yml
eduardo-vp Aug 2, 2023
1aee4f9
Fix test
eduardo-vp Aug 3, 2023
0fda41d
Nit: Comment removed
eduardo-vp Aug 3, 2023
951be33
Merge branch 'main' into feature/add-threadpool-events
eduardo-vp Aug 3, 2023
4d13acc
Test IOPack, IOEnqueue and IODequeue
eduardo-vp Aug 3, 2023
37cdadf
Nit: Fixed variable name
eduardo-vp Aug 3, 2023
cb86c96
Used a separate ManualResetEvent
eduardo-vp Aug 3, 2023
432136a
Used different ManualResetEvent for each IOEvent
eduardo-vp Aug 3, 2023
4d86a5e
Update test, test UnsafeQueueNativeOverlapped in Windows only
eduardo-vp Aug 4, 2023
8fb1008
Added events in RegisterWaitHandle and real async IO for Windows thre…
eduardo-vp Aug 5, 2023
2e94127
Test fixed. Still missing why the first part doesn't work on NativeAot
eduardo-vp Aug 5, 2023
e12ce91
PR comments
eduardo-vp Aug 8, 2023
07dd9ee
Merge branch 'main' into feature/add-threadpool-events
eduardo-vp Aug 8, 2023
84de91a
Fire IODequeue before CompleteWithCallback in OnNativeIOCompleted
eduardo-vp Aug 8, 2023
995f189
Fixed comment
eduardo-vp Aug 8, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 53 additions & 38 deletions src/tests/tracing/eventlistener/EventListenerThreadPool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ internal sealed class RuntimeEventListener : EventListener
public volatile int TPIOEnqueue = 0;
public volatile int TPIODequeue = 0;

public int TPIOPackGoal = 0;
public int TPIOEnqueueGoal = 1;
public int TPIODequeueGoal = 1;

public ManualResetEvent TPWaitWorkerThreadEvent = new ManualResetEvent(false);
public ManualResetEvent TPWaitIOPackEvent = new ManualResetEvent(false);
public ManualResetEvent TPWaitIOEnqueueEvent = new ManualResetEvent(false);
Expand Down Expand Up @@ -50,17 +54,20 @@ protected override void OnEventWritten(EventWrittenEventArgs eventData)
else if (eventData.EventName.Equals("ThreadPoolIOPack"))
{
Interlocked.Increment(ref TPIOPack);
TPWaitIOPackEvent.Set();
if (TPIOPack == TPIOPackGoal)
TPWaitIOPackEvent.Set();
}
else if (eventData.EventName.Equals("ThreadPoolIOEnqueue"))
{
Interlocked.Increment(ref TPIOEnqueue);
TPWaitIOEnqueueEvent.Set();
if (TPIOEnqueue == TPIOEnqueueGoal)
TPWaitIOEnqueueEvent.Set();
}
else if (eventData.EventName.Equals("ThreadPoolIODequeue"))
{
Interlocked.Increment(ref TPIODequeue);
TPWaitIODequeueEvent.Set();
if (TPIODequeue == TPIODequeueGoal)
TPWaitIODequeueEvent.Set();
}
}
}
Expand All @@ -71,24 +78,47 @@ static int Main()
{
using (RuntimeEventListener listener = new RuntimeEventListener())
{
// This should fire either of TPWorkerThreadStartCount, TPWorkerThreadStopCount or TPWorkerThreadWaitCount
int someNumber = 0;
Task[] tasks = new Task[100];
for (int i = 0; i < tasks.Length; i++)
{
tasks[i] = Task.Run(() => { someNumber += 1; });
}

// Test this part in CoreCLR only
if (!TestLibrary.Utilities.IsNativeAot)
if (TestLibrary.Utilities.IsWindows)
{
int someNumber = 0;
Task[] tasks = new Task[100];
for (int i = 0; i < tasks.Length; i++)
// This part is Windows-specific, it should fire an IOPack, IOEnqueue and IODequeue event
listener.TPIOPackGoal += 1;
listener.TPIOEnqueueGoal += 1;
listener.TPIODequeueGoal += 1;

Overlapped overlapped = new Overlapped();
unsafe
{
tasks[i] = Task.Run(() => { someNumber += 1; });
NativeOverlapped* nativeOverlapped = overlapped.Pack(null);
ThreadPool.UnsafeQueueNativeOverlapped(nativeOverlapped);
}
}

// RegisterWaitForSingleObject should fire an IOEnqueue and IODequeue event
ManualResetEvent manualResetEvent = new ManualResetEvent(false);
WaitOrTimerCallback work = (x, timedOut) => { int y = (int)x; };
ThreadPool.RegisterWaitForSingleObject(manualResetEvent, work, 1, 100, true);
manualResetEvent.Set();

listener.TPWaitWorkerThreadEvent.WaitOne(TimeSpan.FromMinutes(3));
ManualResetEvent[] waitEvents = new ManualResetEvent[] {listener.TPWaitIOPackEvent,
listener.TPWaitIOEnqueueEvent,
listener.TPWaitIODequeueEvent};

bool workerThreadEventsOk = listener.TPWorkerThreadStartCount > 0 ||
listener.TPWorkerThreadStopCount > 0 ||
listener.TPWorkerThreadWaitCount > 0;
WaitHandle.WaitAll(waitEvents, TimeSpan.FromMinutes(1));

if (!workerThreadEventsOk)
if (!TestLibrary.Utilities.IsNativeAot) // This test works in CoreCLR only, don't know why yet
eduardo-vp marked this conversation as resolved.
Show resolved Hide resolved
{
listener.TPWaitWorkerThreadEvent.WaitOne(TimeSpan.FromMinutes(1));
if (listener.TPWorkerThreadStartCount == 0 &&
listener.TPWorkerThreadStopCount == 0 &&
listener.TPWorkerThreadWaitCount == 0)
eduardo-vp marked this conversation as resolved.
Show resolved Hide resolved
{
Console.WriteLine("Test Failed: Did not see any of the expected events.");
Console.WriteLine($"ThreadPoolWorkerThreadStartCount: {listener.TPWorkerThreadStartCount}");
Expand All @@ -98,32 +128,17 @@ static int Main()
}
}

// Test this part in Windows only
if (TestLibrary.Utilities.IsWindows)
if (listener.TPIOPack != listener.TPIOPackGoal &&
listener.TPIOEnqueue != listener.TPIOEnqueueGoal &&
listener.TPIODequeue != listener.TPIODequeueGoal)
eduardo-vp marked this conversation as resolved.
Show resolved Hide resolved
{
Overlapped overlapped = new Overlapped();

unsafe
{
NativeOverlapped* nativeOverlapped = overlapped.Pack(null);
ThreadPool.UnsafeQueueNativeOverlapped(nativeOverlapped);
}

ManualResetEvent[] ioWaitEvents = new ManualResetEvent[] {listener.TPWaitIOPackEvent, listener.TPWaitIOEnqueueEvent, listener.TPWaitIODequeueEvent};

WaitHandle.WaitAll(ioWaitEvents, TimeSpan.FromMinutes(3));

if (!(listener.TPIOPack > 0 && listener.TPIOEnqueue > 0 && listener.TPIODequeue > 0))
{
Console.WriteLine("Test Failed: Did not see all of the expected events.");
Console.WriteLine($"ThreadPoolIOPack: {listener.TPIOPack}");
Console.WriteLine($"ThreadPoolIOEnqueue: {listener.TPIOEnqueue}");
Console.WriteLine($"ThreadPoolIODequeue: {listener.TPIODequeue}");
return -1;
}
Console.WriteLine("Test Failed: Did not see all of the expected events.");
Console.WriteLine($"ThreadPoolIOPack: {listener.TPIOPack}");
Console.WriteLine($"ThreadPoolIOEnqueue: {listener.TPIOEnqueue}");
Console.WriteLine($"ThreadPoolIODequeue: {listener.TPIODequeue}");
return -1;
}



Console.WriteLine("Test Passed.");
return 100;
}
Expand Down