summaryrefslogtreecommitdiffhomepage
path: root/Private/Source/ProcessScheduler.cxx
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2024-05-05 21:10:18 +0200
committerAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2024-05-05 21:10:18 +0200
commitf95d8bf159d10b5a9521dcaa0bc37aa0e9dfc02b (patch)
treebf8186f1a0521a64983bb0bca4f7b54883542195 /Private/Source/ProcessScheduler.cxx
parent5a903c1d8f80ca8d7bc5fbea0aea710ce0133f9d (diff)
MHR-23: Add run_format.sh, kernel patches.
Signed-off-by: Amlal El Mahrouss <amlal.elmahrouss@icloud.com>
Diffstat (limited to 'Private/Source/ProcessScheduler.cxx')
-rw-r--r--Private/Source/ProcessScheduler.cxx620
1 files changed, 342 insertions, 278 deletions
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<ProcessHeader>& 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<ProcessHeader>& 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<HAL::StackFrame*>(
+ 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> ProcessScheduler::Shared()
+ {
+ static ProcessScheduler ref;
+ return {ref};
+ }
+
+ /// @brief Gets current running process.
+ /// @return
+ Ref<ProcessHeader>& 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<ProcessHeader>& 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<Int>(kSchedMinMicroTime))
+ {
+ process.Leak().Status = ProcessStatus::kRunning;
+ process.Leak().Affinity = AffinityKind::kHartStandard;
+
+ return true;
+ }
+
+ ++process.Leak().PTime;
+ }
+
+ return process.Leak().PTime > static_cast<Int>(kSchedMinMicroTime);
+ }
-SizeT ProcessScheduler::Add(Ref<ProcessHeader> &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<ProcessHeader>& 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<HAL::StackFrame *>(
- 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> ProcessScheduler::Shared() {
- static ProcessScheduler ref;
- return {ref};
-}
-
-/// @brief Gets current running process.
-/// @return
-Ref<ProcessHeader> &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<ProcessHeader> &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<Int>(kSchedMinMicroTime)) {
- process.Leak().Status = ProcessStatus::kRunning;
- process.Leak().Affinity = AffinityKind::kHartStandard;
-
- return true;
- }
-
- ++process.Leak().PTime;
- }
-
- return process.Leak().PTime > static_cast<Int>(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