Ejemplo n.º 1
0
 public void Resume(KThread Thread)
 {
     TryResumingExecution(AllThreads[Thread]);
 }
Ejemplo n.º 2
0
 public void WakeUp(KThread Thread)
 {
     AllThreads[Thread].WaitSync.Set();
 }
Ejemplo n.º 3
0
 public void Yield(KThread Thread)
 {
     Yield(Thread, Thread.ActualPriority);
 }
Ejemplo n.º 4
0
        private void SvcGetThreadContext3(CpuThreadState ThreadState)
        {
            long Position = (long)ThreadState.X0;
            int  Handle   = (int)ThreadState.X1;

            KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();
            KThread  CurrentThread  = System.Scheduler.GetCurrentThread();

            KThread Thread = Process.HandleTable.GetObject <KThread>(Handle);

            if (Thread == null)
            {
                Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");

                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);

                return;
            }

            if (Thread.Owner != CurrentProcess)
            {
                Logger.PrintWarning(LogClass.KernelSvc, $"Invalid thread, it belongs to another process.");

                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);

                return;
            }

            if (CurrentThread == Thread)
            {
                Logger.PrintWarning(LogClass.KernelSvc, "Invalid thread, current thread is not accepted.");

                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidThread);

                return;
            }

            Memory.WriteUInt64(Position + 0x0, Thread.Context.ThreadState.X0);
            Memory.WriteUInt64(Position + 0x8, Thread.Context.ThreadState.X1);
            Memory.WriteUInt64(Position + 0x10, Thread.Context.ThreadState.X2);
            Memory.WriteUInt64(Position + 0x18, Thread.Context.ThreadState.X3);
            Memory.WriteUInt64(Position + 0x20, Thread.Context.ThreadState.X4);
            Memory.WriteUInt64(Position + 0x28, Thread.Context.ThreadState.X5);
            Memory.WriteUInt64(Position + 0x30, Thread.Context.ThreadState.X6);
            Memory.WriteUInt64(Position + 0x38, Thread.Context.ThreadState.X7);
            Memory.WriteUInt64(Position + 0x40, Thread.Context.ThreadState.X8);
            Memory.WriteUInt64(Position + 0x48, Thread.Context.ThreadState.X9);
            Memory.WriteUInt64(Position + 0x50, Thread.Context.ThreadState.X10);
            Memory.WriteUInt64(Position + 0x58, Thread.Context.ThreadState.X11);
            Memory.WriteUInt64(Position + 0x60, Thread.Context.ThreadState.X12);
            Memory.WriteUInt64(Position + 0x68, Thread.Context.ThreadState.X13);
            Memory.WriteUInt64(Position + 0x70, Thread.Context.ThreadState.X14);
            Memory.WriteUInt64(Position + 0x78, Thread.Context.ThreadState.X15);
            Memory.WriteUInt64(Position + 0x80, Thread.Context.ThreadState.X16);
            Memory.WriteUInt64(Position + 0x88, Thread.Context.ThreadState.X17);
            Memory.WriteUInt64(Position + 0x90, Thread.Context.ThreadState.X18);
            Memory.WriteUInt64(Position + 0x98, Thread.Context.ThreadState.X19);
            Memory.WriteUInt64(Position + 0xa0, Thread.Context.ThreadState.X20);
            Memory.WriteUInt64(Position + 0xa8, Thread.Context.ThreadState.X21);
            Memory.WriteUInt64(Position + 0xb0, Thread.Context.ThreadState.X22);
            Memory.WriteUInt64(Position + 0xb8, Thread.Context.ThreadState.X23);
            Memory.WriteUInt64(Position + 0xc0, Thread.Context.ThreadState.X24);
            Memory.WriteUInt64(Position + 0xc8, Thread.Context.ThreadState.X25);
            Memory.WriteUInt64(Position + 0xd0, Thread.Context.ThreadState.X26);
            Memory.WriteUInt64(Position + 0xd8, Thread.Context.ThreadState.X27);
            Memory.WriteUInt64(Position + 0xe0, Thread.Context.ThreadState.X28);
            Memory.WriteUInt64(Position + 0xe8, Thread.Context.ThreadState.X29);
            Memory.WriteUInt64(Position + 0xf0, Thread.Context.ThreadState.X30);
            Memory.WriteUInt64(Position + 0xf8, Thread.Context.ThreadState.X31);

            Memory.WriteInt64(Position + 0x100, Thread.LastPc);

            Memory.WriteUInt64(Position + 0x108, (ulong)Thread.Context.ThreadState.Psr);

            Memory.WriteVector128(Position + 0x110, Thread.Context.ThreadState.V0);
            Memory.WriteVector128(Position + 0x120, Thread.Context.ThreadState.V1);
            Memory.WriteVector128(Position + 0x130, Thread.Context.ThreadState.V2);
            Memory.WriteVector128(Position + 0x140, Thread.Context.ThreadState.V3);
            Memory.WriteVector128(Position + 0x150, Thread.Context.ThreadState.V4);
            Memory.WriteVector128(Position + 0x160, Thread.Context.ThreadState.V5);
            Memory.WriteVector128(Position + 0x170, Thread.Context.ThreadState.V6);
            Memory.WriteVector128(Position + 0x180, Thread.Context.ThreadState.V7);
            Memory.WriteVector128(Position + 0x190, Thread.Context.ThreadState.V8);
            Memory.WriteVector128(Position + 0x1a0, Thread.Context.ThreadState.V9);
            Memory.WriteVector128(Position + 0x1b0, Thread.Context.ThreadState.V10);
            Memory.WriteVector128(Position + 0x1c0, Thread.Context.ThreadState.V11);
            Memory.WriteVector128(Position + 0x1d0, Thread.Context.ThreadState.V12);
            Memory.WriteVector128(Position + 0x1e0, Thread.Context.ThreadState.V13);
            Memory.WriteVector128(Position + 0x1f0, Thread.Context.ThreadState.V14);
            Memory.WriteVector128(Position + 0x200, Thread.Context.ThreadState.V15);
            Memory.WriteVector128(Position + 0x210, Thread.Context.ThreadState.V16);
            Memory.WriteVector128(Position + 0x220, Thread.Context.ThreadState.V17);
            Memory.WriteVector128(Position + 0x230, Thread.Context.ThreadState.V18);
            Memory.WriteVector128(Position + 0x240, Thread.Context.ThreadState.V19);
            Memory.WriteVector128(Position + 0x250, Thread.Context.ThreadState.V20);
            Memory.WriteVector128(Position + 0x260, Thread.Context.ThreadState.V21);
            Memory.WriteVector128(Position + 0x270, Thread.Context.ThreadState.V22);
            Memory.WriteVector128(Position + 0x280, Thread.Context.ThreadState.V23);
            Memory.WriteVector128(Position + 0x290, Thread.Context.ThreadState.V24);
            Memory.WriteVector128(Position + 0x2a0, Thread.Context.ThreadState.V25);
            Memory.WriteVector128(Position + 0x2b0, Thread.Context.ThreadState.V26);
            Memory.WriteVector128(Position + 0x2c0, Thread.Context.ThreadState.V27);
            Memory.WriteVector128(Position + 0x2d0, Thread.Context.ThreadState.V28);
            Memory.WriteVector128(Position + 0x2e0, Thread.Context.ThreadState.V29);
            Memory.WriteVector128(Position + 0x2f0, Thread.Context.ThreadState.V30);
            Memory.WriteVector128(Position + 0x300, Thread.Context.ThreadState.V31);

            Memory.WriteInt32(Position + 0x310, Thread.Context.ThreadState.Fpcr);
            Memory.WriteInt32(Position + 0x314, Thread.Context.ThreadState.Fpsr);
            Memory.WriteInt64(Position + 0x318, Thread.Context.ThreadState.Tpidr);

            ThreadState.X0 = 0;
        }
Ejemplo n.º 5
0
        public long WaitFor(KSynchronizationObject[] syncObjs, long timeout, ref int hndIndex)
        {
            long result = MakeError(ErrorModule.Kernel, KernelErr.Timeout);

            _system.CriticalSection.Enter();

            //Check if objects are already signaled before waiting.
            for (int index = 0; index < syncObjs.Length; index++)
            {
                if (!syncObjs[index].IsSignaled())
                {
                    continue;
                }

                hndIndex = index;

                _system.CriticalSection.Leave();

                return(0);
            }

            if (timeout == 0)
            {
                _system.CriticalSection.Leave();

                return(result);
            }

            KThread currentThread = _system.Scheduler.GetCurrentThread();

            if (currentThread.ShallBeTerminated ||
                currentThread.SchedFlags == ThreadSchedState.TerminationPending)
            {
                result = MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating);
            }
            else if (currentThread.SyncCancelled)
            {
                currentThread.SyncCancelled = false;

                result = MakeError(ErrorModule.Kernel, KernelErr.Cancelled);
            }
            else
            {
                LinkedListNode <KThread>[] syncNodes = new LinkedListNode <KThread> [syncObjs.Length];

                for (int index = 0; index < syncObjs.Length; index++)
                {
                    syncNodes[index] = syncObjs[index].AddWaitingThread(currentThread);
                }

                currentThread.WaitingSync   = true;
                currentThread.SignaledObj   = null;
                currentThread.ObjSyncResult = (int)result;

                currentThread.Reschedule(ThreadSchedState.Paused);

                if (timeout > 0)
                {
                    _system.TimeManager.ScheduleFutureInvocation(currentThread, timeout);
                }

                _system.CriticalSection.Leave();

                currentThread.WaitingSync = false;

                if (timeout > 0)
                {
                    _system.TimeManager.UnscheduleFutureInvocation(currentThread);
                }

                _system.CriticalSection.Enter();

                result = (uint)currentThread.ObjSyncResult;

                hndIndex = -1;

                for (int index = 0; index < syncObjs.Length; index++)
                {
                    syncObjs[index].RemoveWaitingThread(syncNodes[index]);

                    if (syncObjs[index] == currentThread.SignaledObj)
                    {
                        hndIndex = index;
                    }
                }
            }

            _system.CriticalSection.Leave();

            return(result);
        }
Ejemplo n.º 6
0
        public long WaitFor(KSynchronizationObject[] SyncObjs, long Timeout, ref int HndIndex)
        {
            long Result = MakeError(ErrorModule.Kernel, KernelErr.Timeout);

            System.CriticalSectionLock.Lock();

            //Check if objects are already signaled before waiting.
            for (int Index = 0; Index < SyncObjs.Length; Index++)
            {
                if (!SyncObjs[Index].IsSignaled())
                {
                    continue;
                }

                HndIndex = Index;

                System.CriticalSectionLock.Unlock();

                return(0);
            }

            if (Timeout == 0)
            {
                System.CriticalSectionLock.Unlock();

                return(Result);
            }

            KThread CurrentThread = System.Scheduler.GetCurrentThread();

            if (CurrentThread.ShallBeTerminated ||
                CurrentThread.SchedFlags == ThreadSchedState.TerminationPending)
            {
                Result = MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating);
            }
            else if (CurrentThread.SyncCancelled)
            {
                CurrentThread.SyncCancelled = false;

                Result = MakeError(ErrorModule.Kernel, KernelErr.Cancelled);
            }
            else
            {
                LinkedListNode <KThread>[] SyncNodes = new LinkedListNode <KThread> [SyncObjs.Length];

                for (int Index = 0; Index < SyncObjs.Length; Index++)
                {
                    SyncNodes[Index] = SyncObjs[Index].AddWaitingThread(CurrentThread);
                }

                CurrentThread.WaitingSync   = true;
                CurrentThread.SignaledObj   = null;
                CurrentThread.ObjSyncResult = (int)Result;

                CurrentThread.Reschedule(ThreadSchedState.Paused);

                if (Timeout >= 1)
                {
                    System.TimeManager.ScheduleFutureInvocation(CurrentThread, Timeout);
                }

                System.CriticalSectionLock.Unlock();

                CurrentThread.WaitingSync = false;

                if (Timeout >= 1)
                {
                    System.TimeManager.UnscheduleFutureInvocation(CurrentThread);
                }

                System.CriticalSectionLock.Lock();

                Result = (uint)CurrentThread.ObjSyncResult;

                HndIndex = -1;

                for (int Index = 0; Index < SyncObjs.Length; Index++)
                {
                    SyncObjs[Index].RemoveWaitingThread(SyncNodes[Index]);

                    if (SyncObjs[Index] == CurrentThread.SignaledObj)
                    {
                        HndIndex = Index;
                    }
                }
            }

            System.CriticalSectionLock.Unlock();

            return(Result);
        }
Ejemplo n.º 7
0
        private KernelResult CreateThread(
            ulong Entrypoint,
            ulong ArgsPtr,
            ulong StackTop,
            int Priority,
            int CpuCore,
            out int Handle)
        {
            Handle = 0;

            KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();

            if (CpuCore == -2)
            {
                CpuCore = CurrentProcess.DefaultCpuCore;
            }

            if ((uint)CpuCore >= KScheduler.CpuCoresCount || !CurrentProcess.IsCpuCoreAllowed(CpuCore))
            {
                return(KernelResult.InvalidCpuCore);
            }

            if ((uint)Priority >= KScheduler.PrioritiesCount || !CurrentProcess.IsPriorityAllowed(Priority))
            {
                return(KernelResult.InvalidPriority);
            }

            long Timeout = KTimeManager.ConvertMillisecondsToNanoseconds(100);

            if (CurrentProcess.ResourceLimit != null &&
                !CurrentProcess.ResourceLimit.Reserve(LimitableResource.Thread, 1, Timeout))
            {
                return(KernelResult.ResLimitExceeded);
            }

            KThread Thread = new KThread(System);

            KernelResult Result = CurrentProcess.InitializeThread(
                Thread,
                Entrypoint,
                ArgsPtr,
                StackTop,
                Priority,
                CpuCore);

            if (Result != KernelResult.Success)
            {
                CurrentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1);

                return(Result);
            }

            Result = Process.HandleTable.GenerateHandle(Thread, out Handle);

            if (Result != KernelResult.Success)
            {
                Thread.Terminate();

                CurrentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1);
            }

            return(Result);
        }
Ejemplo n.º 8
0
        public void ContextSwitch()
        {
            lock (CoreContexts)
            {
                if (MultiCoreScheduling)
                {
                    int SelectedCount = 0;

                    for (int Core = 0; Core < KScheduler.CpuCoresCount; Core++)
                    {
                        KCoreContext CoreContext = CoreContexts[Core];

                        if (CoreContext.ContextSwitchNeeded && (CoreContext.CurrentThread?.Context.IsCurrentThread() ?? false))
                        {
                            CoreContext.ContextSwitch();
                        }

                        if (CoreContext.CurrentThread?.Context.IsCurrentThread() ?? false)
                        {
                            SelectedCount++;
                        }
                    }

                    if (SelectedCount == 0)
                    {
                        CoreManager.GetThread(Thread.CurrentThread).Reset();
                    }
                    else if (SelectedCount == 1)
                    {
                        CoreManager.GetThread(Thread.CurrentThread).Set();
                    }
                    else
                    {
                        throw new InvalidOperationException("Thread scheduled in more than one core!");
                    }
                }
                else
                {
                    KThread CurrentThread = CoreContexts[CurrentCore].CurrentThread;

                    bool HasThreadExecuting = CurrentThread != null;

                    if (HasThreadExecuting)
                    {
                        //If this is not the thread that is currently executing, we need
                        //to request an interrupt to allow safely starting another thread.
                        if (!CurrentThread.Context.IsCurrentThread())
                        {
                            CurrentThread.Context.RequestInterrupt();

                            return;
                        }

                        CoreManager.GetThread(CurrentThread.Context.Work).Reset();
                    }

                    //Advance current core and try picking a thread,
                    //keep advancing if it is null.
                    for (int Core = 0; Core < 4; Core++)
                    {
                        CurrentCore = (CurrentCore + 1) % CpuCoresCount;

                        KCoreContext CoreContext = CoreContexts[CurrentCore];

                        CoreContext.UpdateCurrentThread();

                        if (CoreContext.CurrentThread != null)
                        {
                            CoreContext.CurrentThread.ClearExclusive();

                            CoreManager.GetThread(CoreContext.CurrentThread.Context.Work).Set();

                            CoreContext.CurrentThread.Context.Execute();

                            break;
                        }
                    }

                    //If nothing was running before, then we are on a "external"
                    //HLE thread, we don't need to wait.
                    if (!HasThreadExecuting)
                    {
                        return;
                    }
                }
            }

            CoreManager.GetThread(Thread.CurrentThread).WaitOne();
        }
Ejemplo n.º 9
0
 public void RemoveThread(KThread Thread)
 {
     CoreManager.RemoveThread(Thread.Context.Work);
 }
Ejemplo n.º 10
0
        public void StopThread(KThread Thread)
        {
            Thread.Context.StopExecution();

            CoreManager.GetThread(Thread.Context.Work).Set();
        }
Ejemplo n.º 11
0
 private void UnpauseAndTerminateAllThreadsExcept(KThread Thread)
 {
     //TODO.
 }
Ejemplo n.º 12
0
        public KernelResult Start(int MainThreadPriority, ulong StackSize)
        {
            lock (ProcessLock)
            {
                if (State > ProcessState.CreatedAttached)
                {
                    return(KernelResult.InvalidState);
                }

                if (ResourceLimit != null && !ResourceLimit.Reserve(LimitableResource.Thread, 1))
                {
                    return(KernelResult.ResLimitExceeded);
                }

                KResourceLimit ThreadResourceLimit = ResourceLimit;
                KResourceLimit MemoryResourceLimit = null;

                if (MainThreadStackSize != 0)
                {
                    throw new InvalidOperationException("Trying to start a process with a invalid state!");
                }

                ulong StackSizeRounded = BitUtils.AlignUp(StackSize, KMemoryManager.PageSize);

                ulong NeededSize = StackSizeRounded + ImageSize;

                //Check if the needed size for the code and the stack will fit on the
                //memory usage capacity of this Process. Also check for possible overflow
                //on the above addition.
                if (NeededSize > MemoryUsageCapacity ||
                    NeededSize < StackSizeRounded)
                {
                    ThreadResourceLimit?.Release(LimitableResource.Thread, 1);

                    return(KernelResult.OutOfMemory);
                }

                if (StackSizeRounded != 0 && ResourceLimit != null)
                {
                    MemoryResourceLimit = ResourceLimit;

                    if (!MemoryResourceLimit.Reserve(LimitableResource.Memory, StackSizeRounded))
                    {
                        ThreadResourceLimit?.Release(LimitableResource.Thread, 1);

                        return(KernelResult.ResLimitExceeded);
                    }
                }

                KernelResult Result;

                KThread MainThread = null;

                ulong StackTop = 0;

                void CleanUpForError()
                {
                    MainThread?.Terminate();
                    HandleTable.Destroy();

                    if (MainThreadStackSize != 0)
                    {
                        ulong StackBottom = StackTop - MainThreadStackSize;

                        ulong StackPagesCount = MainThreadStackSize / KMemoryManager.PageSize;

                        MemoryManager.UnmapForKernel(StackBottom, StackPagesCount, MemoryState.Stack);
                    }

                    MemoryResourceLimit?.Release(LimitableResource.Memory, StackSizeRounded);
                    ThreadResourceLimit?.Release(LimitableResource.Thread, 1);
                }

                if (StackSizeRounded != 0)
                {
                    ulong StackPagesCount = StackSizeRounded / KMemoryManager.PageSize;

                    ulong RegionStart = MemoryManager.StackRegionStart;
                    ulong RegionSize  = MemoryManager.StackRegionEnd - RegionStart;

                    ulong RegionPagesCount = RegionSize / KMemoryManager.PageSize;

                    Result = MemoryManager.AllocateOrMapPa(
                        StackPagesCount,
                        KMemoryManager.PageSize,
                        0,
                        false,
                        RegionStart,
                        RegionPagesCount,
                        MemoryState.Stack,
                        MemoryPermission.ReadAndWrite,
                        out ulong StackBottom);

                    if (Result != KernelResult.Success)
                    {
                        CleanUpForError();

                        return(Result);
                    }

                    MainThreadStackSize += StackSizeRounded;

                    StackTop = StackBottom + StackSizeRounded;
                }

                ulong HeapCapacity = MemoryUsageCapacity - MainThreadStackSize - ImageSize;

                Result = MemoryManager.SetHeapCapacity(HeapCapacity);

                if (Result != KernelResult.Success)
                {
                    CleanUpForError();

                    return(Result);
                }

                HandleTable = new KHandleTable(System);

                Result = HandleTable.Initialize(Capabilities.HandleTableSize);

                if (Result != KernelResult.Success)
                {
                    CleanUpForError();

                    return(Result);
                }

                MainThread = new KThread(System);

                Result = MainThread.Initialize(
                    Entrypoint,
                    0,
                    StackTop,
                    MainThreadPriority,
                    DefaultCpuCore,
                    this);

                if (Result != KernelResult.Success)
                {
                    CleanUpForError();

                    return(Result);
                }

                Result = HandleTable.GenerateHandle(MainThread, out int MainThreadHandle);

                if (Result != KernelResult.Success)
                {
                    CleanUpForError();

                    return(Result);
                }

                MainThread.SetEntryArguments(0, MainThreadHandle);

                ProcessState OldState = State;
                ProcessState NewState = State != ProcessState.Created
                    ? ProcessState.Attached
                    : ProcessState.Started;

                SetState(NewState);

                //TODO: We can't call KThread.Start from a non-guest thread.
                //We will need to make some changes to allow the creation of
                //dummy threads that will be used to initialize the current
                //thread on KCoreContext so that GetCurrentThread doesn't fail.

                /* Result = MainThread.Start();
                 *
                 * if (Result != KernelResult.Success)
                 * {
                 *  SetState(OldState);
                 *
                 *  CleanUpForError();
                 * } */

                MainThread.Reschedule(ThreadSchedState.Running);

                return(Result);
            }
        }