Esempio n. 1
0
        public static void YieldUntilCompletion(Task task)
        {
            KThread currentThread = Context.Scheduler.GetCurrentThread();

            Context.CriticalSection.Enter();

            currentThread.Reschedule(ThreadSchedState.Paused);

            task.ContinueWith((antecedent) =>
            {
                currentThread.Reschedule(ThreadSchedState.Running);
            });

            Context.CriticalSection.Leave();
        }
Esempio n. 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();
        }
Esempio n. 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();
        }
Esempio n. 4
0
        public long ArbitrateLock(
            Process Process,
            AMemory Memory,
            int OwnerHandle,
            long MutexAddress,
            int RequesterHandle)
        {
            System.CriticalSectionLock.Lock();

            KThread CurrentThread = System.Scheduler.GetCurrentThread();

            CurrentThread.SignaledObj   = null;
            CurrentThread.ObjSyncResult = 0;

            if (!UserToKernelInt32(Memory, MutexAddress, out int MutexValue))
            {
                System.CriticalSectionLock.Unlock();

                return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm));;
            }

            if (MutexValue != (OwnerHandle | HasListenersMask))
            {
                System.CriticalSectionLock.Unlock();

                return(0);
            }

            KThread MutexOwner = Process.HandleTable.GetObject <KThread>(OwnerHandle);

            if (MutexOwner == null)
            {
                System.CriticalSectionLock.Unlock();

                return(MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle));
            }

            CurrentThread.MutexAddress             = MutexAddress;
            CurrentThread.ThreadHandleForUserMutex = RequesterHandle;

            MutexOwner.AddMutexWaiter(CurrentThread);

            CurrentThread.Reschedule(ThreadSchedState.Paused);

            System.CriticalSectionLock.Unlock();
            System.CriticalSectionLock.Lock();

            if (CurrentThread.MutexOwner != null)
            {
                CurrentThread.MutexOwner.RemoveMutexWaiter(CurrentThread);
            }

            System.CriticalSectionLock.Unlock();

            return((uint)CurrentThread.ObjSyncResult);
        }
Esempio n. 5
0
        public static void Wait(Horizon System, LinkedList <KThread> ThreadList, object Mutex, long Timeout)
        {
            KThread CurrentThread = System.Scheduler.GetCurrentThread();

            System.CriticalSection.Enter();

            Monitor.Exit(Mutex);

            CurrentThread.Withholder = ThreadList;

            CurrentThread.Reschedule(ThreadSchedState.Paused);

            CurrentThread.WithholderNode = ThreadList.AddLast(CurrentThread);

            if (CurrentThread.ShallBeTerminated ||
                CurrentThread.SchedFlags == ThreadSchedState.TerminationPending)
            {
                ThreadList.Remove(CurrentThread.WithholderNode);

                CurrentThread.Reschedule(ThreadSchedState.Running);

                CurrentThread.Withholder = null;

                System.CriticalSection.Leave();
            }
            else
            {
                if (Timeout > 0)
                {
                    System.TimeManager.ScheduleFutureInvocation(CurrentThread, Timeout);
                }

                System.CriticalSection.Leave();

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

            Monitor.Enter(Mutex);
        }
Esempio n. 6
0
        public static void Wait(Horizon system, LinkedList <KThread> threadList, object mutex, long timeout)
        {
            KThread currentThread = system.Scheduler.GetCurrentThread();

            system.CriticalSection.Enter();

            Monitor.Exit(mutex);

            currentThread.Withholder = threadList;

            currentThread.Reschedule(ThreadSchedState.Paused);

            currentThread.WithholderNode = threadList.AddLast(currentThread);

            if (currentThread.ShallBeTerminated ||
                currentThread.SchedFlags == ThreadSchedState.TerminationPending)
            {
                threadList.Remove(currentThread.WithholderNode);

                currentThread.Reschedule(ThreadSchedState.Running);

                currentThread.Withholder = null;

                system.CriticalSection.Leave();
            }
            else
            {
                if (timeout > 0)
                {
                    system.TimeManager.ScheduleFutureInvocation(currentThread, timeout);
                }

                system.CriticalSection.Leave();

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

            Monitor.Enter(mutex);
        }
Esempio n. 7
0
        public long ArbitrateLock(int ownerHandle, long mutexAddress, int requesterHandle)
        {
            KThread currentThread = _system.Scheduler.GetCurrentThread();

            _system.CriticalSection.Enter();

            currentThread.SignaledObj   = null;
            currentThread.ObjSyncResult = 0;

            KProcess currentProcess = _system.Scheduler.GetCurrentProcess();

            if (!KernelTransfer.UserToKernelInt32(_system, mutexAddress, out int mutexValue))
            {
                _system.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm));
            }

            if (mutexValue != (ownerHandle | HasListenersMask))
            {
                _system.CriticalSection.Leave();

                return(0);
            }

            KThread mutexOwner = currentProcess.HandleTable.GetObject <KThread>(ownerHandle);

            if (mutexOwner == null)
            {
                _system.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle));
            }

            currentThread.MutexAddress             = mutexAddress;
            currentThread.ThreadHandleForUserMutex = requesterHandle;

            mutexOwner.AddMutexWaiter(currentThread);

            currentThread.Reschedule(ThreadSchedState.Paused);

            _system.CriticalSection.Leave();
            _system.CriticalSection.Enter();

            if (currentThread.MutexOwner != null)
            {
                currentThread.MutexOwner.RemoveMutexWaiter(currentThread);
            }

            _system.CriticalSection.Leave();

            return((uint)currentThread.ObjSyncResult);
        }
Esempio n. 8
0
        public static void NotifyAll(Horizon System, LinkedList <KThread> ThreadList)
        {
            System.CriticalSection.Enter();

            LinkedListNode <KThread> Node = ThreadList.First;

            for (; Node != null; Node = ThreadList.First)
            {
                KThread Thread = Node.Value;

                ThreadList.Remove(Thread.WithholderNode);

                Thread.Withholder = null;

                Thread.Reschedule(ThreadSchedState.Running);
            }

            System.CriticalSection.Leave();
        }
Esempio n. 9
0
        public static void NotifyAll(Horizon system, LinkedList <KThread> threadList)
        {
            system.CriticalSection.Enter();

            LinkedListNode <KThread> node = threadList.First;

            for (; node != null; node = threadList.First)
            {
                KThread thread = node.Value;

                threadList.Remove(thread.WithholderNode);

                thread.Withholder = null;

                thread.Reschedule(ThreadSchedState.Running);
            }

            system.CriticalSection.Leave();
        }
Esempio n. 10
0
        private void SendSyncRequest(AThreadState ThreadState, long MessagePtr, long Size, int Handle)
        {
            KThread CurrThread = Process.GetThread(ThreadState.Tpidr);

            byte[] MessageData = Memory.ReadBytes(MessagePtr, Size);

            KSession Session = Process.HandleTable.GetObject <KSession>(Handle);

            if (Session != null)
            {
                //Process.Scheduler.Suspend(CurrThread);

                System.CriticalSectionLock.Lock();

                KThread CurrentThread = System.Scheduler.GetCurrentThread();

                CurrentThread.SignaledObj   = null;
                CurrentThread.ObjSyncResult = 0;

                CurrentThread.Reschedule(ThreadSchedState.Paused);

                IpcMessage Message = new IpcMessage(MessageData, MessagePtr);

                ThreadPool.QueueUserWorkItem(ProcessIpcRequest, new HleIpcMessage(
                                                 CurrentThread,
                                                 Session,
                                                 Message,
                                                 MessagePtr));

                System.CriticalSectionLock.Unlock();

                ThreadState.X0 = (ulong)CurrentThread.ObjSyncResult;
            }
            else
            {
                Device.Log.PrintWarning(LogClass.KernelSvc, $"Invalid session handle 0x{Handle:x8}!");

                ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
            }
        }
Esempio n. 11
0
        private void SendSyncRequest(CpuThreadState threadState, long messagePtr, long size, int handle)
        {
            byte[] messageData = _memory.ReadBytes(messagePtr, size);

            KSession session = _process.HandleTable.GetObject <KSession>(handle);

            if (session != null)
            {
                _system.CriticalSection.Enter();

                KThread currentThread = _system.Scheduler.GetCurrentThread();

                currentThread.SignaledObj   = null;
                currentThread.ObjSyncResult = 0;

                currentThread.Reschedule(ThreadSchedState.Paused);

                IpcMessage message = new IpcMessage(messageData, messagePtr);

                ThreadPool.QueueUserWorkItem(ProcessIpcRequest, new HleIpcMessage(
                                                 currentThread,
                                                 session,
                                                 message,
                                                 messagePtr));

                _system.ThreadCounter.AddCount();

                _system.CriticalSection.Leave();

                threadState.X0 = (ulong)currentThread.ObjSyncResult;
            }
            else
            {
                Logger.PrintWarning(LogClass.KernelSvc, $"Invalid session handle 0x{handle:x8}!");

                threadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
            }
        }
Esempio n. 12
0
        public long WaitProcessWideKeyAtomic(
            long MutexAddress,
            long CondVarAddress,
            int ThreadHandle,
            long Timeout)
        {
            System.CriticalSection.Enter();

            KThread CurrentThread = System.Scheduler.GetCurrentThread();

            CurrentThread.SignaledObj   = null;
            CurrentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout);

            if (CurrentThread.ShallBeTerminated ||
                CurrentThread.SchedFlags == ThreadSchedState.TerminationPending)
            {
                System.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating));
            }

            (long Result, _) = MutexUnlock(CurrentThread, MutexAddress);

            if (Result != 0)
            {
                System.CriticalSection.Leave();

                return(Result);
            }

            CurrentThread.MutexAddress             = MutexAddress;
            CurrentThread.ThreadHandleForUserMutex = ThreadHandle;
            CurrentThread.CondVarAddress           = CondVarAddress;

            CondVarThreads.Add(CurrentThread);

            if (Timeout != 0)
            {
                CurrentThread.Reschedule(ThreadSchedState.Paused);

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

            System.CriticalSection.Leave();

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

            System.CriticalSection.Enter();

            if (CurrentThread.MutexOwner != null)
            {
                CurrentThread.MutexOwner.RemoveMutexWaiter(CurrentThread);
            }

            CondVarThreads.Remove(CurrentThread);

            System.CriticalSection.Leave();

            return((uint)CurrentThread.ObjSyncResult);
        }
Esempio n. 13
0
        public long WaitForAddressIfLessThan(long Address, int Value, bool ShouldDecrement, long Timeout)
        {
            KThread CurrentThread = System.Scheduler.GetCurrentThread();

            System.CriticalSection.Enter();

            if (CurrentThread.ShallBeTerminated ||
                CurrentThread.SchedFlags == ThreadSchedState.TerminationPending)
            {
                System.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating));
            }

            CurrentThread.SignaledObj   = null;
            CurrentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout);

            KProcess CurrentProcess = System.Scheduler.GetCurrentProcess();

            //If ShouldDecrement is true, do atomic decrement of the value at Address.
            CurrentProcess.CpuMemory.SetExclusive(0, Address);

            if (!KernelTransfer.UserToKernelInt32(System, Address, out int CurrentValue))
            {
                System.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm));
            }

            if (ShouldDecrement)
            {
                while (CurrentValue < Value)
                {
                    if (CurrentProcess.CpuMemory.TestExclusive(0, Address))
                    {
                        CurrentProcess.CpuMemory.WriteInt32(Address, CurrentValue - 1);

                        CurrentProcess.CpuMemory.ClearExclusiveForStore(0);

                        break;
                    }

                    CurrentProcess.CpuMemory.SetExclusive(0, Address);

                    CurrentValue = CurrentProcess.CpuMemory.ReadInt32(Address);
                }
            }

            CurrentProcess.CpuMemory.ClearExclusive(0);

            if (CurrentValue < Value)
            {
                if (Timeout == 0)
                {
                    System.CriticalSection.Leave();

                    return(MakeError(ErrorModule.Kernel, KernelErr.Timeout));
                }

                CurrentThread.MutexAddress         = Address;
                CurrentThread.WaitingInArbitration = true;

                InsertSortedByPriority(ArbiterThreads, CurrentThread);

                CurrentThread.Reschedule(ThreadSchedState.Paused);

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

                System.CriticalSection.Leave();

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

                System.CriticalSection.Enter();

                if (CurrentThread.WaitingInArbitration)
                {
                    ArbiterThreads.Remove(CurrentThread);

                    CurrentThread.WaitingInArbitration = false;
                }

                System.CriticalSection.Leave();

                return(CurrentThread.ObjSyncResult);
            }

            System.CriticalSection.Leave();

            return(MakeError(ErrorModule.Kernel, KernelErr.InvalidState));
        }
Esempio n. 14
0
        public long WaitForAddressIfEqual(long Address, int Value, long Timeout)
        {
            KThread CurrentThread = System.Scheduler.GetCurrentThread();

            System.CriticalSection.Enter();

            if (CurrentThread.ShallBeTerminated ||
                CurrentThread.SchedFlags == ThreadSchedState.TerminationPending)
            {
                System.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating));
            }

            CurrentThread.SignaledObj   = null;
            CurrentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout);

            if (!KernelTransfer.UserToKernelInt32(System, Address, out int CurrentValue))
            {
                System.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm));
            }

            if (CurrentValue == Value)
            {
                if (Timeout == 0)
                {
                    System.CriticalSection.Leave();

                    return(MakeError(ErrorModule.Kernel, KernelErr.Timeout));
                }

                CurrentThread.MutexAddress         = Address;
                CurrentThread.WaitingInArbitration = true;

                InsertSortedByPriority(ArbiterThreads, CurrentThread);

                CurrentThread.Reschedule(ThreadSchedState.Paused);

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

                System.CriticalSection.Leave();

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

                System.CriticalSection.Enter();

                if (CurrentThread.WaitingInArbitration)
                {
                    ArbiterThreads.Remove(CurrentThread);

                    CurrentThread.WaitingInArbitration = false;
                }

                System.CriticalSection.Leave();

                return(CurrentThread.ObjSyncResult);
            }

            System.CriticalSection.Leave();

            return(MakeError(ErrorModule.Kernel, KernelErr.InvalidState));
        }
Esempio n. 15
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);
        }
Esempio n. 16
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);
        }
Esempio n. 17
0
        public long WaitProcessWideKeyAtomic(
            long mutexAddress,
            long condVarAddress,
            int threadHandle,
            long timeout)
        {
            _system.CriticalSection.Enter();

            KThread currentThread = _system.Scheduler.GetCurrentThread();

            currentThread.SignaledObj   = null;
            currentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout);

            if (currentThread.ShallBeTerminated ||
                currentThread.SchedFlags == ThreadSchedState.TerminationPending)
            {
                _system.CriticalSection.Leave();

                return(MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating));
            }

            (long result, _) = MutexUnlock(currentThread, mutexAddress);

            if (result != 0)
            {
                _system.CriticalSection.Leave();

                return(result);
            }

            currentThread.MutexAddress             = mutexAddress;
            currentThread.ThreadHandleForUserMutex = threadHandle;
            currentThread.CondVarAddress           = condVarAddress;

            CondVarThreads.Add(currentThread);

            if (timeout != 0)
            {
                currentThread.Reschedule(ThreadSchedState.Paused);

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

            _system.CriticalSection.Leave();

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

            _system.CriticalSection.Enter();

            if (currentThread.MutexOwner != null)
            {
                currentThread.MutexOwner.RemoveMutexWaiter(currentThread);
            }

            CondVarThreads.Remove(currentThread);

            _system.CriticalSection.Leave();

            return((uint)currentThread.ObjSyncResult);
        }
Esempio n. 18
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);
            }
        }