From 3e2b931d65582284e9716c42a902cab6d279c7f0 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Thu, 5 Sep 2024 11:54:27 +0200 Subject: [ IMP ] Add Interrupt for scheduler (for APIC, maybe PIT?) [ IMP ] Fixed user scheduler context switching. Signed-off-by: Amlal El Mahrouss --- .../HALKit/AMD64/HalCoreInterruptHandlerAMD64.cxx | 5 + dev/ZKA/HALKit/AMD64/HalCoreMPScheduler.cxx | 2 +- dev/ZKA/KernelKit/HardwareThreadScheduler.hxx | 129 +++++++++++++ dev/ZKA/KernelKit/MP.hxx | 129 ------------- dev/ZKA/KernelKit/UserProcessScheduler.hxx | 12 +- dev/ZKA/Sources/HardwareThreadScheduler.cxx | 200 +++++++++++++++++++++ dev/ZKA/Sources/MP.cxx | 197 -------------------- dev/ZKA/Sources/UserProcessScheduler.cxx | 9 +- 8 files changed, 348 insertions(+), 335 deletions(-) create mode 100644 dev/ZKA/KernelKit/HardwareThreadScheduler.hxx delete mode 100644 dev/ZKA/KernelKit/MP.hxx create mode 100644 dev/ZKA/Sources/HardwareThreadScheduler.cxx delete mode 100644 dev/ZKA/Sources/MP.cxx (limited to 'dev') diff --git a/dev/ZKA/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cxx b/dev/ZKA/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cxx index 1be22e7d..b49a688f 100644 --- a/dev/ZKA/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cxx +++ b/dev/ZKA/HALKit/AMD64/HalCoreInterruptHandlerAMD64.cxx @@ -28,6 +28,11 @@ EXTERN_C void idt_handle_pf(Kernel::UIntPtr rsp) Kernel::ke_stop(RUNTIME_CHECK_PROCESS); } +EXTERN_C void idt_handle_scheduler(Kernel::UIntPtr rsp) +{ + Kernel::UserProcessHelper::StartScheduling(); +} + /// @brief Handle math fault. /// @param rsp EXTERN_C void idt_handle_math(Kernel::UIntPtr rsp) diff --git a/dev/ZKA/HALKit/AMD64/HalCoreMPScheduler.cxx b/dev/ZKA/HALKit/AMD64/HalCoreMPScheduler.cxx index f985deb7..5f6c0552 100644 --- a/dev/ZKA/HALKit/AMD64/HalCoreMPScheduler.cxx +++ b/dev/ZKA/HALKit/AMD64/HalCoreMPScheduler.cxx @@ -16,7 +16,7 @@ // Needed for SMP. // #include -#include +#include #define kApicSignature "APIC" diff --git a/dev/ZKA/KernelKit/HardwareThreadScheduler.hxx b/dev/ZKA/KernelKit/HardwareThreadScheduler.hxx new file mode 100644 index 00000000..cf5d6754 --- /dev/null +++ b/dev/ZKA/KernelKit/HardwareThreadScheduler.hxx @@ -0,0 +1,129 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#ifndef __INC_MP_MANAGER_HPP__ +#define __INC_MP_MANAGER_HPP__ + +#include +#include +#include + +/// @note Last Rev Sun 28 Jul CET 2024 +/// @note Last Rev Thu, Aug 1, 2024 9:07:38 AM + +#define cMaxHWThreads (8U) + +namespace Kernel +{ + class HardwareThread; + class HardwareThreadScheduler; + + 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 ThreadKind; + typedef ThreadID ThreadID; + + /// + /// \name HardwareThread + /// \brief Abstraction over the CPU's core, used to run processes or threads. + /// + + class HardwareThread final + { + public: + explicit HardwareThread(); + ~HardwareThread(); + + public: + ZKA_COPY_DEFAULT(HardwareThread) + + public: + operator bool(); + + public: + void Wake(const bool wakeup = false) noexcept; + void Busy(const bool busy = false) noexcept; + + public: + bool Switch(VoidPtr image, UInt8* stack_ptr, HAL::StackFramePtr frame); + bool IsWakeup() noexcept; + + public: + HAL::StackFramePtr StackFrame() noexcept; + const ThreadKind& Kind() noexcept; + bool IsBusy() noexcept; + const ThreadID& ID() noexcept; + + private: + HAL::StackFramePtr fStack{nullptr}; + ThreadKind fKind{ThreadKind::kHartStandard}; + ThreadID fID{0}; + ProcessID fSourcePID{-1}; + bool fWakeup{false}; + bool fBusy{false}; + + private: + friend class HardwareThreadScheduler; + }; + + /// + /// \name HardwareThreadScheduler + /// \brief Class to manage the thread scheduling. + /// + + class HardwareThreadScheduler final + { + private: + explicit HardwareThreadScheduler(); + + public: + ~HardwareThreadScheduler(); + ZKA_COPY_DEFAULT(HardwareThreadScheduler); + + public: + HAL::StackFramePtr Leak() noexcept; + + public: + Ref operator[](const SizeT& idx); + bool operator!() noexcept; + operator bool() noexcept; + + public: + /// @brief Shared instance of the MP Mgr. + /// @return the reference to the mp manager class. + STATIC HardwareThreadScheduler& 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 mp_wakeup_thread(HAL::StackFramePtr stack); + + /// @brief makes thread sleep. + /// hooks and hangs thread to prevent code from executing. + Void mp_hang_thread(HAL::StackFramePtr stack); +} // namespace Kernel + +#endif // !__INC_MP_MANAGER_HPP__ diff --git a/dev/ZKA/KernelKit/MP.hxx b/dev/ZKA/KernelKit/MP.hxx deleted file mode 100644 index cf5d6754..00000000 --- a/dev/ZKA/KernelKit/MP.hxx +++ /dev/null @@ -1,129 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies. - -------------------------------------------- */ - -#ifndef __INC_MP_MANAGER_HPP__ -#define __INC_MP_MANAGER_HPP__ - -#include -#include -#include - -/// @note Last Rev Sun 28 Jul CET 2024 -/// @note Last Rev Thu, Aug 1, 2024 9:07:38 AM - -#define cMaxHWThreads (8U) - -namespace Kernel -{ - class HardwareThread; - class HardwareThreadScheduler; - - 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 ThreadKind; - typedef ThreadID ThreadID; - - /// - /// \name HardwareThread - /// \brief Abstraction over the CPU's core, used to run processes or threads. - /// - - class HardwareThread final - { - public: - explicit HardwareThread(); - ~HardwareThread(); - - public: - ZKA_COPY_DEFAULT(HardwareThread) - - public: - operator bool(); - - public: - void Wake(const bool wakeup = false) noexcept; - void Busy(const bool busy = false) noexcept; - - public: - bool Switch(VoidPtr image, UInt8* stack_ptr, HAL::StackFramePtr frame); - bool IsWakeup() noexcept; - - public: - HAL::StackFramePtr StackFrame() noexcept; - const ThreadKind& Kind() noexcept; - bool IsBusy() noexcept; - const ThreadID& ID() noexcept; - - private: - HAL::StackFramePtr fStack{nullptr}; - ThreadKind fKind{ThreadKind::kHartStandard}; - ThreadID fID{0}; - ProcessID fSourcePID{-1}; - bool fWakeup{false}; - bool fBusy{false}; - - private: - friend class HardwareThreadScheduler; - }; - - /// - /// \name HardwareThreadScheduler - /// \brief Class to manage the thread scheduling. - /// - - class HardwareThreadScheduler final - { - private: - explicit HardwareThreadScheduler(); - - public: - ~HardwareThreadScheduler(); - ZKA_COPY_DEFAULT(HardwareThreadScheduler); - - public: - HAL::StackFramePtr Leak() noexcept; - - public: - Ref operator[](const SizeT& idx); - bool operator!() noexcept; - operator bool() noexcept; - - public: - /// @brief Shared instance of the MP Mgr. - /// @return the reference to the mp manager class. - STATIC HardwareThreadScheduler& 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 mp_wakeup_thread(HAL::StackFramePtr stack); - - /// @brief makes thread sleep. - /// hooks and hangs thread to prevent code from executing. - Void mp_hang_thread(HAL::StackFramePtr stack); -} // namespace Kernel - -#endif // !__INC_MP_MANAGER_HPP__ diff --git a/dev/ZKA/KernelKit/UserProcessScheduler.hxx b/dev/ZKA/KernelKit/UserProcessScheduler.hxx index d5172fe9..9585da29 100644 --- a/dev/ZKA/KernelKit/UserProcessScheduler.hxx +++ b/dev/ZKA/KernelKit/UserProcessScheduler.hxx @@ -52,12 +52,12 @@ namespace Kernel //! to run. enum class AffinityKind : Int32 { - kRealTime = 0500, - kVeryHigh = 2500, - kHigh = 2000, - kStandard = 1500, - kLowUsage = 1000, - kVeryLowUsage = 5000, + kRealTime = 500, + kVeryHigh = 250, + kHigh = 200, + kStandard = 1000, + kLowUsage = 1500, + kVeryLowUsage = 2000, }; // operator overloading. diff --git a/dev/ZKA/Sources/HardwareThreadScheduler.cxx b/dev/ZKA/Sources/HardwareThreadScheduler.cxx new file mode 100644 index 00000000..b130ef63 --- /dev/null +++ b/dev/ZKA/Sources/HardwareThreadScheduler.cxx @@ -0,0 +1,200 @@ +/* ------------------------------------------- + + Copyright ZKA Technologies. + +------------------------------------------- */ + +#include +#include +#include +#include + +///! BUGS: 0 + +///! @file MP.cxx +///! @brief This file handles multi processing in the Kernel. +///! @brief Multi processing is needed for multi-tasking operations. + +namespace Kernel +{ + ///! 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) + mp_hang_thread(fStack); + else + mp_wakeup_thread(fStack); + } + + /// @note Those symbols are needed in order to switch and validate the stack. + + EXTERN Bool hal_check_stack(HAL::StackFramePtr stackPtr); + EXTERN_C Bool mp_register_process(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(VoidPtr image, UInt8* stack_ptr, HAL::StackFramePtr frame) + { + if (!frame || + !image || + !stack_ptr) + return false; + + if (this->IsBusy()) + return false; + + fStack = frame; + + if (kHandoverHeader->f_HardwareTables.f_MultiProcessingEnabled) + { + this->Busy(true); + Bool ret = mp_register_process(fStack); + this->Busy(true); + + return ret; + } + else + { + mp_do_context_switch_pre(); + mp_do_context_switch(image, stack_ptr, fStack); + + return true; + } + } + + ///! @brief Tells if processor is waked up. + bool HardwareThread::IsWakeup() noexcept + { + return fWakeup; + } + + ///! @brief Internal Hardware Thread list. + STATIC HardwareThread cThreadList[cMaxHWThreads]; + + ///! @brief Constructor and destructors. + + ///! @brief Default constructor. + HardwareThreadScheduler::HardwareThreadScheduler() = default; + + ///! @brief Default destructor. + HardwareThreadScheduler::~HardwareThreadScheduler() = default; + + /// @brief Shared singleton function + HardwareThreadScheduler& HardwareThreadScheduler::The() + { + STATIC HardwareThreadScheduler sched; + return sched; + } + + /// @brief Get Stack Frame of Core + HAL::StackFramePtr HardwareThreadScheduler::Leak() noexcept + { + return fThreadList[fCurrentThread].fStack; + } + + /** + * Get Hardware thread at index. + * @param idx the index + * @return the reference to the hardware thread. + */ + Ref HardwareThreadScheduler::operator[](const SizeT& idx) + { + if (idx == 0) + { + if (fThreadList[idx].Kind() != kHartSystemReserved) + { + fThreadList[idx].fKind = kHartBoot; + } + } + else if (idx >= cMaxHWThreads) + { + static HardwareThread* fakeThread = new HardwareThread(); + + if (!fakeThread) + { + fakeThread = new HardwareThread(); + } + + fakeThread->fKind = kInvalidHart; + + return {fakeThread}; + } + + return &fThreadList[idx]; + } + + /** + * Check if thread pool isn't empty. + * @return + */ + HardwareThreadScheduler::operator bool() noexcept + { + return !fThreadList.Empty(); + } + + /** + * Reverse operator bool + * @return + */ + bool HardwareThreadScheduler::operator!() noexcept + { + return fThreadList.Empty(); + } + + /// @brief Returns the amount of core present. + /// @return the number of cores. + SizeT HardwareThreadScheduler::Count() noexcept + { + return fThreadList.Count(); + } +} // namespace Kernel diff --git a/dev/ZKA/Sources/MP.cxx b/dev/ZKA/Sources/MP.cxx deleted file mode 100644 index 0e109b66..00000000 --- a/dev/ZKA/Sources/MP.cxx +++ /dev/null @@ -1,197 +0,0 @@ -/* ------------------------------------------- - - Copyright ZKA Technologies. - -------------------------------------------- */ - -#include -#include -#include -#include - -///! BUGS: 0 - -///! @file MP.cxx -///! @brief This file handles multi processing in the Kernel. -///! @brief Multi processing is needed for multi-tasking operations. - -namespace Kernel -{ - ///! 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) - mp_hang_thread(fStack); - else - mp_wakeup_thread(fStack); - } - - /// @note Those symbols are needed in order to switch and validate the stack. - - EXTERN Bool hal_check_stack(HAL::StackFramePtr stackPtr); - EXTERN_C Bool mp_register_process(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(VoidPtr image, UInt8* stack_ptr, HAL::StackFramePtr frame) - { - if (!frame || - !image || - !stack_ptr) - return false; - - fStack = frame; - - if (kHandoverHeader->f_HardwareTables.f_MultiProcessingEnabled) - { - this->Busy(true); - Bool ret = mp_register_process(fStack); - this->Busy(true); - - return ret; - } - else - { - mp_do_context_switch_pre(); - mp_do_context_switch(image, stack_ptr, fStack); - - return true; - } - } - - ///! @brief Tells if processor is waked up. - bool HardwareThread::IsWakeup() noexcept - { - return fWakeup; - } - - ///! @brief Internal Hardware Thread list. - STATIC HardwareThread cThreadList[cMaxHWThreads]; - - ///! @brief Constructor and destructors. - - ///! @brief Default constructor. - HardwareThreadScheduler::HardwareThreadScheduler() = default; - - ///! @brief Default destructor. - HardwareThreadScheduler::~HardwareThreadScheduler() = default; - - /// @brief Shared singleton function - HardwareThreadScheduler& HardwareThreadScheduler::The() - { - STATIC HardwareThreadScheduler sched; - return sched; - } - - /// @brief Get Stack Frame of Core - HAL::StackFramePtr HardwareThreadScheduler::Leak() noexcept - { - return fThreadList[fCurrentThread].fStack; - } - - /** - * Get Hardware thread at index. - * @param idx the index - * @return the reference to the hardware thread. - */ - Ref HardwareThreadScheduler::operator[](const SizeT& idx) - { - if (idx == 0) - { - if (fThreadList[idx].Kind() != kHartSystemReserved) - { - fThreadList[idx].fKind = kHartBoot; - } - } - else if (idx >= cMaxHWThreads) - { - static HardwareThread* fakeThread = new HardwareThread(); - - if (!fakeThread) - { - fakeThread = new HardwareThread(); - } - - fakeThread->fKind = kInvalidHart; - - return {fakeThread}; - } - - return &fThreadList[idx]; - } - - /** - * Check if thread pool isn't empty. - * @return - */ - HardwareThreadScheduler::operator bool() noexcept - { - return !fThreadList.Empty(); - } - - /** - * Reverse operator bool - * @return - */ - bool HardwareThreadScheduler::operator!() noexcept - { - return fThreadList.Empty(); - } - - /// @brief Returns the amount of core present. - /// @return the number of cores. - SizeT HardwareThreadScheduler::Count() noexcept - { - return fThreadList.Count(); - } -} // namespace Kernel diff --git a/dev/ZKA/Sources/UserProcessScheduler.cxx b/dev/ZKA/Sources/UserProcessScheduler.cxx index 733e19ed..4e0c8902 100644 --- a/dev/ZKA/Sources/UserProcessScheduler.cxx +++ b/dev/ZKA/Sources/UserProcessScheduler.cxx @@ -11,7 +11,7 @@ #include #include -#include +#include #include #include #include @@ -435,11 +435,16 @@ namespace Kernel HardwareThreadScheduler::The()[index].Leak()->Kind() != ThreadKind::kHartSystemReserved) { + PID prev_pid = UserProcessHelper::TheCurrentPID(); UserProcessHelper::TheCurrentPID() = new_pid; bool ret = HardwareThreadScheduler::The()[index].Leak()->Switch(image_ptr, stack, frame_ptr); - return ret; + if (!ret) + { + UserProcessHelper::TheCurrentPID() = prev_pid; + continue; + } } } -- cgit v1.2.3