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));
        }
            private void SignalMutex(bool isAbandoned)
            {
                s_lock.VerifyIsLocked();

                Debug.Assert(IsMutex);
                Debug.Assert(!IsSignaled);

                _ownershipInfo.RelinquishOwnership(this, isAbandoned);

                for (ThreadWaitInfo.WaitedListNode waiterNode = _waitersHead, nextWaiterNode;
                     waiterNode != null;
                     waiterNode = nextWaiterNode)
                {
                    // Signaling a waiter will unregister the waiter node, but it may only abort the wait without satisfying the
                    // wait, in which case we would try to signal another waiter. So, keep the next node before trying.
                    nextWaiterNode = waiterNode.Next;

                    ThreadWaitInfo waitInfo = waiterNode.WaitInfo;
                    if (waitInfo.TrySignalToSatisfyWait(waiterNode, isAbandoned))
                    {
                        _ownershipInfo.AssignOwnership(this, waitInfo);
                        return;
                    }
                }

                _signalCount = 1;
            }
Ejemplo n.º 3
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;
                }
Ejemplo n.º 5
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();
                }
            }
Ejemplo n.º 6
0
            public virtual bool continueWaitState(SceKernelThreadInfo thread, ThreadWaitInfo wait)
            {
                // Check if the thread has to continue its wait state or if the fpl
                // has been allocated during the callback execution.
                SceKernelFplInfo fpl = outerInstance.fplMap[wait.Fpl_id];

                if (fpl == null)
                {
                    thread.cpuContext._v0 = ERROR_KERNEL_NOT_FOUND_FPOOL;
                    return(false);
                }

                // Check fpl.
                int addr = outerInstance.tryAllocateFpl(fpl);

                if (addr != 0)
                {
                    fpl.threadWaitingList.removeWaitingThread(thread);
                    thread.wait.Fpl_dataAddr.setValue(addr);
                    thread.cpuContext._v0 = 0;
                    return(false);
                }

                return(true);
            }
Ejemplo n.º 7
0
            public virtual bool continueWaitState(SceKernelThreadInfo thread, ThreadWaitInfo wait)
            {
                // Check if the thread has to continue its wait state or if the mbx
                // has received a new message during the callback execution.
                SceKernelMbxInfo info = outerInstance.mbxMap[wait.Mbx_id];

                if (info == null)
                {
                    thread.cpuContext._v0 = ERROR_KERNEL_NOT_FOUND_MESSAGE_BOX;
                    return(false);
                }

                // Check the mbx for a new message.
                if (info.hasMessage())
                {
                    Memory mem     = Memory.Instance;
                    int    msgAddr = info.removeMsg(mem);
                    wait.Mbx_resultAddr.setValue(msgAddr);
                    info.threadWaitingList.removeWaitingThread(thread);
                    thread.cpuContext._v0 = 0;
                    return(false);
                }

                return(true);
            }
            /// <summary>
            /// This function does not check for a pending thread interrupt. Callers are expected to do that soon after
            /// acquiring <see cref="s_lock"/>.
            /// </summary>
            public bool Wait_Locked(ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible, bool prioritize)
            {
                s_lock.VerifyIsLocked();
                Debug.Assert(waitInfo != null);
                Debug.Assert(waitInfo.Thread == RuntimeThread.CurrentThread);

                Debug.Assert(timeoutMilliseconds >= -1);
                Debug.Assert(!interruptible || !waitInfo.CheckAndResetPendingInterrupt);

                bool needToWait = false;

                try
                {
                    if (IsSignaled)
                    {
                        bool isAbandoned = IsAbandonedMutex;
                        AcceptSignal(waitInfo);
                        if (isAbandoned)
                        {
                            throw new AbandonedMutexException();
                        }
                        return(true);
                    }

                    if (IsMutex && _ownershipInfo.Thread == waitInfo.Thread)
                    {
                        if (!_ownershipInfo.CanIncrementReacquireCount)
                        {
                            throw new OverflowException(SR.Overflow_MutexReacquireCount);
                        }
                        _ownershipInfo.IncrementReacquireCount();
                        return(true);
                    }

                    if (timeoutMilliseconds == 0)
                    {
                        return(false);
                    }

                    WaitableObject[] waitableObjects = waitInfo.GetWaitedObjectArray(1);
                    waitableObjects[0] = this;
                    waitInfo.RegisterWait(1, prioritize, isWaitForAll: false);
                    needToWait = true;
                }
                finally
                {
                    // Once the wait function is called, it will release the lock
                    if (!needToWait)
                    {
                        s_lock.Release();
                    }
                }

                return
                    (waitInfo.Wait(
                         timeoutMilliseconds,
                         interruptible,
                         waitHandlesForAbandon: null,
                         isSleep: false) != WaitHandle.WaitTimeout);
            }
Ejemplo n.º 9
0
                public WaitedListNode(ThreadWaitInfo waitInfo, int waitedObjectIndex)
                {
                    Debug.Assert(waitInfo != null);
                    Debug.Assert(waitedObjectIndex >= 0);
                    Debug.Assert(waitedObjectIndex < WaitHandle.MaxWaitHandles);

                    _waitInfo          = waitInfo;
                    _waitedObjectIndex = waitedObjectIndex;
                }
Ejemplo n.º 10
0
            public virtual bool continueWaitState(SceKernelThreadInfo thread, ThreadWaitInfo wait)
            {
                // Continue the wait state until the list is done
                bool contineWait = !list.Done;

                if (!contineWait)
                {
                    ExternalGE.onGeStopWaitList();
                }

                return(contineWait);
            }
Ejemplo n.º 11
0
        public static void Sleep(int timeoutMilliseconds)
        {
            Debug.Assert(timeoutMilliseconds >= -1);

            ThreadWaitInfo waitInfo = RuntimeThread.CurrentThread.WaitInfo;

            if (waitInfo.CheckAndResetPendingInterrupt)
            {
                throw new ThreadInterruptedException();
            }

            waitInfo.Sleep(timeoutMilliseconds);
        }
Ejemplo n.º 12
0
        public static bool Wait(IntPtr handle, int timeoutMilliseconds)
        {
            Debug.Assert(timeoutMilliseconds >= -1);

            ThreadWaitInfo waitInfo = RuntimeThread.CurrentThread.WaitInfo;

            if (waitInfo.CheckAndResetPendingInterrupt)
            {
                throw new ThreadInterruptedException();
            }

            return(HandleManager.FromHandle(handle).Wait(waitInfo, timeoutMilliseconds));
        }
Ejemplo n.º 13
0
            public virtual bool continueWaitState(SceKernelThreadInfo thread, ThreadWaitInfo wait)
            {
                if (outerInstance.checkDriveStat(wait.wantedUmdStat))
                {
                    outerInstance.waitingThreads.Remove(thread);
                    // Return success
                    thread.cpuContext._v0 = 0;

                    // Do not continue the wait state
                    return(false);
                }

                return(true);
            }
Ejemplo n.º 14
0
        public virtual void copy(ThreadWaitInfo that)
        {
            forever           = that.forever;
            microTimeTimeout  = that.microTimeTimeout;
            micros            = that.micros;
            waitTimeoutAction = that.waitTimeoutAction;
            waitStateChecker  = that.waitStateChecker;

            ThreadEnd_id = that.ThreadEnd_id;
            ThreadEnd_returnExitStatus = that.ThreadEnd_returnExitStatus;

            EventFlag_id           = that.EventFlag_id;
            EventFlag_bits         = that.EventFlag_bits;
            EventFlag_wait         = that.EventFlag_wait;
            EventFlag_outBits_addr = that.EventFlag_outBits_addr;

            Semaphore_id     = that.Semaphore_id;
            Semaphore_signal = that.Semaphore_signal;

            Mutex_id    = that.Mutex_id;
            Mutex_count = that.Mutex_count;

            LwMutex_id    = that.LwMutex_id;
            LwMutex_count = that.LwMutex_count;

            Io_id         = that.Io_id;
            Io_resultAddr = that.Io_resultAddr;

            wantedUmdStat = that.wantedUmdStat;

            MsgPipe_id              = that.MsgPipe_id;
            MsgPipe_address         = that.MsgPipe_address;
            MsgPipe_size            = that.MsgPipe_size;
            MsgPipe_waitMode        = that.MsgPipe_waitMode;
            MsgPipe_resultSize_addr = that.MsgPipe_resultSize_addr;
            MsgPipe_isSend          = that.MsgPipe_isSend;

            Mbx_id         = that.Mbx_id;
            Mbx_resultAddr = that.Mbx_resultAddr;

            Fpl_id       = that.Fpl_id;
            Fpl_dataAddr = that.Fpl_dataAddr;

            Vpl_id       = that.Vpl_id;
            Vpl_size     = that.Vpl_size;
            Vpl_dataAddr = that.Vpl_dataAddr;

            onUnblockAction = that.onUnblockAction;
        }
Ejemplo n.º 15
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();
                }
            }
        }
            public bool Wait(ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible, bool prioritize)
            {
                Debug.Assert(waitInfo != null);
                Debug.Assert(waitInfo.Thread == RuntimeThread.CurrentThread);

                Debug.Assert(timeoutMilliseconds >= -1);

                s_lock.Acquire();

                if (interruptible && waitInfo.CheckAndResetPendingInterrupt)
                {
                    s_lock.Release();
                    throw new ThreadInterruptedException();
                }

                return(Wait_Locked(waitInfo, timeoutMilliseconds, interruptible, prioritize));
            }
Ejemplo n.º 17
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);
        }
            /// <summary>
            /// This function does not check for a pending thread interrupt. Callers are expected to do that soon after
            /// acquiring <see cref="s_lock"/>.
            /// </summary>
            public int Wait_Locked(ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible, bool prioritize, ref LockHolder lockHolder)
            {
                s_lock.VerifyIsLocked();
                Debug.Assert(waitInfo != null);
                Debug.Assert(waitInfo.Thread == Thread.CurrentThread);

                Debug.Assert(timeoutMilliseconds >= -1);
                Debug.Assert(!interruptible || !waitInfo.CheckAndResetPendingInterrupt);

                if (IsSignaled)
                {
                    bool isAbandoned = IsAbandonedMutex;
                    AcceptSignal(waitInfo);
                    return(isAbandoned ? WaitHandle.WaitAbandoned : WaitHandle.WaitSuccess);
                }

                if (IsMutex && _ownershipInfo != null && _ownershipInfo.Thread == waitInfo.Thread)
                {
                    if (!_ownershipInfo.CanIncrementReacquireCount)
                    {
                        lockHolder.Dispose();
                        throw new OverflowException(SR.Overflow_MutexReacquireCount);
                    }
                    _ownershipInfo.IncrementReacquireCount();
                    return(WaitHandle.WaitSuccess);
                }

                if (timeoutMilliseconds == 0)
                {
                    return(WaitHandle.WaitTimeout);
                }

                WaitableObject?[] waitableObjects = waitInfo.GetWaitedObjectArray(1);
                waitableObjects[0] = this;
                waitInfo.RegisterWait(1, prioritize, isWaitForAll: false);

                return
                    (waitInfo.Wait(
                         timeoutMilliseconds,
                         interruptible,
                         isSleep: false,
                         ref lockHolder));
            }
                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;
                    }
                }
Ejemplo n.º 20
0
            public virtual bool continueWaitState(SceKernelThreadInfo thread, ThreadWaitInfo wait)
            {
                // Check if the thread has to continue its wait state or if the msgpipe
                // has been sent a new message during the callback execution.
                SceKernelMppInfo info = outerInstance.msgMap[wait.MsgPipe_id];

                if (info == null)
                {
                    thread.cpuContext._v0 = ERROR_KERNEL_NOT_FOUND_MESSAGE_PIPE;
                    return(false);
                }

                if (outerInstance.tryReceiveMsgPipe(info, wait.MsgPipe_address, wait.MsgPipe_size, wait.MsgPipe_waitMode, wait.MsgPipe_resultSize_addr))
                {
                    info.receiveThreadWaitingList.removeWaitingThread(thread);
                    thread.cpuContext._v0 = 0;
                    return(false);
                }

                return(true);
            }
Ejemplo n.º 21
0
            public virtual bool continueWaitState(SceKernelThreadInfo thread, ThreadWaitInfo wait)
            {
                // Check if the thread has to continue its wait state or if the event flag
                // has been set during the callback execution.
                SceKernelEventFlagInfo @event = eventMap[wait.EventFlag_id];

                if (@event == null)
                {
                    thread.cpuContext._v0 = ERROR_KERNEL_NOT_FOUND_EVENT_FLAG;
                    return(false);
                }

                // Check EventFlag.
                if (outerInstance.checkEventFlag(@event, wait.EventFlag_bits, wait.EventFlag_wait, wait.EventFlag_outBits_addr))
                {
                    @event.threadWaitingList.removeWaitingThread(thread);
                    thread.cpuContext._v0 = 0;
                    return(false);
                }

                return(true);
            }
Ejemplo n.º 22
0
            public virtual bool continueWaitState(SceKernelThreadInfo thread, ThreadWaitInfo wait)
            {
                // Check if the thread has to continue its wait state or if the lwmutex
                // has been unlocked during the callback execution.
                SceKernelLwMutexInfo info = outerInstance.lwMutexMap[wait.LwMutex_id];

                if (info == null)
                {
                    thread.cpuContext._v0 = ERROR_KERNEL_LWMUTEX_NOT_FOUND;
                    return(false);
                }

                // Check the lwmutex.
                if (outerInstance.tryLockLwMutex(info, wait.LwMutex_count, thread))
                {
                    info.threadWaitingList.removeWaitingThread(thread);
                    thread.cpuContext._v0 = 0;
                    return(false);
                }

                return(true);
            }
Ejemplo n.º 23
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();
            }
        }
Ejemplo n.º 24
0
            public virtual bool continueWaitState(SceKernelThreadInfo thread, ThreadWaitInfo wait)
            {
                // Check if the thread has to continue its wait state or if the sema
                // has been signaled during the callback execution.
                SceKernelSemaInfo sema = outerInstance.semaMap[wait.Semaphore_id];

                if (sema == null)
                {
                    thread.cpuContext._v0 = ERROR_KERNEL_NOT_FOUND_SEMAPHORE;
                    return(false);
                }

                // Check the sema.
                if (outerInstance.tryWaitSemaphore(sema, wait.Semaphore_signal))
                {
                    sema.threadWaitingList.removeWaitingThread(thread);
                    thread.cpuContext._v0 = 0;
                    return(false);
                }

                return(true);
            }
Ejemplo n.º 25
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();
                }
            }
        }
            public int Wait(ThreadWaitInfo waitInfo, int timeoutMilliseconds, bool interruptible, bool prioritize)
            {
                Debug.Assert(waitInfo != null);
                Debug.Assert(waitInfo.Thread == Thread.CurrentThread);

                Debug.Assert(timeoutMilliseconds >= -1);

                var lockHolder = new LockHolder(s_lock);

                try
                {
                    if (interruptible && waitInfo.CheckAndResetPendingInterrupt)
                    {
                        lockHolder.Dispose();
                        throw new ThreadInterruptedException();
                    }

                    return(Wait_Locked(waitInfo, timeoutMilliseconds, interruptible, prioritize, ref lockHolder));
                }
                finally
                {
                    lockHolder.Dispose();
                }
            }
            private void AcceptSignal(ThreadWaitInfo waitInfo)
            {
                s_lock.VerifyIsLocked();
                Debug.Assert(IsSignaled);

                switch (_type)
                {
                case WaitableObjectType.ManualResetEvent:
                    return;

                case WaitableObjectType.AutoResetEvent:
                case WaitableObjectType.Semaphore:
                    --_signalCount;
                    return;

                default:
                    Debug.Assert(_type == WaitableObjectType.Mutex);
                    --_signalCount;

                    Debug.Assert(_ownershipInfo.Thread == null);
                    _ownershipInfo.AssignOwnership(this, waitInfo);
                    return;
                }
            }
Ejemplo n.º 28
0
 public static void Sleep(int timeoutMilliseconds, bool interruptible = true)
 {
     ThreadWaitInfo.Sleep(timeoutMilliseconds, interruptible);
 }
Ejemplo n.º 29
0
 public static void UninterruptibleSleep0()
 {
     ThreadWaitInfo.UninterruptibleSleep0();
 }
Ejemplo n.º 30
0
        public static int Wait(
            Span <IntPtr> waitHandles,
            bool waitForAll,
            int timeoutMilliseconds)
        {
            Debug.Assert(waitHandles != null);
            Debug.Assert(waitHandles.Length > 0);
            Debug.Assert(waitHandles.Length <= WaitHandle.MaxWaitHandles);
            Debug.Assert(timeoutMilliseconds >= -1);

            ThreadWaitInfo waitInfo = Thread.CurrentThread.WaitInfo;

            WaitableObject?[] waitableObjects = waitInfo.GetWaitedObjectArray(waitHandles.Length);
            bool success = false;

            try
            {
                for (int i = 0; i < waitHandles.Length; ++i)
                {
                    Debug.Assert(waitHandles[i] != IntPtr.Zero);
                    WaitableObject waitableObject = HandleManager.FromHandle(waitHandles[i]);
                    if (waitForAll)
                    {
                        // Check if this is a duplicate, as wait-for-all does not support duplicates. Including the parent
                        // loop, this becomes a brute force O(n^2) search, which is intended since the typical array length is
                        // short enough that this would actually be faster than other alternatives. Also, the worst case is not
                        // so bad considering that the array length is limited by <see cref="WaitHandle.MaxWaitHandles"/>.
                        for (int j = 0; j < i; ++j)
                        {
                            if (waitableObject == waitableObjects[j])
                            {
                                throw new DuplicateWaitObjectException("waitHandles[" + i + ']');
                            }
                        }
                    }

                    waitableObjects[i] = waitableObject;
                }
                success = true;
            }
            finally
            {
                if (!success)
                {
                    for (int i = 0; i < waitHandles.Length; ++i)
                    {
                        waitableObjects[i] = null;
                    }
                }
            }

            if (waitHandles.Length == 1)
            {
                WaitableObject waitableObject = waitableObjects[0] !;
                waitableObjects[0] = null;
                return
                    (waitableObject.Wait(waitInfo, timeoutMilliseconds, interruptible: true, prioritize: false));
            }

            return
                (WaitableObject.Wait(
                     waitableObjects,
                     waitHandles.Length,
                     waitForAll,
                     waitInfo,
                     timeoutMilliseconds,
                     interruptible: true,
                     prioritize: false));
        }