summaryrefslogtreecommitdiffhomepage
path: root/dev/kernel/src/HardwareThreadScheduler.cc
blob: 1aa990ac73601494801a110bd7d9268c2eabc526 (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/* -------------------------------------------

	Copyright (C) 2024-2025, Amlal EL Mahrouss, all rights reserved.

------------------------------------------- */

#include <ArchKit/ArchKit.h>
#include <KernelKit/UserProcessScheduler.h>
#include <KernelKit/HardwareThreadScheduler.h>
#include <CFKit/Property.h>

/***********************************************************************************/
///! @file HardwareThreadScheduler.cc
///! @brief This file handles multi processing in the Kernel.
///! @brief Multi processing is needed for multi-tasking operations.
/***********************************************************************************/

namespace Kernel
{
	/***********************************************************************************/
	/// @note Those symbols are needed in order to switch and validate the stack.
	/***********************************************************************************/

	EXTERN_C Bool hal_check_stack(HAL::StackFramePtr frame);
	EXTERN_C Bool mp_register_process(HAL::StackFramePtr frame, ProcessID pid);

	STATIC HardwareThreadScheduler kHardwareThreadScheduler;

	///! 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;
		constexpr Int64 kTimeoutMax = 0x1000000; // an arbitrary value used to tell if the timeout hasn't been reached yet.

		if (fBusy && (busy_timer > kTimeoutMax))
		{
			busy_timer = 0U;
			fBusy	   = No;

			return No;
		}

		++busy_timer;

		return fBusy;
	}

	/***********************************************************************************/
	/// @brief Get processor stack frame.
	/***********************************************************************************/

	HAL::StackFramePtr HardwareThread::StackFrame() noexcept
	{
		MUST_PASS(this->fStack);
		return this->fStack;
	}

	Void HardwareThread::Busy(const Bool busy) noexcept
	{
		this->fBusy = busy;
	}

	HardwareThread::operator bool()
	{
		return this->fStack && !this->fBusy;
	}

	/***********************************************************************************/
	/// @brief Wakeup the processor.
	/***********************************************************************************/

	Void HardwareThread::Wake(const bool wakeup) noexcept
	{
		this->fWakeup = wakeup;
	}

	/***********************************************************************************/
	/// @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_ptr, Ptr8 stack_ptr, HAL::StackFramePtr frame, const ThreadID& pid)
	{
		if (this->IsBusy())
			return NO;

		this->fStack = frame;
		this->fPID	 = pid;

		this->fStack->BP = reinterpret_cast<UIntPtr>(image_ptr);
		this->fStack->SP = reinterpret_cast<UIntPtr>(stack_ptr);

		Bool ret = mp_register_process(fStack, this->fPID);

		if (ret)
			this->Busy(YES);

		return ret;
	}

	/***********************************************************************************/
	///! @brief Tells if processor is waked up.
	/***********************************************************************************/
	bool HardwareThread::IsWakeup() noexcept
	{
		return this->fWakeup;
	}

	/***********************************************************************************/
	///! @brief Constructor and destructors.
	///! @brief Default constructor.
	/***********************************************************************************/

	HardwareThreadScheduler::HardwareThreadScheduler() = default;

	/***********************************************************************************/
	///! @brief Default destructor.
	/***********************************************************************************/
	HardwareThreadScheduler::~HardwareThreadScheduler() = default;

	/***********************************************************************************/
	/// @brief Shared singleton function
	/***********************************************************************************/
	HardwareThreadScheduler& HardwareThreadScheduler::The()
	{
		return kHardwareThreadScheduler;
	}

	/***********************************************************************************/
	/// @brief Get Stack Frame of AP.
	/***********************************************************************************/
	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() != kAPSystemReserved)
			{
				fThreadList[idx].fKind = kAPBoot;
			}
		}
		else if (idx >= kMaxAPInsideSched)
		{
			static HardwareThread* kFakeThread = nullptr;
			return {kFakeThread};
		}

		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 APs.
	/***********************************************************************************/
	SizeT HardwareThreadScheduler::Capacity() noexcept
	{
		return fThreadList.Count();
	}
} // namespace Kernel