From d55c82e554102847d9132563455d2d67abd53202 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 6 Jun 2026 21:00:56 +0000 Subject: [PATCH 1/2] Initial plan From fa0dbc299c33d52977d14ed430f3504014c216dc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 6 Jun 2026 21:33:22 +0000 Subject: [PATCH 2/2] Remove prioritized wait plumbing from Unix WaitSubsystem Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com> --- .../src/System/Threading/NamedMutex.Unix.cs | 2 +- .../WaitSubsystem.HandleManager.Unix.cs | 6 +-- .../WaitSubsystem.ThreadWaitInfo.Unix.cs | 41 ++----------------- .../System/Threading/WaitSubsystem.Unix.cs | 21 ++++------ .../WaitSubsystem.WaitableObject.Unix.cs | 9 ++-- 5 files changed, 21 insertions(+), 58 deletions(-) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/NamedMutex.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/NamedMutex.Unix.cs index f1086e17582688..077f68c63b23e2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/NamedMutex.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/NamedMutex.Unix.cs @@ -647,7 +647,7 @@ public NamedMutex(SharedMemoryProcessDataHeader proce _processDataHeader = processDataHeader; } - public int Wait_Locked(ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible, bool prioritize, ref LockHolder lockHolder) + public int Wait_Locked(ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible, ref LockHolder lockHolder) { lockHolder.Dispose(); LockHolder scope = SharedMemoryManager.Instance.AcquireCreationDeletionProcessLock(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.HandleManager.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.HandleManager.Unix.cs index 6bc31a9e1ec931..1f95eb293c42ec 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.HandleManager.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.HandleManager.Unix.cs @@ -13,11 +13,11 @@ internal static partial class WaitSubsystem public interface IWaitableObject { void OnDeleteHandle(); - int Wait_Locked(ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible, bool prioritize, ref LockHolder lockHolder); + int Wait_Locked(ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible, ref LockHolder lockHolder); void Signal(int count, ref LockHolder lockHolder); } - public static int Wait(this IWaitableObject waitable, ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible, bool prioritize) + public static int Wait(this IWaitableObject waitable, ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible) { Debug.Assert(waitInfo.Thread == Thread.CurrentThread); @@ -32,7 +32,7 @@ public static int Wait(this IWaitableObject waitable, ThreadWaitInfo waitInfo, i throw new ThreadInterruptedException(); } - return waitable.Wait_Locked(waitInfo, timeoutMilliseconds, interruptible, prioritize, ref lockHolder); + return waitable.Wait_Locked(waitInfo, timeoutMilliseconds, interruptible, ref lockHolder); } finally { diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.ThreadWaitInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.ThreadWaitInfo.Unix.cs index 7d169c9a6404f5..0f4ea01afb95a7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.ThreadWaitInfo.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.ThreadWaitInfo.Unix.cs @@ -127,7 +127,7 @@ private bool IsWaiting } /// - /// Callers must ensure to clear the array after use. Once is called (followed + /// Callers must ensure to clear the array after use. Once is called (followed /// by a call to , the array will be cleared automatically. /// public WaitableObject?[] GetWaitedObjectArray(int requiredCapacity) @@ -174,7 +174,7 @@ private WaitedListNode[] GetWaitedListNodeArray(int requiredCapacity) /// /// The caller is expected to populate and pass in the number of objects filled /// - public void RegisterWait(int waitedCount, bool prioritize, bool isWaitForAll) + public void RegisterWait(int waitedCount, bool isWaitForAll) { s_lock.VerifyIsLocked(); Debug.Assert(_thread == Thread.CurrentThread); @@ -218,19 +218,9 @@ public void RegisterWait(int waitedCount, bool prioritize, bool isWaitForAll) _isWaitForAll = isWaitForAll; _waitedCount = waitedCount; - if (prioritize) - { - for (int i = 0; i < waitedCount; ++i) - { - waitedListNodes[i].RegisterPrioritizedWait(waitedObjects[i]!); - } - } - else + for (int i = 0; i < waitedCount; ++i) { - for (int i = 0; i < waitedCount; ++i) - { - waitedListNodes[i].RegisterWait(waitedObjects[i]!); - } + waitedListNodes[i].RegisterWait(waitedObjects[i]!); } } @@ -712,29 +702,6 @@ public void RegisterWait(WaitableObject waitableObject) waitableObject.WaitersTail = this; } - public void RegisterPrioritizedWait(WaitableObject waitableObject) - { - s_lock.VerifyIsLocked(); - Debug.Assert(_waitInfo.Thread == Thread.CurrentThread); - - Debug.Assert(waitableObject != null); - - Debug.Assert(_previous == null); - Debug.Assert(_next == null); - - WaitedListNode? head = waitableObject.WaitersHead; - if (head != null) - { - _next = head; - head._previous = this; - } - else - { - waitableObject.WaitersTail = this; - } - waitableObject.WaitersHead = this; - } - public void UnregisterWait(WaitableObject waitableObject) { s_lock.VerifyIsLocked(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.Unix.cs index cad35f0dc4d378..5232c73bd31bc5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.Unix.cs @@ -189,7 +189,7 @@ public static SafeWaitHandle NewMutex(bool initiallyOwned) // by the thread. See . So, acquire the lock only after all // possibilities for exceptions have been exhausted. ThreadWaitInfo waitInfo = Thread.CurrentThread.WaitInfo; - bool acquiredLock = waitableObject.Wait(waitInfo, timeoutMilliseconds: 0, interruptible: false, prioritize: false) == 0; + bool acquiredLock = waitableObject.Wait(waitInfo, timeoutMilliseconds: 0, interruptible: false) == 0; Debug.Assert(acquiredLock); return safeWaitHandle; } @@ -242,7 +242,7 @@ public static OpenExistingResult OpenNamedMutex(string name, bool isUserScope, o // by the thread. See . So, acquire the lock only after all // possibilities for exceptions have been exhausted. ThreadWaitInfo waitInfo = Thread.CurrentThread.WaitInfo; - int status = waitableObject.Wait_Locked(waitInfo, timeoutMilliseconds: 0, interruptible: false, prioritize: false, ref lockHolder); + int status = waitableObject.Wait_Locked(waitInfo, timeoutMilliseconds: 0, interruptible: false, ref lockHolder); Debug.Assert(status == 0); return safeWaitHandle; } @@ -361,13 +361,12 @@ public static int Wait(IntPtr handle, int timeoutMilliseconds, bool interruptibl public static int Wait( IWaitableObject waitableObject, int timeoutMilliseconds, - bool interruptible = true, - bool prioritize = false) + bool interruptible = true) { Debug.Assert(waitableObject != null); Debug.Assert(timeoutMilliseconds >= -1); - return waitableObject.Wait(Thread.CurrentThread.WaitInfo, timeoutMilliseconds, interruptible, prioritize); + return waitableObject.Wait(Thread.CurrentThread.WaitInfo, timeoutMilliseconds, interruptible); } public static int Wait( @@ -385,7 +384,7 @@ public static int Wait( if (waitHandles.Length == 1 && HandleManager.FromHandle(waitHandles[0]) is NamedMutex namedMutex) { // Named mutexes don't participate in the wait subsystem fully. - return namedMutex.Wait(waitInfo, timeoutMilliseconds, interruptible: true, prioritize: false); + return namedMutex.Wait(waitInfo, timeoutMilliseconds, interruptible: true); } #endif @@ -439,7 +438,7 @@ public static int Wait( WaitableObject waitableObject = waitableObjects[0]!; waitableObjects[0] = null; return - waitableObject.Wait(waitInfo, timeoutMilliseconds, interruptible: true, prioritize: false); + waitableObject.Wait(waitInfo, timeoutMilliseconds, interruptible: true); } return @@ -449,8 +448,7 @@ public static int Wait( waitForAll, waitInfo, timeoutMilliseconds, - interruptible: true, - prioritize: false); + interruptible: true); } public static int SignalAndWait( @@ -471,8 +469,7 @@ public static int SignalAndWait( IWaitableObject waitableObjectToSignal, IWaitableObject waitableObjectToWaitOn, int timeoutMilliseconds, - bool interruptible = true, - bool prioritize = false) + bool interruptible = true) { Debug.Assert(waitableObjectToSignal != null); Debug.Assert(waitableObjectToWaitOn != null); @@ -498,7 +495,7 @@ public static int SignalAndWait( s_lock.VerifyIsNotLocked(); throw new InvalidOperationException(SR.Threading_WaitHandleTooManyPosts, ex); } - return waitableObjectToWaitOn.Wait_Locked(waitInfo, timeoutMilliseconds, interruptible, prioritize, ref lockHolder); + return waitableObjectToWaitOn.Wait_Locked(waitInfo, timeoutMilliseconds, interruptible, ref lockHolder); } finally { diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.WaitableObject.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.WaitableObject.Unix.cs index 7f892a32a7e646..b1911b61a4d457 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.WaitableObject.Unix.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitSubsystem.WaitableObject.Unix.cs @@ -305,7 +305,7 @@ private void AcceptSignal(ThreadWaitInfo waitInfo) /// This function does not check for a pending thread interrupt. Callers are expected to do that soon after /// acquiring . /// - public int Wait_Locked(ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible, bool prioritize, ref LockHolder lockHolder) + public int Wait_Locked(ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible, ref LockHolder lockHolder) { s_lock.VerifyIsLocked(); Debug.Assert(waitInfo != null); @@ -339,7 +339,7 @@ public int Wait_Locked(ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool in WaitableObject?[] waitableObjects = waitInfo.GetWaitedObjectArray(1); waitableObjects[0] = this; - waitInfo.RegisterWait(1, prioritize, isWaitForAll: false); + waitInfo.RegisterWait(1, isWaitForAll: false); return waitInfo.Wait( @@ -355,8 +355,7 @@ public static int Wait( bool waitForAll, ThreadWaitInfo waitInfo, int timeoutMilliseconds, - bool interruptible, - bool prioritize) + bool interruptible) { s_lock.VerifyIsNotLocked(); Debug.Assert(waitInfo != null); @@ -481,7 +480,7 @@ public static int Wait( waitableObjects = null; // no need to clear this anymore, RegisterWait / Wait will take over from here - waitInfo.RegisterWait(count, prioritize, waitForAll); + waitInfo.RegisterWait(count, waitForAll); return waitInfo.Wait(timeoutMilliseconds, interruptible, isSleep: false, ref lockHolder); } finally