public void TerminateCurrentProcess() { bool shallTerminate = false; KernelContext.CriticalSection.Enter(); lock (_processLock) { if (State >= ProcessState.Started) { if (State == ProcessState.Started || State == ProcessState.Attached || State == ProcessState.DebugSuspended) { SetState(ProcessState.Exiting); shallTerminate = true; } } } KernelContext.CriticalSection.Leave(); if (shallTerminate) { UnpauseAndTerminateAllThreadsExcept(KernelStatic.GetCurrentThread()); HandleTable.Destroy(); // NOTE: this is supposed to be called in receiving of the mailbox. SignalExitToDebugExited(); SignalExit(); } }
public KernelResult Terminate() { KernelResult result; bool shallTerminate = false; System.CriticalSection.Enter(); lock (_processLock) { if (_state >= ProcessState.Started) { if (_state == ProcessState.Started || _state == ProcessState.Crashed || _state == ProcessState.Attached || _state == ProcessState.DebugSuspended) { SetState(ProcessState.Exiting); shallTerminate = true; } result = KernelResult.Success; } else { result = KernelResult.InvalidState; } } System.CriticalSection.Leave(); if (shallTerminate) { // UnpauseAndTerminateAllThreadsExcept(System.Scheduler.GetCurrentThread()); HandleTable.Destroy(); SignalExitForDebugEvent(); SignalExit(); } return(result); }
public KernelResult Terminate() { KernelResult result; bool shallTerminate = false; KernelContext.CriticalSection.Enter(); lock (_processLock) { if (State >= ProcessState.Started) { if (State == ProcessState.Started || State == ProcessState.Crashed || State == ProcessState.Attached || State == ProcessState.DebugSuspended) { SetState(ProcessState.Exiting); shallTerminate = true; } result = KernelResult.Success; } else { result = KernelResult.InvalidState; } } KernelContext.CriticalSection.Leave(); if (shallTerminate) { UnpauseAndTerminateAllThreadsExcept(KernelStatic.GetCurrentThread()); HandleTable.Destroy(); SignalExitToDebugTerminated(); SignalExit(); } return(result); }
private void Unload() { if (Disposed || Threads.Count > 0) { return; } Disposed = true; HandleTable.Destroy(); INvDrvServices.UnloadProcess(this); if (NeedsHbAbi && Executables.Count > 0 && Executables[0].FilePath.EndsWith(Homebrew.TemporaryNroSuffix)) { File.Delete(Executables[0].FilePath); } Logger.PrintInfo(LogClass.Loader, $"Process {ProcessId} exiting..."); }
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() { HandleTable.Destroy(); mainThread?.DecrementReferenceCount(); if (_mainThreadStackSize != 0) { ulong stackBottom = stackTop - _mainThreadStackSize; ulong stackPagesCount = _mainThreadStackSize / KMemoryManager.PageSize; MemoryManager.UnmapForKernel(stackBottom, stackPagesCount, MemoryState.Stack); _mainThreadStackSize = 0; } 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); if (result == KernelResult.Success) { mainThread.IncrementReferenceCount(); } mainThread.DecrementReferenceCount(); return(result); } }
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, KPageTableBase.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() { HandleTable.Destroy(); mainThread?.DecrementReferenceCount(); if (_mainThreadStackSize != 0) { ulong stackBottom = stackTop - _mainThreadStackSize; ulong stackPagesCount = _mainThreadStackSize / KPageTableBase.PageSize; MemoryManager.UnmapForKernel(stackBottom, stackPagesCount, MemoryState.Stack); _mainThreadStackSize = 0; } memoryResourceLimit?.Release(LimitableResource.Memory, stackSizeRounded); threadResourceLimit?.Release(LimitableResource.Thread, 1); } if (stackSizeRounded != 0) { ulong stackPagesCount = stackSizeRounded / KPageTableBase.PageSize; ulong regionStart = MemoryManager.StackRegionStart; ulong regionSize = MemoryManager.StackRegionEnd - regionStart; ulong regionPagesCount = regionSize / KPageTableBase.PageSize; result = MemoryManager.MapPages( stackPagesCount, KPageTableBase.PageSize, 0, false, regionStart, regionPagesCount, MemoryState.Stack, KMemoryPermission.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(KernelContext); result = HandleTable.Initialize(Capabilities.HandleTableSize); if (result != KernelResult.Success) { CleanUpForError(); return(result); } mainThread = new KThread(KernelContext); result = mainThread.Initialize( _entrypoint, 0, stackTop, mainThreadPriority, DefaultCpuCore, this, ThreadType.User, _customThreadStart); 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); result = mainThread.Start(); if (result != KernelResult.Success) { SetState(oldState); CleanUpForError(); } if (result == KernelResult.Success) { mainThread.IncrementReferenceCount(); } mainThread.DecrementReferenceCount(); return(result); } }
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); } }