From f95d8bf159d10b5a9521dcaa0bc37aa0e9dfc02b Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Sun, 5 May 2024 21:10:18 +0200 Subject: MHR-23: Add run_format.sh, kernel patches. Signed-off-by: Amlal El Mahrouss --- Private/Source/ProcessScheduler.cxx | 620 ++++++++++++++++++++---------------- 1 file changed, 342 insertions(+), 278 deletions(-) (limited to 'Private/Source/ProcessScheduler.cxx') diff --git a/Private/Source/ProcessScheduler.cxx b/Private/Source/ProcessScheduler.cxx index 22222f9e..e82f8362 100644 --- a/Private/Source/ProcessScheduler.cxx +++ b/Private/Source/ProcessScheduler.cxx @@ -21,308 +21,372 @@ /* This file handles the process scheduling. /***********************************************************************************/ -namespace NewOS { -/***********************************************************************************/ -/// @brief Exit Code global -/***********************************************************************************/ - -STATIC Int32 kLastExitCode = 0U; - -/// @brief Gets the latest exit code. -/// @note Not thread-safe. -const Int32 &rt_get_exit_code() noexcept { return kLastExitCode; } - -/***********************************************************************************/ -/// @brief crash current process. -/***********************************************************************************/ - -void ProcessHeader::Crash() { - kcout << this->Name << ": crashed. (id = " << number(39); - kcout << ")\r"; - - if (this->Ring != kRingUserKind) { - MUST_PASS(ke_bug_check()); - } - - this->Exit(kErrorProcessFault); -} - -void ProcessHeader::Wake(const bool should_wakeup) { - this->Status = - should_wakeup ? ProcessStatus::kRunning : ProcessStatus::kFrozen; -} - -/***********************************************************************************/ - -VoidPtr ProcessHeader::New(const SizeT &sz) { - if (this->FreeMemory < 1) { - DbgLastError() = kErrorHeapOutOfMemory; - this->Crash(); /// out of memory. - - return nullptr; - } - - if (this->HeapCursor) { - VoidPtr ptr = this->HeapCursor; - this->HeapCursor = (VoidPtr)((UIntPtr)this->HeapCursor + (sizeof(sz))); - - ++this->UsedMemory; - --this->FreeMemory; - - return ptr; - } - - return nullptr; -} +namespace NewOS +{ + /***********************************************************************************/ + /// @brief Exit Code global + /***********************************************************************************/ + + STATIC Int32 kLastExitCode = 0U; + + /// @brief Gets the latest exit code. + /// @note Not thread-safe. + const Int32& rt_get_exit_code() noexcept + { + return kLastExitCode; + } + + /***********************************************************************************/ + /// @brief crash current process. + /***********************************************************************************/ + + void ProcessHeader::Crash() + { + kcout << this->Name << ": crashed. (id = " << number(39); + kcout << ")\r"; + + if (this->Ring != kRingUserKind) + { + MUST_PASS(ke_bug_check()); + } + + this->Exit(kErrorProcessFault); + } + + void ProcessHeader::Wake(const bool should_wakeup) + { + this->Status = + should_wakeup ? ProcessStatus::kRunning : ProcessStatus::kFrozen; + } + + /***********************************************************************************/ + + VoidPtr ProcessHeader::New(const SizeT& sz) + { + if (this->FreeMemory < 1) + { + DbgLastError() = kErrorHeapOutOfMemory; + this->Crash(); /// out of memory. + + return nullptr; + } + + if (this->HeapCursor) + { + VoidPtr ptr = this->HeapCursor; + this->HeapCursor = (VoidPtr)((UIntPtr)this->HeapCursor + (sizeof(sz))); + + ++this->UsedMemory; + --this->FreeMemory; + + return ptr; + } + + return nullptr; + } + + /***********************************************************************************/ + + /* @brief checks if runtime pointer is in region. */ + bool rt_is_in_pool(VoidPtr pool_ptr, VoidPtr pool, const SizeT& sz) + { + UIntPtr* _pool_ptr = (UIntPtr*)pool_ptr; + UIntPtr* _pool = (UIntPtr*)pool; + + for (SizeT index = sz; _pool[sz] != kUserHeapMag; --index) + { + if (&_pool[index] > &_pool_ptr[sz]) + continue; + + if (_pool[index] == _pool_ptr[index]) + return true; + } + + return false; + } + + /* @brief free pointer from usage. */ + Boolean ProcessHeader::Delete(VoidPtr ptr, const SizeT& sz) + { + if (sz < 1 || this->HeapCursor == this->HeapPtr) + return false; + + // also check for the amount of allocations we've done so far. + if (this->UsedMemory < 1) + return false; + + if (rt_is_in_pool(ptr, this->HeapCursor, this->UsedMemory)) + { + this->HeapCursor = (VoidPtr)((UIntPtr)this->HeapCursor - (sizeof(sz))); + rt_zero_memory(ptr, sz); + + ++this->FreeMemory; + --this->UsedMemory; + + return true; + } + + return false; + } + + /// @brief process name getter. + const Char* ProcessHeader::GetName() + { + return this->Name; + } + + /// @brief process selector getter. + const ProcessSelector& ProcessHeader::GetSelector() + { + return this->Selector; + } + + /// @brief process status getter. + const ProcessStatus& ProcessHeader::GetStatus() + { + return this->Status; + } + + /***********************************************************************************/ -/***********************************************************************************/ - -/* @brief checks if runtime pointer is in region. */ -bool rt_is_in_pool(VoidPtr pool_ptr, VoidPtr pool, const SizeT &sz) { - UIntPtr *_pool_ptr = (UIntPtr *)pool_ptr; - UIntPtr *_pool = (UIntPtr *)pool; - - for (SizeT index = sz; _pool[sz] != kUserHeapMag; --index) { - if (&_pool[index] > &_pool_ptr[sz]) continue; - - if (_pool[index] == _pool_ptr[index]) return true; - } - - return false; -} - -/* @brief free pointer from usage. */ -Boolean ProcessHeader::Delete(VoidPtr ptr, const SizeT &sz) { - if (sz < 1 || this->HeapCursor == this->HeapPtr) return false; - - // also check for the amount of allocations we've done so far. - if (this->UsedMemory < 1) return false; - - if (rt_is_in_pool(ptr, this->HeapCursor, this->UsedMemory)) { - this->HeapCursor = (VoidPtr)((UIntPtr)this->HeapCursor - (sizeof(sz))); - rt_zero_memory(ptr, sz); - - ++this->FreeMemory; - --this->UsedMemory; - - return true; - } - - return false; -} - -/// @brief process name getter. -const Char *ProcessHeader::GetName() { return this->Name; } - -/// @brief process selector getter. -const ProcessSelector &ProcessHeader::GetSelector() { return this->Selector; } - -/// @brief process status getter. -const ProcessStatus &ProcessHeader::GetStatus() { return this->Status; } - -/***********************************************************************************/ - -/** + /** @brief Affinity is the time slot allowed for the process. */ -const AffinityKind &ProcessHeader::GetAffinity() { return this->Affinity; } + const AffinityKind& ProcessHeader::GetAffinity() + { + return this->Affinity; + } -/** + /** @brief Standard exit proc. */ -void ProcessHeader::Exit(Int32 exit_code) { - if (this->ProcessId != - ProcessScheduler::Shared().Leak().GetCurrent().Leak().ProcessId) - ke_stop(RUNTIME_CHECK_PROCESS); - - if (this->Ring == (Int32)ProcessSelector::kRingKernel && - ProcessScheduler::Shared().Leak().GetCurrent().Leak().Ring > 0) - ke_stop(RUNTIME_CHECK_PROCESS); + void ProcessHeader::Exit(Int32 exit_code) + { + if (this->ProcessId != + ProcessScheduler::Shared().Leak().GetCurrent().Leak().ProcessId) + ke_stop(RUNTIME_CHECK_PROCESS); - kLastExitCode = exit_code; + if (this->Ring == (Int32)ProcessSelector::kRingKernel && + ProcessScheduler::Shared().Leak().GetCurrent().Leak().Ring > 0) + ke_stop(RUNTIME_CHECK_PROCESS); - if (this->Ring != (Int32)ProcessSelector::kRingDriver) { - if (this->HeapPtr) rt_free_heap(this->HeapPtr); + kLastExitCode = exit_code; - this->HeapPtr = nullptr; - this->HeapCursor = nullptr; + if (this->Ring != (Int32)ProcessSelector::kRingDriver) + { + if (this->HeapPtr) + rt_free_heap(this->HeapPtr); - this->FreeMemory = 0UL; - this->UsedMemory = 0UL; - } + this->HeapPtr = nullptr; + this->HeapCursor = nullptr; + + this->FreeMemory = 0UL; + this->UsedMemory = 0UL; + } - //! Delete image if not done already. - if (this->Image) ke_delete_ke_heap(this->Image); - if (this->StackFrame) ke_delete_ke_heap((VoidPtr)this->StackFrame); + //! Delete image if not done already. + if (this->Image) + ke_delete_ke_heap(this->Image); + if (this->StackFrame) + ke_delete_ke_heap((VoidPtr)this->StackFrame); - this->Image = nullptr; - this->StackFrame = nullptr; + this->Image = nullptr; + this->StackFrame = nullptr; + + ProcessScheduler::Shared().Leak().Remove(this->ProcessId); + } + + SizeT ProcessScheduler::Add(Ref& process) + { + if (!process) + return -1; + + if (!process.Leak().Image) + { + if (process.Leak().Kind != ProcessHeader::kLibKind) + { + return -kErrorNoEntrypoint; + } + } + + if (!mTeam.AsArray().Count() > kSchedProcessLimitPerTeam) + return -kErrorOutOfTeamSlot; + + if (process.Leak().Ring != (Int32)ProcessSelector::kRingKernel) + return -1; + + kcout << "ProcessScheduler::Add(Ref& process)\r"; + + /// Create heap according to type of process. + if (process.Leak().Kind == ProcessHeader::kUserKind) + process.Leak().HeapPtr = rt_new_heap(kUserHeapUser | kUserHeapRw); + else if (process.Leak().Kind == ProcessHeader::kLibKind) + process.Leak().HeapPtr = rt_new_heap(kUserHeapUser | kUserHeapRw | kUserHeapShared); + else + process.Leak().HeapPtr = rt_new_heap(kUserHeapDriver | kUserHeapRw); + + process.Leak().StackFrame = reinterpret_cast( + ke_new_ke_heap(sizeof(HAL::StackFrame), true, false)); + + MUST_PASS(process.Leak().StackFrame); + + mTeam.AsArray().Add(process); + + process.Leak().ProcessId = mTeam.AsArray().Count() - 1; + process.Leak().HeapCursor = process.Leak().HeapPtr; + + return mTeam.AsArray().Count() - 1; + } + + bool ProcessScheduler::Remove(SizeT process) + { + if (process > mTeam.AsArray().Count()) + return false; + + kcout << "ProcessScheduler::Remove(SizeT process)\r"; + + return mTeam.AsArray().Remove(process); + } + + SizeT ProcessScheduler::Run() noexcept + { + SizeT processIndex = 0; //! we store this guy to tell the scheduler how many + //! things we have scheduled. + + for (; processIndex < mTeam.AsArray().Count(); ++processIndex) + { + auto process = mTeam.AsArray()[processIndex]; + + MUST_PASS(process); //! no need for a MUST_PASS(process.Leak());, it is + //! recursive because of the nature of the class; + + //! run any process needed to be scheduled. + if (ProcessHelper::CanBeScheduled(process.Leak())) + { + auto unwrapped_process = *process.Leak(); + + unwrapped_process.PTime = 0; + + // set the current process. + mTeam.AsRef() = unwrapped_process; + + // tell helper to find a core to schedule on. + ProcessHelper::Switch(mTeam.AsRef().Leak().StackFrame, + mTeam.AsRef().Leak().ProcessId); + } + else + { + // otherwise increment the P-time. + ++mTeam.AsRef().Leak().PTime; + } + } + + return processIndex; + } + + Ref ProcessScheduler::Shared() + { + static ProcessScheduler ref; + return {ref}; + } + + /// @brief Gets current running process. + /// @return + Ref& ProcessScheduler::GetCurrent() + { + return mTeam.AsRef(); + } + + PID& ProcessHelper::GetCurrentPID() + { + kcout << "ProcessHelper::GetCurrentPID: Leaking ProcessId...\r"; + return ProcessScheduler::Shared().Leak().GetCurrent().Leak().ProcessId; + } + + bool ProcessHelper::CanBeScheduled(Ref& process) + { + if (process.Leak().Status == ProcessStatus::kFrozen || + process.Leak().Status == ProcessStatus::kDead) + return false; - ProcessScheduler::Shared().Leak().Remove(this->ProcessId); -} + if (process.Leak().GetStatus() == ProcessStatus::kStarting) + { + if (process.Leak().PTime < static_cast(kSchedMinMicroTime)) + { + process.Leak().Status = ProcessStatus::kRunning; + process.Leak().Affinity = AffinityKind::kHartStandard; + + return true; + } + + ++process.Leak().PTime; + } + + return process.Leak().PTime > static_cast(kSchedMinMicroTime); + } -SizeT ProcessScheduler::Add(Ref &process) { - if (!process) return -1; - - if (!process.Leak().Image) { - if (process.Leak().Kind != ProcessHeader::kLibKind) { - return -kErrorNoEntrypoint; - } - } - - if (!mTeam.AsArray().Count() > kSchedProcessLimitPerTeam) return -kErrorOutOfTeamSlot; - - if (process.Leak().Ring != (Int32)ProcessSelector::kRingKernel) return -1; - - kcout << "ProcessScheduler::Add(Ref& process)\r"; - - /// Create heap according to type of process. - if (process.Leak().Kind == ProcessHeader::kUserKind) - process.Leak().HeapPtr = rt_new_heap(kUserHeapUser | kUserHeapRw); - else if (process.Leak().Kind == ProcessHeader::kLibKind) - process.Leak().HeapPtr = rt_new_heap(kUserHeapUser | kUserHeapRw | kUserHeapShared); - else - process.Leak().HeapPtr = rt_new_heap(kUserHeapDriver | kUserHeapRw); - - process.Leak().StackFrame = reinterpret_cast( - ke_new_ke_heap(sizeof(HAL::StackFrame), true, false)); - - MUST_PASS(process.Leak().StackFrame); - - mTeam.AsArray().Add(process); - - process.Leak().ProcessId = mTeam.AsArray().Count() - 1; - process.Leak().HeapCursor = process.Leak().HeapPtr; - - return mTeam.AsArray().Count() - 1; -} - -bool ProcessScheduler::Remove(SizeT process) { - if (process > mTeam.AsArray().Count()) return false; - - kcout << "ProcessScheduler::Remove(SizeT process)\r"; - - return mTeam.AsArray().Remove(process); -} - -SizeT ProcessScheduler::Run() noexcept { - SizeT processIndex = 0; //! we store this guy to tell the scheduler how many - //! things we have scheduled. - - for (; processIndex < mTeam.AsArray().Count(); ++processIndex) { - auto process = mTeam.AsArray()[processIndex]; - - MUST_PASS(process); //! no need for a MUST_PASS(process.Leak());, it is - //! recursive because of the nature of the class; - - //! run any process needed to be scheduled. - if (ProcessHelper::CanBeScheduled(process.Leak())) { - auto unwrapped_process = *process.Leak(); - - unwrapped_process.PTime = 0; - - // set the current process. - mTeam.AsRef() = unwrapped_process; - - // tell helper to find a core to schedule on. - ProcessHelper::Switch(mTeam.AsRef().Leak().StackFrame, - mTeam.AsRef().Leak().ProcessId); - } else { - // otherwise increment the P-time. - ++mTeam.AsRef().Leak().PTime; - } - } - - return processIndex; -} - -Ref ProcessScheduler::Shared() { - static ProcessScheduler ref; - return {ref}; -} - -/// @brief Gets current running process. -/// @return -Ref &ProcessScheduler::GetCurrent() { return mTeam.AsRef(); } - -PID &ProcessHelper::GetCurrentPID() { - kcout << "ProcessHelper::GetCurrentPID: Leaking ProcessId...\r"; - return ProcessScheduler::Shared().Leak().GetCurrent().Leak().ProcessId; -} - -bool ProcessHelper::CanBeScheduled(Ref &process) { - if (process.Leak().Status == ProcessStatus::kFrozen || - process.Leak().Status == ProcessStatus::kDead) - return false; - - if (process.Leak().GetStatus() == ProcessStatus::kStarting) { - if (process.Leak().PTime < static_cast(kSchedMinMicroTime)) { - process.Leak().Status = ProcessStatus::kRunning; - process.Leak().Affinity = AffinityKind::kHartStandard; - - return true; - } - - ++process.Leak().PTime; - } - - return process.Leak().PTime > static_cast(kSchedMinMicroTime); -} - -/** + /** * @brief Spin scheduler class. */ -bool ProcessHelper::StartScheduling() { - if (ProcessHelper::CanBeScheduled( - ProcessScheduler::Shared().Leak().GetCurrent())) { - --ProcessScheduler::Shared().Leak().GetCurrent().Leak().PTime; - return false; - } + bool ProcessHelper::StartScheduling() + { + if (ProcessHelper::CanBeScheduled( + ProcessScheduler::Shared().Leak().GetCurrent())) + { + --ProcessScheduler::Shared().Leak().GetCurrent().Leak().PTime; + return false; + } - auto processRef = ProcessScheduler::Shared().Leak(); + auto processRef = ProcessScheduler::Shared().Leak(); - if (!processRef) - return false; // we have nothing to schedule. simply return. + if (!processRef) + return false; // we have nothing to schedule. simply return. - SizeT ret = processRef.Run(); + SizeT ret = processRef.Run(); - kcout << StringBuilder::FromInt( - "ProcessHelper::StartScheduling() Iterated over {%} jobs inside team.\r", ret); + kcout << StringBuilder::FromInt( + "ProcessHelper::StartScheduling() Iterated over {%} jobs inside team.\r", ret); - return true; -} + return true; + } -/** + /** * \brief Does a context switch in a CPU. * \param the_stack the stackframe of the running app. * \param new_pid the process's PID. */ -bool ProcessHelper::Switch(HAL::StackFrame *the_stack, const PID &new_pid) { - if (!the_stack || new_pid < 0) return false; - - for (SizeT index = 0UL; index < SMPManager::Shared().Leak().Count(); ++index) { - if (SMPManager::Shared().Leak()[index].Leak().Kind() == kInvalidHart) - continue; - - if (SMPManager::Shared().Leak()[index].Leak().StackFrame() == the_stack) { - SMPManager::Shared().Leak()[index].Leak().Busy(false); - continue; - } - - if (SMPManager::Shared().Leak()[index].Leak().IsBusy()) continue; - - if (SMPManager::Shared().Leak()[index].Leak().Kind() != - ThreadKind::kHartBoot && - SMPManager::Shared().Leak()[index].Leak().Kind() != - ThreadKind::kHartSystemReserved) { - SMPManager::Shared().Leak()[index].Leak().Busy(true); - ProcessHelper::GetCurrentPID() = new_pid; - - return SMPManager::Shared().Leak()[index].Leak().Switch(the_stack); - } - } - - return false; -} -} // namespace NewOS + bool ProcessHelper::Switch(HAL::StackFrame* the_stack, const PID& new_pid) + { + if (!the_stack || new_pid < 0) + return false; + + for (SizeT index = 0UL; index < SMPManager::Shared().Leak().Count(); ++index) + { + if (SMPManager::Shared().Leak()[index].Leak().Kind() == kInvalidHart) + continue; + + if (SMPManager::Shared().Leak()[index].Leak().StackFrame() == the_stack) + { + SMPManager::Shared().Leak()[index].Leak().Busy(false); + continue; + } + + if (SMPManager::Shared().Leak()[index].Leak().IsBusy()) + continue; + + if (SMPManager::Shared().Leak()[index].Leak().Kind() != + ThreadKind::kHartBoot && + SMPManager::Shared().Leak()[index].Leak().Kind() != + ThreadKind::kHartSystemReserved) + { + SMPManager::Shared().Leak()[index].Leak().Busy(true); + ProcessHelper::GetCurrentPID() = new_pid; + + return SMPManager::Shared().Leak()[index].Leak().Switch(the_stack); + } + } + + return false; + } +} // namespace NewOS -- cgit v1.2.3