[LibraryImport(Libraries.Kernel32)]
[return:MarshalAs(UnmanagedType.Bool)]
internal static partial bool SetThreadPriority(SafeWaitHandle hThread, int nPriority);
+
+ [LibraryImport(Libraries.Kernel32, SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ internal static partial bool GetThreadIOPendingFlag(nint hThread, out BOOL lpIOIsPending);
}
}
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.SystemTimeToFileTime.cs">
<Link>Common\Interop\Windows\Kernel32\Interop.SystemTimeToFileTime.cs</Link>
</Compile>
+ <Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.Threading.cs">
+ <Link>Common\Interop\Windows\Kernel32\Interop.Threading.cs</Link>
+ </Compile>
<Compile Include="$(CommonPath)Interop\Windows\Kernel32\Interop.TimeZone.cs">
<Link>Common\Interop\Windows\Kernel32\Interop.TimeZone.cs</Link>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\PortableThreadPool.WaitThread.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\PortableThreadPool.WorkerThread.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\PortableThreadPool.WorkerTracking.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)System\Threading\PortableThreadPool.CpuUtilizationReader.Unix.cs" Condition="'$(TargetsUnix)' == 'true' or '$(TargetsBrowser)' == 'true' or '$(TargetsWasi)' == 'true'" />
- <Compile Include="$(MSBuildThisFileDirectory)System\Threading\PortableThreadPool.CpuUtilizationReader.Windows.cs" Condition="'$(TargetsWindows)' == 'true'" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\PortableThreadPool.Unix.cs" Condition="'$(TargetsUnix)' == 'true' or '$(TargetsBrowser)' == 'true' or '$(TargetsWasi)' == 'true'" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\PortableThreadPool.Windows.cs" Condition="'$(TargetsWindows)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\LowLevelLifoSemaphore.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\LowLevelLifoSemaphore.Windows.cs" Condition="'$(TargetsWindows)' == 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\PreAllocatedOverlapped.cs" Condition="('$(TargetsBrowser)' != 'true' and '$(TargetsWasi)' != 'true') or '$(FeatureWasmThreads)' == 'true'" />
</ItemGroup>
<ItemGroup Condition="'$(FeatureCoreCLR)' != 'true' and '$(TargetsWindows)' == 'true'">
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\WaitHandle.Windows.cs" />
- <Compile Include="$(CommonPath)\Interop\Windows\Kernel32\Interop.Threading.cs">
- <Link>Interop\Windows\Kernel32\Interop.Threading.cs</Link>
- </Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)System\IParsable.cs" />
{
internal sealed partial class PortableThreadPool
{
+ private static partial class WorkerThread
+ {
+ private static bool IsIOPending
+ {
+ get
+ {
+ bool success =
+ Interop.Kernel32.GetThreadIOPendingFlag(Interop.Kernel32.GetCurrentThread(), out Interop.BOOL isIOPending);
+ Debug.Assert(success);
+ return !success || isIOPending != Interop.BOOL.FALSE;
+ }
+ }
+ }
+
private struct CpuUtilizationReader
{
public long _idleTime;
/// <summary>
/// The worker thread infastructure for the CLR thread pool.
/// </summary>
- private static class WorkerThread
+ private static partial class WorkerThread
{
private const int SemaphoreSpinCountDefaultBaseline = 70;
#if !TARGET_ARM64 && !TARGET_ARM && !TARGET_LOONGARCH64
}
}
+ // The thread cannot exit if it has IO pending, otherwise the IO may be canceled
+ if (IsIOPending)
+ {
+ continue;
+ }
+
threadAdjustmentLock.Acquire();
try
{