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; }
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 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 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); }
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); }
public WaitedListNode(ThreadWaitInfo waitInfo, int waitedObjectIndex) { Debug.Assert(waitInfo != null); Debug.Assert(waitedObjectIndex >= 0); Debug.Assert(waitedObjectIndex < WaitHandle.MaxWaitHandles); _waitInfo = waitInfo; _waitedObjectIndex = waitedObjectIndex; }
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); }
public static void Sleep(int timeoutMilliseconds) { Debug.Assert(timeoutMilliseconds >= -1); ThreadWaitInfo waitInfo = RuntimeThread.CurrentThread.WaitInfo; if (waitInfo.CheckAndResetPendingInterrupt) { throw new ThreadInterruptedException(); } waitInfo.Sleep(timeoutMilliseconds); }
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)); }
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); }
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; }
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)); }
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; } }
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); }
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); }
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); }
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 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); }
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; } }
public static void Sleep(int timeoutMilliseconds, bool interruptible = true) { ThreadWaitInfo.Sleep(timeoutMilliseconds, interruptible); }
public static void UninterruptibleSleep0() { ThreadWaitInfo.UninterruptibleSleep0(); }
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)); }