Skip to content

Commit fd7a650

Browse files
committed
disable priority boost
1 parent 2a6b71c commit fd7a650

2 files changed

Lines changed: 39 additions & 12 deletions

File tree

src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Threading.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ internal static unsafe partial SafeWaitHandle CreateThread(
4242
[LibraryImport(Libraries.Kernel32)]
4343
internal static partial IntPtr GetCurrentThread();
4444

45+
[LibraryImport(Libraries.Kernel32, SetLastError = true)]
46+
[return: MarshalAs(UnmanagedType.Bool)]
47+
internal static partial bool SetThreadPriorityBoost(IntPtr hThread, [MarshalAs(UnmanagedType.Bool)] bool bDisablePriorityBoost);
48+
4549
internal const int DUPLICATE_SAME_ACCESS = 2;
4650

4751
[LibraryImport(Libraries.Kernel32, SetLastError = true)]

src/libraries/System.Private.CoreLib/src/System/Threading/LowLevelLifoSemaphore.cs

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,9 @@ private void MaybeWakeWaiterSlow(Counts counts)
198198

199199
private bool WaitAsWaiter(int timeoutMs)
200200
{
201-
Debug.Assert(timeoutMs == -1 || timeoutMs > 0);
201+
Debug.Assert(timeoutMs > 0 || timeoutMs == -1);
202+
203+
_onWait();
202204

203205
while (true)
204206
{
@@ -317,20 +319,41 @@ private bool Block(int timeoutMs)
317319

318320
if (blocker != null)
319321
{
320-
_onWait();
321-
while (!blocker.TimedWait(timeoutMs))
322+
if (OperatingSystem.IsWindows())
322323
{
323-
if (TryRemove(blocker))
324+
// Disable the priority boost that Windows would normally apply
325+
// when this thread is unblocked. The semaphore is used to park
326+
// thread-pool workers; a transient priority boost on wake provides
327+
// no benefit here and can disturb scheduling of other work.
328+
// GetCurrentThread() returns a pseudo-handle (-2) that is valid
329+
// only on the calling thread and does not need to be closed.
330+
Interop.Kernel32.SetThreadPriorityBoost(Interop.Kernel32.GetCurrentThread(), bDisablePriorityBoost: true);
331+
}
332+
333+
try
334+
{
335+
while (!blocker.TimedWait(timeoutMs))
324336
{
325-
return false;
326-
}
337+
if (TryRemove(blocker))
338+
{
339+
return false;
340+
}
327341

328-
// We timed out, but our waiter is already popped. Someone is waking
329-
// our blocker. This is a very rare case.
330-
// We can't leave or the wake could be lost, so let's wait again.
331-
// The blocker is likely woken already, but give it some extra time,
332-
// just so we do not keep coming here again.
333-
timeoutMs = 10;
342+
// We timed out, but our waiter is already popped. Someone is waking
343+
// our blocker. This is a very rare case.
344+
// We can't leave or the wake could be lost, so let's wait again.
345+
// The blocker is likely woken already, but give it some extra time,
346+
// just so we do not keep coming here again.
347+
timeoutMs = 10;
348+
}
349+
}
350+
finally
351+
{
352+
if (OperatingSystem.IsWindows())
353+
{
354+
// restore the default.
355+
Interop.Kernel32.SetThreadPriorityBoost(Interop.Kernel32.GetCurrentThread(), bDisablePriorityBoost: false);
356+
}
334357
}
335358
}
336359

0 commit comments

Comments
 (0)