From f832f36101a3c488a0d2e56832d33deee9109d1f Mon Sep 17 00:00:00 2001 From: Eduardo Manuel Velarde Polar Date: Thu, 22 Aug 2024 20:13:51 -0700 Subject: [PATCH 1/4] Stop counting work items from ThreadPoolTypedWorkItemQueue as completed work items --- .../System/Threading/ThreadPoolWorkQueue.cs | 2 -- .../tests/ThreadPoolTests.cs | 26 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs index bc0fe4556bb31..7a9db16ffe2d7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs @@ -1392,8 +1392,6 @@ void IThreadPoolWorkItem.Execute() // Reset thread state after all user code for the work item has completed currentThread.ResetThreadPoolThread(); } - - ThreadInt64PersistentCounter.Add(tl.threadLocalCompletionCountObject!, completedCount); } } diff --git a/src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs b/src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs index 7c3c215c5ee6c..023b676006ac4 100644 --- a/src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs +++ b/src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs @@ -1439,6 +1439,32 @@ static async Task RunAsyncIOTest() }, ioCompletionPortCount.ToString()).Dispose(); } + + [ConditionalFact(nameof(IsThreadingAndRemoteExecutorSupported))] + 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 + Thread.Sleep(1000); + + Assert.Equal(1, ThreadPool.CompletedWorkItemCount); + }).Dispose(); + } + public static bool IsThreadingAndRemoteExecutorSupported => PlatformDetection.IsThreadingSupported && RemoteExecutor.IsSupported; From ea83aeb5d6b4ade66ca23f1aeaa897f9117e2c56 Mon Sep 17 00:00:00 2001 From: Eduardo Manuel Velarde Polar Date: Fri, 23 Aug 2024 15:15:16 -0700 Subject: [PATCH 2/4] Fix CompletedWorkItemCount --- .../src/System/Threading/ThreadPoolWorkQueue.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs index 7a9db16ffe2d7..89dac7492578f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs @@ -1392,6 +1392,12 @@ void IThreadPoolWorkItem.Execute() // Reset thread state after all user code for the work item has completed currentThread.ResetThreadPoolThread(); } + + // Discount a work item here to avoid counting most of the queue processing work items + if (completedCount > 1) + { + ThreadInt64PersistentCounter.Add(tl.threadLocalCompletionCountObject!, completedCount - 1); + } } } From 55620e305aed2fbec3905562439f2948b7d64bd9 Mon Sep 17 00:00:00 2001 From: Eduardo Velarde <32459232+eduardo-vp@users.noreply.github.com> Date: Fri, 23 Aug 2024 15:15:38 -0700 Subject: [PATCH 3/4] Update src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs Co-authored-by: Koundinya Veluri --- .../System.Threading.ThreadPool/tests/ThreadPoolTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs b/src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs index 023b676006ac4..22f16165f8dcf 100644 --- a/src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs +++ b/src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs @@ -1459,8 +1459,8 @@ public static unsafe void ThreadPoolCompletedWorkItemCountTest() manualResetEvent.Wait(); // Allow work item(s) to be marked as completed during this time, should be only one - Thread.Sleep(1000); - + ThreadTestHelpers.WaitForCondition(() => ThreadPool.CompletedWorkItemCount == 1); + Thread.Sleep(50); Assert.Equal(1, ThreadPool.CompletedWorkItemCount); }).Dispose(); } From 3662053334ee15a7738b6a4e3ff5f3e98a6b8af6 Mon Sep 17 00:00:00 2001 From: Eduardo Manuel Velarde Polar Date: Mon, 26 Aug 2024 10:15:04 -0700 Subject: [PATCH 4/4] Run CompletedWorkItemCountTest on Windows only --- .../System.Threading.ThreadPool/tests/ThreadPoolTests.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs b/src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs index 22f16165f8dcf..e8f9460e7f7a9 100644 --- a/src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs +++ b/src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs @@ -1441,6 +1441,7 @@ static async Task RunAsyncIOTest() [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