Example #1
0
        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;
                }
Example #3
0
        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);
        }
Example #4
0
            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));
        }
Example #6
0
                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);
            }
Example #9
0
        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));
        }
Example #10
0
        public static void ReleaseMutex(IntPtr handle)
        {
            WaitableObject waitableObject = HandleManager.FromHandle(handle);

            s_lock.Acquire();
            try
            {
                waitableObject.SignalMutex();
            }
            finally
            {
                s_lock.Release();
            }
        }
Example #11
0
        public static void ResetEvent(IntPtr handle)
        {
            WaitableObject waitableObject = HandleManager.FromHandle(handle);

            s_lock.Acquire();
            try
            {
                waitableObject.UnsignalEvent();
            }
            finally
            {
                s_lock.Release();
            }
        }
Example #12
0
        public static void ResetEvent(WaitableObject waitableObject)
        {
            Debug.Assert(waitableObject != null);

            s_lock.Acquire();
            try
            {
                waitableObject.UnsignalEvent();
            }
            finally
            {
                s_lock.Release();
            }
        }
Example #13
0
        public static void ReleaseMutex(WaitableObject waitableObject)
        {
            Debug.Assert(waitableObject != null);

            s_lock.Acquire();
            try
            {
                waitableObject.SignalMutex();
            }
            finally
            {
                s_lock.Release();
            }
        }
Example #14
0
        public static void ReleaseMutex(WaitableObject waitableObject)
        {
            Debug.Assert(waitableObject != null);

            LockHolder lockHolder = new LockHolder(s_lock);

            try
            {
                waitableObject.SignalMutex(ref lockHolder);
            }
            finally
            {
                lockHolder.Dispose();
            }
        }
Example #15
0
        public static void ResetEvent(WaitableObject waitableObject)
        {
            Debug.Assert(waitableObject != null);

            LockHolder lockHolder = new LockHolder(s_lock);

            try
            {
                waitableObject.UnsignalEvent(ref lockHolder);
            }
            finally
            {
                lockHolder.Dispose();
            }
        }
Example #16
0
        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();
            }
        }
Example #17
0
        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();
            }
        }
Example #18
0
        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();
            }
        }
Example #19
0
        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();
                }
            }
        }
Example #20
0
        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);
                }
            }
        }
Example #21
0
        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;
                    }
                }
Example #23
0
        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);
        }
Example #24
0
        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();
            }
        }
Example #25
0
                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;
                }
Example #26
0
                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;
                }
Example #27
0
        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();
                }
            }
        }
Example #28
0
            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);
            }
Example #30
0
            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);
            }