public void CancelSynchronization() { System.CriticalSectionLock.Lock(); if ((SchedFlags & ThreadSchedState.LowNibbleMask) != ThreadSchedState.Paused || !WaitingSync) { SyncCancelled = true; } else if (WithholderNode != null) { System.Withholders.Remove(WithholderNode); SetNewSchedFlags(ThreadSchedState.Running); WithholderNode = null; SyncCancelled = true; } else { SignaledObj = null; ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Cancelled); SetNewSchedFlags(ThreadSchedState.Running); SyncCancelled = false; } System.CriticalSectionLock.Unlock(); }
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 = 0; Thread.Reschedule(ThreadSchedState.Running); } Node = Node.Next; } } System.CriticalSection.Leave(); }
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 = 0; thread.Reschedule(ThreadSchedState.Running); } node = node.Next; } } _system.CriticalSection.Leave(); }
private void SvcWaitSynchronization(CpuThreadState threadState) { long handlesPtr = (long)threadState.X1; int handlesCount = (int)threadState.X2; long timeout = (long)threadState.X3; Logger.PrintDebug(LogClass.KernelSvc, "HandlesPtr = 0x" + handlesPtr.ToString("x16") + ", " + "HandlesCount = 0x" + handlesCount.ToString("x8") + ", " + "Timeout = 0x" + timeout.ToString("x16")); if ((uint)handlesCount > 0x40) { threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.CountOutOfRange); return; } List <KSynchronizationObject> syncObjs = new List <KSynchronizationObject>(); for (int index = 0; index < handlesCount; index++) { int handle = _memory.ReadInt32(handlesPtr + index * 4); Logger.PrintDebug(LogClass.KernelSvc, $"Sync handle 0x{handle:x8}"); KSynchronizationObject syncObj = _process.HandleTable.GetObject <KSynchronizationObject>(handle); if (syncObj == null) { break; } syncObjs.Add(syncObj); } int hndIndex = (int)threadState.X1; ulong high = threadState.X1 & (0xffffffffUL << 32); long result = _system.Synchronization.WaitFor(syncObjs.ToArray(), timeout, ref hndIndex); if (result != 0) { if (result == MakeError(ErrorModule.Kernel, KernelErr.Timeout) || result == MakeError(ErrorModule.Kernel, KernelErr.Cancelled)) { Logger.PrintDebug(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); } else { Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{result:x}!"); } } threadState.X0 = (ulong)result; threadState.X1 = (uint)hndIndex | high; }
private void SvcWaitSynchronization(CpuThreadState ThreadState) { long HandlesPtr = (long)ThreadState.X1; int HandlesCount = (int)ThreadState.X2; long Timeout = (long)ThreadState.X3; Logger.PrintDebug(LogClass.KernelSvc, "HandlesPtr = 0x" + HandlesPtr.ToString("x16") + ", " + "HandlesCount = 0x" + HandlesCount.ToString("x8") + ", " + "Timeout = 0x" + Timeout.ToString("x16")); if ((uint)HandlesCount > 0x40) { ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.CountOutOfRange); return; } List <KSynchronizationObject> SyncObjs = new List <KSynchronizationObject>(); for (int Index = 0; Index < HandlesCount; Index++) { int Handle = Memory.ReadInt32(HandlesPtr + Index * 4); Logger.PrintDebug(LogClass.KernelSvc, $"Sync handle 0x{Handle:x8}"); KSynchronizationObject SyncObj = Process.HandleTable.GetObject <KSynchronizationObject>(Handle); if (SyncObj == null) { break; } SyncObjs.Add(SyncObj); } int HndIndex = (int)ThreadState.X1; ulong High = ThreadState.X1 & (0xffffffffUL << 32); long Result = System.Synchronization.WaitFor(SyncObjs.ToArray(), Timeout, ref HndIndex); if (Result != 0) { if (Result == MakeError(ErrorModule.Kernel, KernelErr.Timeout) || Result == MakeError(ErrorModule.Kernel, KernelErr.Cancelled)) { Logger.PrintDebug(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!"); } else { Logger.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!"); } } ThreadState.X0 = (ulong)Result; ThreadState.X1 = (uint)HndIndex | High; }
private void SvcWaitSynchronization(AThreadState ThreadState) { long HandlesPtr = (long)ThreadState.X1; int HandlesCount = (int)ThreadState.X2; long Timeout = (long)ThreadState.X3; Device.Log.PrintDebug(LogClass.KernelSvc, "HandlesPtr = 0x" + HandlesPtr.ToString("x16") + ", " + "HandlesCount = 0x" + HandlesCount.ToString("x8") + ", " + "Timeout = 0x" + Timeout.ToString("x16")); if ((uint)HandlesCount > 0x40) { ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.CountOutOfRange); return; } KSynchronizationObject[] SyncObjs = new KSynchronizationObject[HandlesCount]; for (int Index = 0; Index < HandlesCount; Index++) { int Handle = Memory.ReadInt32(HandlesPtr + Index * 4); KSynchronizationObject SyncObj = Process.HandleTable.GetData <KSynchronizationObject>(Handle); SyncObjs[Index] = SyncObj; } int HndIndex = (int)ThreadState.X1; ulong High = ThreadState.X1 & (0xffffffffUL << 32); long Result = System.Synchronization.WaitFor(SyncObjs, Timeout, ref HndIndex); if (Result != 0) { if (Result == MakeError(ErrorModule.Kernel, KernelErr.Timeout) || Result == MakeError(ErrorModule.Kernel, KernelErr.Cancelled)) { Device.Log.PrintDebug(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!"); } else { Device.Log.PrintWarning(LogClass.KernelSvc, $"Operation failed with error 0x{Result:x}!"); } } ThreadState.X0 = (ulong)Result; ThreadState.X1 = (uint)HndIndex | High; }
private void SvcWaitSynchronization(AThreadState ThreadState) { long HandlesPtr = (long)ThreadState.X1; int HandlesCount = (int)ThreadState.X2; ulong Timeout = ThreadState.X3; Device.Log.PrintDebug(LogClass.KernelSvc, "HandlesPtr = 0x" + HandlesPtr.ToString("x16") + ", " + "HandlesCount = 0x" + HandlesCount.ToString("x8") + ", " + "Timeout = 0x" + 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) { Device.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; } } }