Example #1
0
        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();
        }
Example #2
0
        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();
        }
Example #3
0
        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();
        }
Example #4
0
        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;
        }
Example #5
0
        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;
        }
Example #6
0
        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;
        }
Example #7
0
        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;
                }
            }
        }