Skip to content

Commit

Permalink
Stop counting work items from ThreadPoolTypedWorkItemQueue for Thread…
Browse files Browse the repository at this point in the history
…Pool.CompletedWorkItemCount (dotnet#106854)

* Stop counting work items from ThreadPoolTypedWorkItemQueue as completed work items

* Fix CompletedWorkItemCount

* Update src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs

Co-authored-by: Koundinya Veluri <kouvel@users.noreply.github.com>

* Run CompletedWorkItemCountTest on Windows only

---------

Co-authored-by: Eduardo Manuel Velarde Polar <evelardepola@microsoft.com>
Co-authored-by: Koundinya Veluri <kouvel@users.noreply.github.com>
  • Loading branch information
3 people authored and jtschuster committed Sep 17, 2024
1 parent 4196cd2 commit 3e7c20f
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -1393,7 +1393,11 @@ void IThreadPoolWorkItem.Execute()
currentThread.ResetThreadPoolThread();
}

ThreadInt64PersistentCounter.Add(tl.threadLocalCompletionCountObject!, completedCount);
// Discount a work item here to avoid counting most of the queue processing work items
if (completedCount > 1)
{
ThreadInt64PersistentCounter.Add(tl.threadLocalCompletionCountObject!, completedCount - 1);
}
}
}

Expand Down
27 changes: 27 additions & 0 deletions src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1440,6 +1440,33 @@ static async Task RunAsyncIOTest()
}, ioCompletionPortCount.ToString()).Dispose();
}


[ConditionalFact(nameof(IsThreadingAndRemoteExecutorSupported))]
[PlatformSpecific(TestPlatforms.Windows)]
public static unsafe void ThreadPoolCompletedWorkItemCountTest()
{
// Run in a separate process to test in a clean thread pool environment such that we don't count external work items
RemoteExecutor.Invoke(() =>
{
using var manualResetEvent = new ManualResetEventSlim(false);
var overlapped = new Overlapped();
NativeOverlapped* nativeOverlapped = overlapped.Pack((errorCode, numBytes, innerNativeOverlapped) =>
{
Overlapped.Free(innerNativeOverlapped);
manualResetEvent.Set();
}, null);
ThreadPool.UnsafeQueueNativeOverlapped(nativeOverlapped);
manualResetEvent.Wait();
// Allow work item(s) to be marked as completed during this time, should be only one
ThreadTestHelpers.WaitForCondition(() => ThreadPool.CompletedWorkItemCount == 1);
Thread.Sleep(50);
Assert.Equal(1, ThreadPool.CompletedWorkItemCount);
}).Dispose();
}

public static bool IsThreadingAndRemoteExecutorSupported =>
PlatformDetection.IsThreadingSupported && RemoteExecutor.IsSupported;

Expand Down

0 comments on commit 3e7c20f

Please sign in to comment.