diff options
Diffstat (limited to 'dev/ZKAKit/src/HardwareThreadScheduler.cc')
| -rw-r--r-- | dev/ZKAKit/src/HardwareThreadScheduler.cc | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/dev/ZKAKit/src/HardwareThreadScheduler.cc b/dev/ZKAKit/src/HardwareThreadScheduler.cc new file mode 100644 index 00000000..ddfd0ee7 --- /dev/null +++ b/dev/ZKAKit/src/HardwareThreadScheduler.cc @@ -0,0 +1,196 @@ +/* ------------------------------------------- + + Copyright ZKA Web Services Co. + +------------------------------------------- */ + +#include <ArchKit/ArchKit.h> +#include <KernelKit/UserProcessScheduler.h> +#include <KernelKit/HardwareThreadScheduler.h> +#include <CFKit/Property.h> + +///! BUGS: 0 + +///! @file MP.cc +///! @brief This file handles multi processing in the Kernel. +///! @brief Multi processing is needed for multi-tasking operations. + +namespace Kernel +{ + HardwareThreadScheduler* kHardwareThreadScheduler = nullptr; + + ///! 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? + //! @return whether the thread is busy or not. + Bool HardwareThread::IsBusy() noexcept + { + STATIC Int64 busy_timer = 0U; + + if (busy_timer > this->fPTime) + { + busy_timer = 0U; + fBusy = No; + } + + ++busy_timer; + + 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(VoidPtr image, UInt8* stack_ptr, HAL::StackFramePtr frame_ptr); + + /// @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 No; + + if (!this->IsWakeup()) + return No; + + if (this->IsBusy()) + return No; + + fStack = frame; + + Bool ret = mp_register_process(image, stack_ptr, fStack); + + if (ret) + this->Busy(true); + + return ret; + } + + ///! @brief Tells if processor is waked up. + bool HardwareThread::IsWakeup() noexcept + { + return fWakeup; + } + + ///! @brief Constructor and destructors. + + ///! @brief Default constructor. + HardwareThreadScheduler::HardwareThreadScheduler() = default; + + ///! @brief Default destructor. + HardwareThreadScheduler::~HardwareThreadScheduler() = default; + + /// @brief Shared singleton function + HardwareThreadScheduler& HardwareThreadScheduler::The() + { + MUST_PASS(kHardwareThreadScheduler); + return *kHardwareThreadScheduler; + } + + /// @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<HardwareThread*> HardwareThreadScheduler::operator[](const SizeT& idx) + { + if (idx == 0) + { + if (fThreadList[idx].Kind() != kHartSystemReserved) + { + fThreadList[idx].fKind = kHartBoot; + } + } + else if (idx >= cMaxHartInsideSched) + { + static HardwareThread* fakeThread = nullptr; + 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.Capacity(); + } +} // namespace Kernel |
