summaryrefslogtreecommitdiffhomepage
path: root/dev/ZKAKit/src/HardwareThreadScheduler.cc
blob: 07aafbe90b312b0ea4a29bc667cef1f84a99f3dd (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
226
227
228
229
230
231
232
233
234
235
236
237
238
/* -------------------------------------------

	Copyright (C) 2024, ELMH GROUP, 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 Bool	  hal_check_stack(HAL::StackFramePtr frame_ptr);
	EXTERN_C Bool mp_register_process(VoidPtr image, Ptr8 stack_ptr, 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;

		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 this->fStack && !this->fBusy;
	}

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

	Void HardwareThread::Wake(const bool wakeup) noexcept
	{
		fWakeup = wakeup;

		if (!fWakeup)
			mp_hang_thread(fStack);
		else
			mp_wakeup_thread(fStack);
	}

	/***********************************************************************************/
	/// @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, Ptr8 stack_ptr, HAL::StackFramePtr frame, const ProcessID& pid)
	{
		if (!frame ||
			!image ||
			!stack_ptr)
			return No;

		if (!this->IsWakeup())
			return No;

		if (this->IsBusy())
			return No;

		if (!hal_check_stack(frame))
			return No;

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

		Bool ret = mp_register_process(image, stack_ptr, fStack, this->fSourcePID);

		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()
	{
		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* 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 APs.
	/***********************************************************************************/
	SizeT HardwareThreadScheduler::Capacity() noexcept
	{
		if (fThreadList.Empty())
			return 0UL;

		return fThreadList.Capacity();
	}
} // namespace Kernel