private KernelResult WaitSynchronization(ulong handlesPtr, int handlesCount, long timeout, out int handleIndex) { handleIndex = 0; if ((uint)handlesCount > 0x40) { return(KernelResult.MaximumExceeded); } List <KSynchronizationObject> syncObjs = new List <KSynchronizationObject>(); for (int index = 0; index < handlesCount; index++) { int handle = _process.CpuMemory.ReadInt32((long)handlesPtr + index * 4); KSynchronizationObject syncObj = _process.HandleTable.GetObject <KSynchronizationObject>(handle); if (syncObj == null) { break; } syncObjs.Add(syncObj); } return(_system.Synchronization.WaitFor(syncObjs.ToArray(), timeout, out handleIndex)); }
public void SignalObject(KSynchronizationObject syncObj) { _system.CriticalSection.Enter(); if (syncObj.IsSignaled()) { LinkedListNode <KThread> node = syncObj.WaitingThreads.First; while (node != null) { KThread thread = node.Value; if ((thread.SchedFlags & ThreadSchedState.LowMask) == ThreadSchedState.Paused) { thread.SignaledObj = syncObj; thread.ObjSyncResult = KernelResult.Success; thread.Reschedule(ThreadSchedState.Running); } node = node.Next; } } _system.CriticalSection.Leave(); }
private void SvcWaitSynchronization(AThreadState ThreadState) { long HandlesPtr = (long)ThreadState.X1; int HandlesCount = (int)ThreadState.X2; long Timeout = (long)ThreadState.X3; KThread CurrThread = Process.GetThread(ThreadState.Tpidr); WaitHandle[] Handles = new WaitHandle[HandlesCount]; for (int Index = 0; Index < HandlesCount; Index++) { int Handle = Memory.ReadInt32(HandlesPtr + Index * 4); KSynchronizationObject SyncObj = Process.HandleTable.GetData <KSynchronizationObject>(Handle); if (SyncObj == null) { Logging.Warn($"Tried to WaitSynchronization on invalid handle 0x{Handle:x8}!"); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); return; } Handles[Index] = SyncObj.Handle; } Process.Scheduler.Suspend(CurrThread.ProcessorId); int HandleIndex; ulong Result = 0; if (Timeout != -1) { HandleIndex = WaitHandle.WaitAny(Handles, (int)(Timeout / 1000000)); if (HandleIndex == WaitHandle.WaitTimeout) { Result = MakeError(ErrorModule.Kernel, KernelErr.Timeout); } } else { HandleIndex = WaitHandle.WaitAny(Handles); } Process.Scheduler.Resume(CurrThread); ThreadState.X0 = Result; if (Result == 0) { ThreadState.X1 = (ulong)HandleIndex; } }
public KernelResult ReplyAndReceive64( ulong handlesPtr, int handlesCount, int replyTargetHandle, long timeout, out int handleIndex) { handleIndex = 0; if ((uint)handlesCount > 0x40) { return(KernelResult.MaximumExceeded); } KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); ulong copySize = (ulong)((long)handlesCount * 4); if (!currentProcess.MemoryManager.InsideAddrSpace(handlesPtr, copySize)) { return(KernelResult.UserCopyFailed); } if (handlesPtr + copySize < handlesPtr) { return(KernelResult.UserCopyFailed); } int[] handles = new int[handlesCount]; if (!KernelTransfer.UserToKernelInt32Array(_system, handlesPtr, handles)) { return(KernelResult.UserCopyFailed); } KSynchronizationObject[] syncObjs = new KSynchronizationObject[handlesCount]; for (int index = 0; index < handlesCount; index++) { KSynchronizationObject obj = currentProcess.HandleTable.GetObject <KSynchronizationObject>(handles[index]); if (obj == null) { return(KernelResult.InvalidHandle); } syncObjs[index] = obj; } KernelResult result; if (replyTargetHandle != 0) { KServerSession replyTarget = currentProcess.HandleTable.GetObject <KServerSession>(replyTargetHandle); if (replyTarget == null) { return(KernelResult.InvalidHandle); } result = replyTarget.Reply(); if (result != KernelResult.Success) { return(result); } } while ((result = _system.Synchronization.WaitFor(syncObjs, timeout, out handleIndex)) == KernelResult.Success) { KServerSession session = currentProcess.HandleTable.GetObject <KServerSession>(handles[handleIndex]); if (session == null) { break; } if ((result = session.Receive()) != KernelResult.NotFound) { break; } } return(result); }
private void SvcWaitSynchronization(AThreadState ThreadState) { long HandlesPtr = (long)ThreadState.X1; int HandlesCount = (int)ThreadState.X2; ulong Timeout = ThreadState.X3; Ns.Log.PrintDebug(LogClass.KernelSvc, "HandlesPtr = " + HandlesPtr.ToString("x16") + ", " + "HandlesCount = " + HandlesCount.ToString("x8") + ", " + "Timeout = " + Timeout.ToString("x16")); if ((uint)HandlesCount > 0x40) { ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.CountOutOfRange); return; } KThread CurrThread = Process.GetThread(ThreadState.Tpidr); WaitHandle[] Handles = new WaitHandle[HandlesCount + 1]; for (int Index = 0; Index < HandlesCount; Index++) { int Handle = Memory.ReadInt32(HandlesPtr + Index * 4); KSynchronizationObject SyncObj = Process.HandleTable.GetData <KSynchronizationObject>(Handle); if (SyncObj == null) { Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid handle 0x{Handle:x8}!"); ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); return; } Handles[Index] = SyncObj.WaitEvent; } using (AutoResetEvent WaitEvent = new AutoResetEvent(false)) { if (!SyncWaits.TryAdd(CurrThread, WaitEvent)) { throw new InvalidOperationException(); } Handles[HandlesCount] = WaitEvent; Process.Scheduler.Suspend(CurrThread); int HandleIndex; ulong Result = 0; if (Timeout != ulong.MaxValue) { HandleIndex = WaitHandle.WaitAny(Handles, NsTimeConverter.GetTimeMs(Timeout)); } else { HandleIndex = WaitHandle.WaitAny(Handles); } if (HandleIndex == WaitHandle.WaitTimeout) { Result = MakeError(ErrorModule.Kernel, KernelErr.Timeout); } else if (HandleIndex == HandlesCount) { Result = MakeError(ErrorModule.Kernel, KernelErr.Canceled); } SyncWaits.TryRemove(CurrThread, out _); Process.Scheduler.Resume(CurrThread); ThreadState.X0 = Result; if (Result == 0) { ThreadState.X1 = (ulong)HandleIndex; } } }