public void Resume(KThread Thread) { TryResumingExecution(AllThreads[Thread]); }
public void WakeUp(KThread Thread) { AllThreads[Thread].WaitSync.Set(); }
public void Yield(KThread Thread) { Yield(Thread, Thread.ActualPriority); }
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; }
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); }
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); }
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); }
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(); }
public void RemoveThread(KThread Thread) { CoreManager.RemoveThread(Thread.Context.Work); }
public void StopThread(KThread Thread) { Thread.Context.StopExecution(); CoreManager.GetThread(Thread.Context.Work).Set(); }
private void UnpauseAndTerminateAllThreadsExcept(KThread Thread) { //TODO. }
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); } }