From 60902ec5fc462128d264f63f279c7fc362a72e1d Mon Sep 17 00:00:00 2001 From: Amlal EL Mahrouss Date: Mon, 29 Jul 2024 14:51:58 +0200 Subject: [IMP] Replace SMP manager with Multi Processing manager. Signed-off-by: Amlal EL Mahrouss --- Kernel/KernelKit/MPManager.hpp | 126 ++++++++++++++++++ Kernel/KernelKit/SMPManager.hpp | 126 ------------------ Kernel/Sources/MPManager.cxx | 256 ++++++++++++++++++++++++++++++++++++ Kernel/Sources/ProcessScheduler.cxx | 20 +-- Kernel/Sources/SMPManager.cxx | 256 ------------------------------------ 5 files changed, 392 insertions(+), 392 deletions(-) create mode 100644 Kernel/KernelKit/MPManager.hpp delete mode 100644 Kernel/KernelKit/SMPManager.hpp create mode 100644 Kernel/Sources/MPManager.cxx delete mode 100644 Kernel/Sources/SMPManager.cxx diff --git a/Kernel/KernelKit/MPManager.hpp b/Kernel/KernelKit/MPManager.hpp new file mode 100644 index 00000000..6f23dd66 --- /dev/null +++ b/Kernel/KernelKit/MPManager.hpp @@ -0,0 +1,126 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#ifndef __INC_MP_MANAGER_HPP__ +#define __INC_MP_MANAGER_HPP__ + +#include +#include +#include + +/// @note Last Rev Sun 28 Jul CET 2024 + +#define kMaxHarts 8 + +namespace Kernel +{ + using ThreadID = UInt32; + + enum ThreadKind + { + kHartSystemReserved, // System reserved thread, well user can't use it + kHartStandard, // user thread, cannot be used by kernel + kHartFallback, // fallback thread, cannot be used by user if not clear or + // used by kernel. + kHartBoot, // The core we booted from, the mama. + kInvalidHart, + kHartCount, + }; + + typedef enum ThreadKind SmThreadKind; + typedef ThreadID SmThreadID; + + /// + /// \name HardwareThread + /// @brief CPU Hardware Thread (POWER, x64, or 64x0) + /// + + class HardwareThread final + { + public: + explicit HardwareThread(); + ~HardwareThread(); + + public: + NEWOS_COPY_DEFAULT(HardwareThread) + + public: + operator bool(); + + public: + void Wake(const bool wakeup = false) noexcept; + void Busy(const bool busy = false) noexcept; + + public: + bool Switch(HAL::StackFrame* stack); + bool IsWakeup() noexcept; + + public: + HAL::StackFrame* StackFrame() noexcept; + const ThreadKind& Kind() noexcept; + bool IsBusy() noexcept; + const ThreadID& ID() noexcept; + + private: + HAL::StackFrame* fStack{nullptr}; + ThreadKind fKind; + ThreadID fID; + ProcessID fSourcePID; + bool fWakeup; + bool fBusy; + + private: + friend class MPManager; + }; + + /// + /// \name MPManager + /// @brief Multi processor manager to manage other cores and dispatch tasks. + /// + + class MPManager final + { + private: + explicit MPManager(); + + public: + ~MPManager(); + NEWOS_COPY_DEFAULT(MPManager); + + public: + bool Switch(HAL::StackFramePtr the); + HAL::StackFramePtr Leak() noexcept; + + public: + Ref operator[](const SizeT& idx); + bool operator!() noexcept; + operator bool() noexcept; + + public: + /// @brief Shared instance of the SMP Manager. + /// @return the reference to the smp manager. + static Ref The(); + + public: + /// @brief Returns the amount of threads present in the system. + /// @returns SizeT the amount of cores present. + SizeT Count() noexcept; + + private: + Array fThreadList; + ThreadID fCurrentThread{0}; + }; + + /// @brief wakes up thread. + /// wakes up thread from hang. + Void rt_wakeup_thread(HAL::StackFramePtr stack); + + /// @brief makes thread sleep. + /// hooks and hangs thread to prevent code from executing. + Void rt_hang_thread(HAL::StackFramePtr stack); +} // namespace Kernel + +#endif // !__INC_MP_MANAGER_HPP__ diff --git a/Kernel/KernelKit/SMPManager.hpp b/Kernel/KernelKit/SMPManager.hpp deleted file mode 100644 index a7af05d9..00000000 --- a/Kernel/KernelKit/SMPManager.hpp +++ /dev/null @@ -1,126 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#ifndef __INC_SMP_MANAGER_HPP__ -#define __INC_SMP_MANAGER_HPP__ - -#include -#include -#include - -/// @note Last Rev Sun 28 Jul CET 2024 - -#define kMaxHarts 8 - -namespace Kernel -{ - using ThreadID = UInt32; - - enum ThreadKind - { - kHartSystemReserved, // System reserved thread, well user can't use it - kHartStandard, // user thread, cannot be used by kernel - kHartFallback, // fallback thread, cannot be used by user if not clear or - // used by kernel. - kHartBoot, // The core we booted from, the mama. - kInvalidHart, - kHartCount, - }; - - typedef enum ThreadKind SmThreadKind; - typedef ThreadID SmThreadID; - - /// - /// \name HardwareThread - /// @brief CPU Hardware Thread (POWER, x64, or 64x0) - /// - - class HardwareThread final - { - public: - explicit HardwareThread(); - ~HardwareThread(); - - public: - NEWOS_COPY_DEFAULT(HardwareThread) - - public: - operator bool(); - - public: - void Wake(const bool wakeup = false) noexcept; - void Busy(const bool busy = false) noexcept; - - public: - bool Switch(HAL::StackFrame* stack); - bool IsWakeup() noexcept; - - public: - HAL::StackFrame* StackFrame() noexcept; - const ThreadKind& Kind() noexcept; - bool IsBusy() noexcept; - const ThreadID& ID() noexcept; - - private: - HAL::StackFrame* fStack; - ThreadKind fKind; - ThreadID fID; - bool fWakeup; - bool fBusy; - Int64 fPID; - - private: - friend class SMPManager; - }; - - /// - /// \name SMPManager - /// @brief Multi processor manager to manage other cores and dispatch tasks. - /// - - class SMPManager final - { - private: - explicit SMPManager(); - - public: - ~SMPManager(); - NEWOS_COPY_DEFAULT(SMPManager); - - public: - bool Switch(HAL::StackFramePtr the); - HAL::StackFramePtr Leak() noexcept; - - public: - Ref operator[](const SizeT& idx); - bool operator!() noexcept; - operator bool() noexcept; - - public: - /// @brief Shared instance of the SMP Manager. - /// @return the reference to the smp manager. - static Ref The(); - - public: - /// @brief Returns the amount of threads present in the system. - /// @returns SizeT the amount of cores present. - SizeT Count() noexcept; - - private: - Array fThreadList; - ThreadID fCurrentThread{0}; - }; - - /// @brief wakes up thread. - /// wakes up thread from hang. - Void rt_wakeup_thread(HAL::StackFramePtr stack); - - /// @brief makes thread sleep. - /// hooks and hangs thread to prevent code from executing. - Void rt_hang_thread(HAL::StackFramePtr stack); -} // namespace Kernel - -#endif // !__INC_SMP_MANAGER_HPP__ diff --git a/Kernel/Sources/MPManager.cxx b/Kernel/Sources/MPManager.cxx new file mode 100644 index 00000000..d8faa983 --- /dev/null +++ b/Kernel/Sources/MPManager.cxx @@ -0,0 +1,256 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies + +------------------------------------------- */ + +#include +#include +#include +#include + +///! BUGS: 0 + +///! @file MPManager.cxx +///! @brief This file handles multi processing in Kernel. +///! @brief Multi processing is needed for multi-tasking operations. + +namespace Kernel +{ + STATIC Property cSMPCoreName; + + ///! A HardwareThread class takes care of it's owned hardware thread. + ///! It has a stack for it's core. + + ///! @brief C++ constructor. + HardwareThread::HardwareThread() = default; + + ///! @brief C++ destructor. + HardwareThread::~HardwareThread() = default; + + //! @brief returns the id of the thread. + const ThreadID& HardwareThread::ID() noexcept + { + return fID; + } + + //! @brief returns the kind of thread we have. + const ThreadKind& HardwareThread::Kind() noexcept + { + return fKind; + } + + //! @brief is the thread busy? + Bool HardwareThread::IsBusy() noexcept + { + return fBusy; + } + + /// @brief Get processor stack frame. + + HAL::StackFramePtr HardwareThread::StackFrame() noexcept + { + MUST_PASS(fStack); + return fStack; + } + + Void HardwareThread::Busy(const Bool busy) noexcept + { + fBusy = busy; + } + + HardwareThread::operator bool() + { + return fStack; + } + + /// @brief Wakeup the processor. + + Void HardwareThread::Wake(const bool wakeup) noexcept + { + fWakeup = wakeup; + + if (!fWakeup) + rt_hang_thread(fStack); + else + rt_wakeup_thread(fStack); + } + + EXTERN Bool rt_check_stack(HAL::StackFramePtr stackPtr); + + /// @brief Switch to hardware thread. + /// @param stack the new hardware thread. + /// @retval true stack was changed, code is running. + /// @retval false stack is invalid, previous code is running. + Bool HardwareThread::Switch(HAL::StackFramePtr stack) + { + if (!rt_check_stack(stack)) + { + /// provide 'nullptr' to free the stack frame. + if (stack == nullptr) + { + delete fStack; + fStack = nullptr; + + return true; + } + + return false; + } + + if (fStack) + { + delete fStack; + fStack = nullptr; + } + + fStack = stack; + + rt_do_context_switch(fStack); + + return true; + } + + ///! @brief Tells if processor is waked up. + bool HardwareThread::IsWakeup() noexcept + { + return fWakeup; + } + + //! @brief Constructor and destructor + + ///! @brief Default constructor. + MPManager::MPManager() + { + StringView strCoreName(512); + strCoreName += "\\Properties\\Smp\\SchedulerClass"; + + cSMPCoreName.GetKey() = strCoreName; + cSMPCoreName.GetValue() = (UIntPtr)this; + + kcout << "newoskrnl: initializing " << strCoreName.CData() << endl; + } + + ///! @brief Default destructor. + MPManager::~MPManager() = default; + + /// @brief Shared singleton function + Ref MPManager::The() + { + static MPManager manager; + return {manager}; + } + + /// @brief Get Stack Frame of Core + HAL::StackFramePtr MPManager::Leak() noexcept + { + if (fThreadList[fCurrentThread].Leak() && + ProcessHelper::TheCurrentPID() == + fThreadList[fCurrentThread].Leak().Leak()->fSourcePID) + return fThreadList[fCurrentThread].Leak().Leak()->fStack; + + return nullptr; + } + + /// @brief Finds and switch to a free core. + bool MPManager::Switch(HAL::StackFramePtr stack) + { + if (stack == nullptr) + return false; + + for (SizeT idx = 0; idx < kMaxHarts; ++idx) + { + // stack != nullptr -> if core is used, then continue. + if (!fThreadList[idx].Leak() || + !fThreadList[idx].Leak().Leak()->IsWakeup() || + fThreadList[idx].Leak().Leak()->IsBusy()) + continue; + + // to avoid any null deref. + if (!fThreadList[idx].Leak().Leak()->fStack) + continue; + if (fThreadList[idx].Leak().Leak()->fStack->SP == 0) + continue; + if (fThreadList[idx].Leak().Leak()->fStack->BP == 0) + continue; + + fThreadList[idx].Leak().Leak()->Busy(true); + + fThreadList[idx].Leak().Leak()->fID = idx; + + /// I figured out this: + /// Allocate stack + /// Set APIC base to stack + /// Do stuff and relocate stack based on this code. + /// - Amlel + rt_copy_memory(stack, fThreadList[idx].Leak().Leak()->fStack, + sizeof(HAL::StackFrame)); + + fThreadList[idx].Leak().Leak()->Switch(fThreadList[idx].Leak().Leak()->fStack); + + fThreadList[idx].Leak().Leak()->fSourcePID = ProcessHelper::TheCurrentPID(); + + fThreadList[idx].Leak().Leak()->Busy(false); + + return true; + } + + return false; + } + + /** + * Index Hardware thread + * @param idx the index + * @return the reference to the hardware thread. + */ + Ref MPManager::operator[](const SizeT& idx) + { + if (idx == 0) + { + if (fThreadList[idx].Leak().Leak()->Kind() != kHartSystemReserved) + { + fThreadList[idx].Leak().Leak()->fKind = kHartBoot; + } + } + else if (idx >= kMaxHarts) + { + static HardwareThread* fakeThread = new HardwareThread(); + + if (!fakeThread) + { + fakeThread = new HardwareThread(); + } + + fakeThread->fKind = kInvalidHart; + + return {fakeThread}; + } + + return fThreadList[idx].Leak(); + } + + /** + * Check if thread pool isn't empty. + * @return + */ + MPManager::operator bool() noexcept + { + return !fThreadList.Empty(); + } + + /** + * Reverse operator bool + * @return + */ + bool MPManager::operator!() noexcept + { + return fThreadList.Empty(); + } + + /// @brief Returns the amount of core present. + /// @return the number of cores. + SizeT MPManager::Count() noexcept + { + return fThreadList.Count(); + } +} // namespace Kernel diff --git a/Kernel/Sources/ProcessScheduler.cxx b/Kernel/Sources/ProcessScheduler.cxx index b5be1dd2..cccd8979 100644 --- a/Kernel/Sources/ProcessScheduler.cxx +++ b/Kernel/Sources/ProcessScheduler.cxx @@ -10,7 +10,7 @@ /***********************************************************************************/ #include -#include +#include #include #include #include @@ -382,29 +382,29 @@ namespace Kernel if (!the_stack || new_pid < 0) return false; - for (SizeT index = 0UL; index < SMPManager::The().Leak().Count(); ++index) + for (SizeT index = 0UL; index < MPManager::The().Leak().Count(); ++index) { - if (SMPManager::The().Leak()[index].Leak()->Kind() == kInvalidHart) + if (MPManager::The().Leak()[index].Leak()->Kind() == kInvalidHart) continue; - if (SMPManager::The().Leak()[index].Leak()->StackFrame() == the_stack) + if (MPManager::The().Leak()[index].Leak()->StackFrame() == the_stack) { - SMPManager::The().Leak()[index].Leak()->Busy(false); + MPManager::The().Leak()[index].Leak()->Busy(false); continue; } - if (SMPManager::The().Leak()[index].Leak()->IsBusy()) + if (MPManager::The().Leak()[index].Leak()->IsBusy()) continue; - if (SMPManager::The().Leak()[index].Leak()->Kind() != + if (MPManager::The().Leak()[index].Leak()->Kind() != ThreadKind::kHartBoot && - SMPManager::The().Leak()[index].Leak()->Kind() != + MPManager::The().Leak()[index].Leak()->Kind() != ThreadKind::kHartSystemReserved) { - SMPManager::The().Leak()[index].Leak()->Busy(true); + MPManager::The().Leak()[index].Leak()->Busy(true); ProcessHelper::TheCurrentPID() = new_pid; - return SMPManager::The().Leak()[index].Leak()->Switch(the_stack); + return MPManager::The().Leak()[index].Leak()->Switch(the_stack); } } diff --git a/Kernel/Sources/SMPManager.cxx b/Kernel/Sources/SMPManager.cxx deleted file mode 100644 index 155a1f86..00000000 --- a/Kernel/Sources/SMPManager.cxx +++ /dev/null @@ -1,256 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies - -------------------------------------------- */ - -#include -#include -#include -#include - -///! BUGS: 0 - -///! @file SMPManager.cxx -///! @brief This file handles multi processing in Kernel. -///! @brief Multi processing is needed for multi-tasking operations. - -namespace Kernel -{ - STATIC Property cSMPCoreName; - - ///! A HardwareThread class takes care of it's owned hardware thread. - ///! It has a stack for it's core. - - ///! @brief C++ constructor. - HardwareThread::HardwareThread() = default; - - ///! @brief C++ destructor. - HardwareThread::~HardwareThread() = default; - - //! @brief returns the id of the thread. - const ThreadID& HardwareThread::ID() noexcept - { - return fID; - } - - //! @brief returns the kind of thread we have. - const ThreadKind& HardwareThread::Kind() noexcept - { - return fKind; - } - - //! @brief is the thread busy? - Bool HardwareThread::IsBusy() noexcept - { - return fBusy; - } - - /// @brief Get processor stack frame. - - HAL::StackFramePtr HardwareThread::StackFrame() noexcept - { - MUST_PASS(fStack); - return fStack; - } - - Void HardwareThread::Busy(const Bool busy) noexcept - { - fBusy = busy; - } - - HardwareThread::operator bool() - { - return fStack; - } - - /// @brief Wakeup the processor. - - Void HardwareThread::Wake(const bool wakeup) noexcept - { - fWakeup = wakeup; - - if (!fWakeup) - rt_hang_thread(fStack); - else - rt_wakeup_thread(fStack); - } - - EXTERN Bool rt_check_stack(HAL::StackFramePtr stackPtr); - - /// @brief Switch to hardware thread. - /// @param stack the new hardware thread. - /// @retval true stack was changed, code is running. - /// @retval false stack is invalid, previous code is running. - Bool HardwareThread::Switch(HAL::StackFramePtr stack) - { - if (!rt_check_stack(stack)) - { - /// provide 'nullptr' to free the stack frame. - if (stack == nullptr) - { - delete fStack; - fStack = nullptr; - - return true; - } - - return false; - } - - if (fStack) - { - delete fStack; - fStack = nullptr; - } - - fStack = stack; - - rt_do_context_switch(fStack); - - return true; - } - - ///! @brief Tells if processor is waked up. - bool HardwareThread::IsWakeup() noexcept - { - return fWakeup; - } - - //! @brief Constructor and destructor - - ///! @brief Default constructor. - SMPManager::SMPManager() - { - StringView strCoreName(512); - strCoreName += "\\Properties\\Smp\\SchedulerClass"; - - cSMPCoreName.GetKey() = strCoreName; - cSMPCoreName.GetValue() = (UIntPtr)this; - - kcout << "newoskrnl: initializing " << strCoreName.CData() << endl; - } - - ///! @brief Default destructor. - SMPManager::~SMPManager() = default; - - /// @brief Shared singleton function - Ref SMPManager::The() - { - static SMPManager manager; - return {manager}; - } - - /// @brief Get Stack Frame of Core - HAL::StackFramePtr SMPManager::Leak() noexcept - { - if (fThreadList[fCurrentThread].Leak() && - ProcessHelper::TheCurrentPID() == - fThreadList[fCurrentThread].Leak().Leak()->fPID) - return fThreadList[fCurrentThread].Leak().Leak()->fStack; - - return nullptr; - } - - /// @brief Finds and switch to a free core. - bool SMPManager::Switch(HAL::StackFramePtr stack) - { - if (stack == nullptr) - return false; - - for (SizeT idx = 0; idx < kMaxHarts; ++idx) - { - // stack != nullptr -> if core is used, then continue. - if (!fThreadList[idx].Leak() || - !fThreadList[idx].Leak().Leak()->IsWakeup() || - fThreadList[idx].Leak().Leak()->IsBusy()) - continue; - - // to avoid any null deref. - if (!fThreadList[idx].Leak().Leak()->fStack) - continue; - if (fThreadList[idx].Leak().Leak()->fStack->SP == 0) - continue; - if (fThreadList[idx].Leak().Leak()->fStack->BP == 0) - continue; - - fThreadList[idx].Leak().Leak()->Busy(true); - - fThreadList[idx].Leak().Leak()->fID = idx; - - /// I figured out this: - /// Allocate stack - /// Set APIC base to stack - /// Do stuff and relocate stack based on this code. - /// - Amlel - rt_copy_memory(stack, fThreadList[idx].Leak().Leak()->fStack, - sizeof(HAL::StackFrame)); - - fThreadList[idx].Leak().Leak()->Switch(fThreadList[idx].Leak().Leak()->fStack); - - fThreadList[idx].Leak().Leak()->fPID = ProcessHelper::TheCurrentPID(); - - fThreadList[idx].Leak().Leak()->Busy(false); - - return true; - } - - return false; - } - - /** - * Index Hardware thread - * @param idx the index - * @return the reference to the hardware thread. - */ - Ref SMPManager::operator[](const SizeT& idx) - { - if (idx == 0) - { - if (fThreadList[idx].Leak().Leak()->Kind() != kHartSystemReserved) - { - fThreadList[idx].Leak().Leak()->fKind = kHartBoot; - } - } - else if (idx >= kMaxHarts) - { - static HardwareThread* fakeThread = new HardwareThread(); - - if (!fakeThread) - { - fakeThread = new HardwareThread(); - } - - fakeThread->fKind = kInvalidHart; - - return {fakeThread}; - } - - return fThreadList[idx].Leak(); - } - - /** - * Check if thread pool isn't empty. - * @return - */ - SMPManager::operator bool() noexcept - { - return !fThreadList.Empty(); - } - - /** - * Reverse operator bool - * @return - */ - bool SMPManager::operator!() noexcept - { - return fThreadList.Empty(); - } - - /// @brief Returns the amount of core present. - /// @return the number of cores. - SizeT SMPManager::Count() noexcept - { - return fThreadList.Count(); - } -} // namespace Kernel -- cgit v1.2.3