public static SafeWaitHandle?CreateNamedMutex(bool initiallyOwned, string name, out bool createdNew) { // For initially owned, newly created named mutexes, there is a potential race // between adding the mutex to the named object table and initially acquiring it. // To avoid the possibility of another thread retrieving the mutex via its name // before we managed to acquire it, we perform both steps while holding s_lock. LockHolder lockHolder = new LockHolder(s_lock); try { WaitableObject?waitableObject = WaitableObject.CreateNamedMutex_Locked(name, out createdNew); if (waitableObject == null) { return(null); } SafeWaitHandle safeWaitHandle = NewHandle(waitableObject); if (!initiallyOwned || !createdNew) { return(safeWaitHandle); } // Acquire the mutex. A thread's <see cref="ThreadWaitInfo"/> has a reference to all <see cref="Mutex"/>es locked // by the thread. See <see cref="ThreadWaitInfo.LockedMutexesHead"/>. 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); Debug.Assert(status == 0); return(safeWaitHandle); } finally { lockHolder.Dispose(); } }
public void AssignOwnership(WaitableObject waitableObject, ThreadWaitInfo waitInfo) { s_lock.VerifyIsLocked(); Debug.Assert(waitableObject != null); Debug.Assert(waitableObject.IsMutex); Debug.Assert(waitableObject._ownershipInfo == this); Debug.Assert(_thread == null); Debug.Assert(_reacquireCount == 0); Debug.Assert(_previous == null); Debug.Assert(_next == null); _thread = waitInfo.Thread; _isAbandoned = false; WaitableObject head = waitInfo.LockedMutexesHead; if (head != null) { _next = head; head._ownershipInfo._previous = waitableObject; } waitInfo.LockedMutexesHead = waitableObject; }
public static OpenExistingResult OpenNamedMutex(string name, out SafeWaitHandle?result) { OpenExistingResult status = WaitableObject.OpenNamedMutex(name, out WaitableObject? mutex); result = status == OpenExistingResult.Success ? NewHandle(mutex !) : null; return(status); }
public static void SatisfyWaitForAll( ThreadWaitInfo waitInfo, WaitableObject[] waitedObjects, int waitedCount, int signaledWaitedObjectIndex) { Debug.Assert(waitInfo != null); Debug.Assert(waitInfo.Thread != RuntimeThread.CurrentThread); Debug.Assert(waitedObjects != null); Debug.Assert(waitedObjects.Length >= waitedCount); Debug.Assert(waitedCount > 1); Debug.Assert(signaledWaitedObjectIndex >= 0); Debug.Assert(signaledWaitedObjectIndex <= WaitHandle.MaxWaitHandles); for (int i = 0; i < waitedCount; ++i) { Debug.Assert(waitedObjects[i] != null); if (i == signaledWaitedObjectIndex) { continue; } WaitableObject waitedObject = waitedObjects[i]; if (waitedObject.IsSignaled) { waitedObject.AcceptSignal(waitInfo); continue; } Debug.Assert(waitedObject.IsMutex); OwnershipInfo ownershipInfo = waitedObject._ownershipInfo; Debug.Assert(ownershipInfo.Thread == waitInfo.Thread); ownershipInfo.IncrementReacquireCount(); } }
public static int Wait( RuntimeThread currentThread, WaitableObject waitableObject0, WaitableObject waitableObject1, bool waitForAll, int timeoutMilliseconds, bool interruptible = true, bool prioritize = false) { Debug.Assert(currentThread == RuntimeThread.CurrentThread); Debug.Assert(waitableObject0 != null); Debug.Assert(waitableObject1 != null); Debug.Assert(waitableObject1 != waitableObject0); Debug.Assert(timeoutMilliseconds >= -1); ThreadWaitInfo waitInfo = currentThread.WaitInfo; int count = 2; WaitableObject[] waitableObjects = waitInfo.GetWaitedObjectArray(count); waitableObjects[0] = waitableObject0; waitableObjects[1] = waitableObject1; return (WaitableObject.Wait( waitableObjects, count, waitForAll, waitInfo, timeoutMilliseconds, interruptible, prioritize, waitHandlesForAbandon: null)); }
public void UnregisterWait(WaitableObject waitableObject) { s_lock.VerifyIsLocked(); Debug.Assert(waitableObject != null); WaitedListNode previous = _previous; WaitedListNode next = _next; if (previous != null) { previous._next = next; _previous = null; } else { Debug.Assert(waitableObject.WaitersHead == this); waitableObject.WaitersHead = next; } if (next != null) { next._previous = previous; _next = null; } else { Debug.Assert(waitableObject.WaitersTail == this); waitableObject.WaitersTail = previous; } }
public static bool WouldWaitForAllBeSatisfiedOrAborted( RuntimeThread waitingThread, WaitableObject[] waitedObjects, int waitedCount, int signaledWaitedObjectIndex, ref bool wouldAnyMutexReacquireCountOverflow, ref bool isAnyAbandonedMutex) { s_lock.VerifyIsLocked(); Debug.Assert(waitingThread != null); Debug.Assert(waitingThread != RuntimeThread.CurrentThread); Debug.Assert(waitedObjects != null); Debug.Assert(waitedObjects.Length >= waitedCount); Debug.Assert(waitedCount > 1); Debug.Assert(signaledWaitedObjectIndex >= 0); Debug.Assert(signaledWaitedObjectIndex <= WaitHandle.MaxWaitHandles); Debug.Assert(!wouldAnyMutexReacquireCountOverflow); for (int i = 0; i < waitedCount; ++i) { Debug.Assert(waitedObjects[i] != null); if (i == signaledWaitedObjectIndex) { continue; } WaitableObject waitedObject = waitedObjects[i]; if (waitedObject.IsSignaled) { if (!isAnyAbandonedMutex && waitedObject.IsAbandonedMutex) { isAnyAbandonedMutex = true; } continue; } if (waitedObject.IsMutex) { OwnershipInfo ownershipInfo = waitedObject._ownershipInfo; if (ownershipInfo.Thread == waitingThread) { if (!ownershipInfo.CanIncrementReacquireCount) { // This will cause the wait to be aborted without accepting any signals wouldAnyMutexReacquireCountOverflow = true; return(true); } continue; } } return(false); } return(true); }
public static IntPtr NewHandle(WaitableObject waitableObject) { Debug.Assert(waitableObject != null); IntPtr handle = GCHandle.ToIntPtr(GCHandle.Alloc(waitableObject, GCHandleType.Normal)); // SafeWaitHandle treats -1 and 0 as invalid, and the handle should not be these values anyway Debug.Assert(handle != IntPtr.Zero); Debug.Assert(handle != new IntPtr(-1)); return(handle); }
public static int Wait( WaitableObject waitableObject, int timeoutMilliseconds, bool interruptible = true, bool prioritize = false) { Debug.Assert(waitableObject != null); Debug.Assert(timeoutMilliseconds >= -1); return(waitableObject.Wait(Thread.CurrentThread.WaitInfo, timeoutMilliseconds, interruptible, prioritize)); }
public static void ReleaseMutex(IntPtr handle) { WaitableObject waitableObject = HandleManager.FromHandle(handle); s_lock.Acquire(); try { waitableObject.SignalMutex(); } finally { s_lock.Release(); } }
public static void ResetEvent(IntPtr handle) { WaitableObject waitableObject = HandleManager.FromHandle(handle); s_lock.Acquire(); try { waitableObject.UnsignalEvent(); } finally { s_lock.Release(); } }
public static void ResetEvent(WaitableObject waitableObject) { Debug.Assert(waitableObject != null); s_lock.Acquire(); try { waitableObject.UnsignalEvent(); } finally { s_lock.Release(); } }
public static void ReleaseMutex(WaitableObject waitableObject) { Debug.Assert(waitableObject != null); s_lock.Acquire(); try { waitableObject.SignalMutex(); } finally { s_lock.Release(); } }
public static void ReleaseMutex(WaitableObject waitableObject) { Debug.Assert(waitableObject != null); LockHolder lockHolder = new LockHolder(s_lock); try { waitableObject.SignalMutex(ref lockHolder); } finally { lockHolder.Dispose(); } }
public static void ResetEvent(WaitableObject waitableObject) { Debug.Assert(waitableObject != null); LockHolder lockHolder = new LockHolder(s_lock); try { waitableObject.UnsignalEvent(ref lockHolder); } finally { lockHolder.Dispose(); } }
public static int ReleaseSemaphore(WaitableObject waitableObject, int count) { Debug.Assert(waitableObject != null); Debug.Assert(count > 0); s_lock.Acquire(); try { return(waitableObject.SignalSemaphore(count)); } finally { s_lock.Release(); } }
public static int ReleaseSemaphore(IntPtr handle, int count) { Debug.Assert(count > 0); WaitableObject waitableObject = HandleManager.FromHandle(handle); s_lock.Acquire(); try { return(waitableObject.SignalSemaphore(count)); } finally { s_lock.Release(); } }
public static int ReleaseSemaphore(WaitableObject waitableObject, int count) { Debug.Assert(waitableObject != null); Debug.Assert(count > 0); LockHolder lockHolder = new LockHolder(s_lock); try { return(waitableObject.SignalSemaphore(count, ref lockHolder)); } finally { lockHolder.Dispose(); } }
public static int SignalAndWait( WaitableObject waitableObjectToSignal, WaitableObject waitableObjectToWaitOn, int timeoutMilliseconds, bool interruptible = true, bool prioritize = false) { Debug.Assert(waitableObjectToSignal != null); Debug.Assert(waitableObjectToWaitOn != null); Debug.Assert(timeoutMilliseconds >= -1); ThreadWaitInfo waitInfo = Thread.CurrentThread.WaitInfo; bool waitCalled = false; s_lock.Acquire(); try { // A pending interrupt does not signal the specified handle if (interruptible && waitInfo.CheckAndResetPendingInterrupt) { throw new ThreadInterruptedException(); } try { waitableObjectToSignal.Signal(1); } catch (SemaphoreFullException ex) { throw new InvalidOperationException(SR.Threading_WaitHandleTooManyPosts, ex); } waitCalled = true; return(waitableObjectToWaitOn.Wait_Locked(waitInfo, timeoutMilliseconds, interruptible, prioritize)); } finally { // Once the wait function is called, it will release the lock if (waitCalled) { s_lock.VerifyIsNotLocked(); } else { s_lock.Release(); } } }
private static SafeWaitHandle NewHandle(WaitableObject waitableObject) { IntPtr handle = HandleManager.NewHandle(waitableObject); SafeWaitHandle?safeWaitHandle = null; try { safeWaitHandle = new SafeWaitHandle(handle, ownsHandle: true); return(safeWaitHandle); } finally { if (safeWaitHandle == null) { HandleManager.DeleteHandle(handle); } } }
public static SafeWaitHandle NewMutex(bool initiallyOwned) { WaitableObject waitableObject = WaitableObject.NewMutex(); SafeWaitHandle safeWaitHandle = NewHandle(waitableObject); if (!initiallyOwned) { return(safeWaitHandle); } // Acquire the mutex. A thread's <see cref="ThreadWaitInfo"/> has a reference to all <see cref="Mutex"/>es locked // by the thread. See <see cref="ThreadWaitInfo.LockedMutexesHead"/>. 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; Debug.Assert(acquiredLock); return(safeWaitHandle); }
public void RelinquishOwnership(WaitableObject waitableObject, bool isAbandoned) { s_lock.VerifyIsLocked(); Debug.Assert(waitableObject != null); Debug.Assert(waitableObject.IsMutex); Debug.Assert(waitableObject._ownershipInfo == this); Debug.Assert(_thread != null); ThreadWaitInfo waitInfo = _thread.WaitInfo; Debug.Assert(isAbandoned ? _reacquireCount >= 0 : _reacquireCount == 0); Debug.Assert(!_isAbandoned); _thread = null; if (isAbandoned) { _reacquireCount = 0; _isAbandoned = isAbandoned; } WaitableObject previous = _previous; WaitableObject next = _next; if (previous != null) { previous._ownershipInfo._next = next; _previous = null; } else { Debug.Assert(waitInfo.LockedMutexesHead == waitableObject); waitInfo.LockedMutexesHead = next; } if (next != null) { next._ownershipInfo._previous = previous; _next = null; } }
private static SafeWaitHandle NewHandle(WaitableObject waitableObject) { var safeWaitHandle = new SafeWaitHandle(); IntPtr handle = IntPtr.Zero; try { handle = HandleManager.NewHandle(waitableObject); } finally { if (handle == IntPtr.Zero) { waitableObject.OnDeleteHandle(); } } Marshal.InitHandle(safeWaitHandle, handle); return(safeWaitHandle); }
public static int SignalAndWait( WaitableObject waitableObjectToSignal, WaitableObject waitableObjectToWaitOn, int timeoutMilliseconds, bool interruptible = true, bool prioritize = false) { Debug.Assert(waitableObjectToSignal != null); Debug.Assert(waitableObjectToWaitOn != null); Debug.Assert(timeoutMilliseconds >= -1); ThreadWaitInfo waitInfo = Thread.CurrentThread.WaitInfo; LockHolder lockHolder = new LockHolder(s_lock); try { // A pending interrupt does not signal the specified handle if (interruptible && waitInfo.CheckAndResetPendingInterrupt) { lockHolder.Dispose(); throw new ThreadInterruptedException(); } try { waitableObjectToSignal.Signal(1, ref lockHolder); } catch (SemaphoreFullException ex) { s_lock.VerifyIsNotLocked(); throw new InvalidOperationException(SR.Threading_WaitHandleTooManyPosts, ex); } return(waitableObjectToWaitOn.Wait_Locked(waitInfo, timeoutMilliseconds, interruptible, prioritize, ref lockHolder)); } finally { lockHolder.Dispose(); } }
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 RegisterWait(WaitableObject waitableObject) { s_lock.VerifyIsLocked(); Debug.Assert(_waitInfo.Thread == Thread.CurrentThread); Debug.Assert(waitableObject != null); Debug.Assert(_previous == null); Debug.Assert(_next == null); WaitedListNode tail = waitableObject.WaitersTail; if (tail != null) { _previous = tail; tail._next = this; } else { waitableObject.WaitersHead = this; } waitableObject.WaitersTail = this; }
public static bool SignalAndWait(IntPtr handleToSignal, IntPtr handleToWaitOn, int timeoutMilliseconds) { Debug.Assert(timeoutMilliseconds >= -1); ThreadWaitInfo waitInfo = RuntimeThread.CurrentThread.WaitInfo; // A pending interrupt does not signal the specified handle if (waitInfo.CheckAndResetPendingInterrupt) { throw new ThreadInterruptedException(); } WaitableObject waitableObjectToSignal = HandleManager.FromHandle(handleToSignal); WaitableObject waitableObjectToWaitOn = HandleManager.FromHandle(handleToWaitOn); bool waitCalled = false; s_lock.Acquire(); try { waitableObjectToSignal.Signal(1); waitCalled = true; return(waitableObjectToWaitOn.Wait_Locked(waitInfo, timeoutMilliseconds)); } finally { // Once the wait function is called, it will release the lock if (waitCalled) { s_lock.VerifyIsNotLocked(); } else { s_lock.Release(); } } }
public void OnThreadExiting() { // Abandon locked mutexes. Acquired mutexes are prepended to the linked list, so the mutexes are abandoned in // last-acquired-first-abandoned order. s_lock.Acquire(); try { while (true) { WaitableObject waitableObject = LockedMutexesHead; if (waitableObject == null) { break; } waitableObject.AbandonMutex(); Debug.Assert(LockedMutexesHead != waitableObject); } } finally { s_lock.Release(); } }
public static WaitableObject?CreateNamedMutex_Locked(string name, out bool createdNew) { s_lock.VerifyIsLocked(); s_namedObjects ??= new Dictionary <string, WaitableObject>(); if (s_namedObjects.TryGetValue(name, out WaitableObject? result)) { createdNew = false; if (!result.IsMutex) { return(null); } result._referenceCount++; } else { createdNew = true; result = new WaitableObject(WaitableObjectType.Mutex, 1, 1, name, new OwnershipInfo()); s_namedObjects.Add(name, result); } return(result); }
public bool TrySignalToSatisfyWait(WaitedListNode registeredListNode, bool isAbandonedMutex) { s_lock.VerifyIsLocked(); Debug.Assert(_thread != Thread.CurrentThread); Debug.Assert(registeredListNode != null); Debug.Assert(registeredListNode.WaitInfo == this); Debug.Assert(registeredListNode.WaitedObjectIndex >= 0); Debug.Assert(registeredListNode.WaitedObjectIndex < _waitedCount); Debug.Assert(_waitedCount > (_isWaitForAll ? 1 : 0)); int signaledWaitedObjectIndex = registeredListNode.WaitedObjectIndex; bool isWaitForAll = _isWaitForAll; bool wouldAnyMutexReacquireCountOverflow = false; if (isWaitForAll) { // Determine if all waits would be satisfied if (!WaitableObject.WouldWaitForAllBeSatisfiedOrAborted( _thread, _waitedObjects, _waitedCount, signaledWaitedObjectIndex, ref wouldAnyMutexReacquireCountOverflow, ref isAbandonedMutex)) { return(false); } } // The wait would be satisfied. Before making changes to satisfy the wait, acquire the monitor and verify that // the thread can accept a signal. _waitMonitor.Acquire(); if (!IsWaiting) { _waitMonitor.Release(); return(false); } if (isWaitForAll && !wouldAnyMutexReacquireCountOverflow) { // All waits would be satisfied, accept the signals WaitableObject.SatisfyWaitForAll(this, _waitedObjects, _waitedCount, signaledWaitedObjectIndex); } UnregisterWait(); Debug.Assert(_waitedObjectIndexThatSatisfiedWait < 0); if (wouldAnyMutexReacquireCountOverflow) { _waitSignalState = WaitSignalState.NotWaiting_SignaledToAbortWaitDueToMaximumMutexReacquireCount; } else { _waitedObjectIndexThatSatisfiedWait = signaledWaitedObjectIndex; _waitSignalState = isAbandonedMutex ? WaitSignalState.NotWaiting_SignaledToSatisfyWaitWithAbandonedMutex : WaitSignalState.NotWaiting_SignaledToSatisfyWait; } _waitMonitor.Signal_Release(); return(!wouldAnyMutexReacquireCountOverflow); }