/* * ======================================================== * * HCore * Copyright Mahrouss Logic, all rights reserved. * * ======================================================== */ #include #include #include /// BUGS: 0 ///! @brief This file handles multi processing in HCore. ///! @brief Multi processing is needed for multi-tasking operations. namespace HCore { // A HardwareThread class takes care of it's owned hardware thread. // It has a stack for it's core. // @brief constructor HardwareThread::HardwareThread() = default; // @brief destructor HardwareThread::~HardwareThread() = default; //! @brief returns the id const ThreadID& HardwareThread::ID() noexcept { return m_ID; } //! @brief returns the kind const ThreadKind& HardwareThread::Kind() noexcept { return m_Kind; } //! @brief is the core busy? bool HardwareThread::IsBusy() noexcept { return m_Busy; } /// @brief Get processor stack frame. HAL::StackFrame* HardwareThread::StackFrame() noexcept { MUST_PASS(m_Stack); return m_Stack; } void HardwareThread::Busy(const bool busy) noexcept { m_Busy = busy; } HardwareThread::operator bool() { return m_Stack; } /// @brief Wakeup the processor. void HardwareThread::Wake(const bool wakeup) noexcept { m_Wakeup = wakeup; if (!m_Wakeup) rt_hang_thread(m_Stack); else rt_wakeup_thread(m_Stack); } bool HardwareThread::Switch(HAL::StackFrame* stack) { if (stack == nullptr) return false; return rt_do_context_switch(m_Stack, stack) == 0; } ///! @brief Tells if processor is waked up. bool HardwareThread::IsWakeup() noexcept { return m_Wakeup; } //! @brief Constructor and destructor ///! @brief Default constructor. SMPManager::SMPManager() = default; ///! @brief Default destructor. SMPManager::~SMPManager() = default; /// @brief Shared singleton function Ref SMPManager::Shared() { static SMPManager manager; return {manager}; } /// @brief Get Stack Frame of Core HAL::StackFramePtr SMPManager::GetStackFrame() noexcept { if (m_ThreadList[m_CurrentThread].Leak() && ProcessHelper::GetCurrentPID() == m_ThreadList[m_CurrentThread].Leak().Leak().m_PID) return m_ThreadList[m_CurrentThread].Leak().Leak().m_Stack; return nullptr; } /// @brief Finds and switch to a free core. bool SMPManager::Switch(HAL::StackFrame* stack) { if (stack == nullptr) return false; for (SizeT idx = 0; idx < kMaxHarts; ++idx) { // stack != nullptr -> if core is used, then continue. if (!m_ThreadList[idx].Leak() || !m_ThreadList[idx].Leak().Leak().IsWakeup() || m_ThreadList[idx].Leak().Leak().IsBusy()) continue; m_ThreadList[idx].Leak().Leak().m_ID = idx; m_ThreadList[idx].Leak().Leak().m_Stack = stack; m_ThreadList[idx].Leak().Leak().m_PID = ProcessHelper::GetCurrentPID(); m_ThreadList[idx].Leak().Leak().Busy(true); Boolean ret = (rt_do_context_switch(rt_get_current_context(), stack) == 0); m_ThreadList[idx].Leak().Leak().Busy(false); return ret; } return false; } /** * Index Hardware thread * @param idx the index * @return the reference to the hardware thread. */ Ref SMPManager::operator[](const SizeT& idx) { return m_ThreadList[idx].Leak(); } /** * Check if thread pool isn't empty. * @return */ SMPManager::operator bool() noexcept { return !m_ThreadList.Empty(); } /** * Reverse operator bool * @return */ bool SMPManager::operator!() noexcept { return m_ThreadList.Empty(); } } // namespace HCore