blob: 25dbc0cf39177532a170777c492ba86f69e2c1d5 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
/*
* ========================================================
*
* hCore
* Copyright Mahrouss Logic, all rights reserved.
*
* ========================================================
*/
#include <KernelKit/SMPManager.hpp>
#include <KernelKit/ProcessManager.hpp>
#include <ArchKit/Arch.hpp>
//! This file handles multi processing in hCore.
namespace hCore
{
// @brief wakes up thread.
// wakes up thread from hang.
extern void rt_wakeup_thread(HAL::StackFrame* stack);
// @brief makes thread sleep.
// hooks and hangs thread to prevent code from executing.
extern void rt_hang_thread(HAL::StackFrame* stack);
// A ProcessorCore class takes care of it's owned hardware thread.
// It has a stack for it's core.
// @brief constructor
ProcessorCore::ProcessorCore() = default;
// @brief destructor
ProcessorCore::~ProcessorCore() = default;
//! @brief returns the id
const ThreadID& ProcessorCore::ID() noexcept { return m_ID; }
//! @brief returns the kind
const ThreadKind& ProcessorCore::Kind() noexcept { return m_Kind; }
//! @brief is the core busy?
bool ProcessorCore::IsBusy() noexcept { return m_Busy; }
HAL::StackFrame* ProcessorCore::StackFrame() noexcept
{
MUST_PASS(m_Stack);
return m_Stack;
}
void ProcessorCore::Busy(const bool busy) noexcept { m_Busy = busy; }
ProcessorCore::operator bool() { return m_Stack; }
void ProcessorCore::Wake(const bool wakeup) noexcept
{
m_Wakeup = wakeup;
if (!m_Wakeup)
rt_hang_thread(m_Stack);
else
rt_wakeup_thread(m_Stack);
}
bool ProcessorCore::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 ProcessorCore::IsWakeup() noexcept { return m_Wakeup; }
//! @brief Constructor and destructor
///! @brief Default constructor.
SMPManager::SMPManager() = default;
///! @brief Default destructor.
SMPManager::~SMPManager() = default;
Ref<SMPManager> SMPManager::Shared()
{
static SMPManager manager;
return { manager };
}
HAL::StackFramePtr SMPManager::GetStack() 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);
bool ret = rt_do_context_switch(rt_get_current_context(), stack) == 0;
m_ThreadList[idx].Leak().Leak().Busy(false);
}
return false;
}
Ref<ProcessorCore> SMPManager::operator[](const SizeT& idx) { return m_ThreadList[idx].Leak(); }
SMPManager::operator bool() noexcept { return !m_ThreadList.Empty(); }
bool SMPManager::operator!() noexcept { return m_ThreadList.Empty(); }
} // namespace hCore
|