summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/thread.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2014-05-20 19:37:46 -0400
committerGravatar bunnei2014-05-20 19:37:46 -0400
commit75c6d2a8fa3547946227094af6c179e5ccba0e1e (patch)
tree6199164fdc1745d6b12333b0b2efc269e8c7ee5d /src/core/hle/kernel/thread.cpp
parentARM_Interpreter/ARM_Interface: Fixed member variable naming to be consistent ... (diff)
downloadyuzu-75c6d2a8fa3547946227094af6c179e5ccba0e1e.tar.gz
yuzu-75c6d2a8fa3547946227094af6c179e5ccba0e1e.tar.xz
yuzu-75c6d2a8fa3547946227094af6c179e5ccba0e1e.zip
thread: moved threading calls to the Kernel namespace
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
-rw-r--r--src/core/hle/kernel/thread.cpp184
1 files changed, 95 insertions, 89 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index b3d306c53..7b4f0ea47 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -19,7 +19,7 @@
19#include "core/hle/kernel/kernel.h" 19#include "core/hle/kernel/kernel.h"
20#include "core/hle/kernel/thread.h" 20#include "core/hle/kernel/thread.h"
21 21
22// Enums 22namespace Kernel {
23 23
24enum ThreadStatus { 24enum ThreadStatus {
25 THREADSTATUS_RUNNING = 1, 25 THREADSTATUS_RUNNING = 1,
@@ -81,33 +81,32 @@ std::vector<Handle> g_thread_queue;
81Common::ThreadQueueList<Handle> g_thread_ready_queue; 81Common::ThreadQueueList<Handle> g_thread_ready_queue;
82 82
83Handle g_current_thread_handle; 83Handle g_current_thread_handle;
84
85Thread* g_current_thread; 84Thread* g_current_thread;
86 85
87 86
87/// Gets the current thread
88inline Thread* __GetCurrentThread() { 88inline Thread* __GetCurrentThread() {
89 return g_current_thread; 89 return g_current_thread;
90} 90}
91 91
92/// Sets the current thread
92inline void __SetCurrentThread(Thread* t) { 93inline void __SetCurrentThread(Thread* t) {
93 g_current_thread = t; 94 g_current_thread = t;
94 g_current_thread_handle = t->GetHandle(); 95 g_current_thread_handle = t->GetHandle();
95} 96}
96 97
97////////////////////////////////////////////////////////////////////////////////////////////////////
98
99/// Saves the current CPU context 98/// Saves the current CPU context
100void __KernelSaveContext(ThreadContext& ctx) { 99void __SaveContext(ThreadContext& ctx) {
101 Core::g_app_core->SaveContext(ctx); 100 Core::g_app_core->SaveContext(ctx);
102} 101}
103 102
104/// Loads a CPU context 103/// Loads a CPU context
105void __KernelLoadContext(const ThreadContext& ctx) { 104void __LoadContext(const ThreadContext& ctx) {
106 Core::g_app_core->LoadContext(ctx); 105 Core::g_app_core->LoadContext(ctx);
107} 106}
108 107
109/// Resets a thread 108/// Resets a thread
110void __KernelResetThread(Thread* t, s32 lowest_priority) { 109void __ResetThread(Thread* t, s32 lowest_priority) {
111 memset(&t->context, 0, sizeof(ThreadContext)); 110 memset(&t->context, 0, sizeof(ThreadContext));
112 111
113 t->context.pc = t->entry_point; 112 t->context.pc = t->entry_point;
@@ -121,7 +120,7 @@ void __KernelResetThread(Thread* t, s32 lowest_priority) {
121} 120}
122 121
123/// Change a thread to "ready" state 122/// Change a thread to "ready" state
124void __KernelChangeReadyState(Thread* t, bool ready) { 123void __ChangeReadyState(Thread* t, bool ready) {
125 Handle handle = t->GetHandle(); 124 Handle handle = t->GetHandle();
126 if (t->IsReady()) { 125 if (t->IsReady()) {
127 if (!ready) { 126 if (!ready) {
@@ -138,11 +137,11 @@ void __KernelChangeReadyState(Thread* t, bool ready) {
138} 137}
139 138
140/// Changes a threads state 139/// Changes a threads state
141void __KernelChangeThreadState(Thread* t, ThreadStatus new_status) { 140void __ChangeThreadState(Thread* t, ThreadStatus new_status) {
142 if (!t || t->status == new_status) { 141 if (!t || t->status == new_status) {
143 return; 142 return;
144 } 143 }
145 __KernelChangeReadyState(t, (new_status & THREADSTATUS_READY) != 0); 144 __ChangeReadyState(t, (new_status & THREADSTATUS_READY) != 0);
146 t->status = new_status; 145 t->status = new_status;
147 146
148 if (new_status == THREADSTATUS_WAIT) { 147 if (new_status == THREADSTATUS_WAIT) {
@@ -153,16 +152,75 @@ void __KernelChangeThreadState(Thread* t, ThreadStatus new_status) {
153} 152}
154 153
155/// Calls a thread by marking it as "ready" (note: will not actually execute until current thread yields) 154/// Calls a thread by marking it as "ready" (note: will not actually execute until current thread yields)
156void __KernelCallThread(Thread* t) { 155void __CallThread(Thread* t) {
157 // Stop waiting 156 // Stop waiting
158 if (t->wait_type != WAITTYPE_NONE) { 157 if (t->wait_type != WAITTYPE_NONE) {
159 t->wait_type = WAITTYPE_NONE; 158 t->wait_type = WAITTYPE_NONE;
160 } 159 }
161 __KernelChangeThreadState(t, THREADSTATUS_READY); 160 __ChangeThreadState(t, THREADSTATUS_READY);
161}
162
163/// Switches CPU context to that of the specified thread
164void __SwitchContext(Thread* t, const char* reason) {
165 Thread* cur = __GetCurrentThread();
166
167 // Save context for current thread
168 if (cur) {
169 __SaveContext(cur->context);
170
171 if (cur->IsRunning()) {
172 __ChangeReadyState(cur, true);
173 }
174 }
175 // Load context of new thread
176 if (t) {
177 __SetCurrentThread(t);
178 __ChangeReadyState(t, false);
179 t->status = (t->status | THREADSTATUS_RUNNING) & ~THREADSTATUS_READY;
180 t->wait_type = WAITTYPE_NONE;
181 __LoadContext(t->context);
182 } else {
183 __SetCurrentThread(NULL);
184 }
185}
186
187/// Gets the next thread that is ready to be run by priority
188Thread* __NextThread() {
189 Handle next;
190 Thread* cur = __GetCurrentThread();
191
192 if (cur && cur->IsRunning()) {
193 next = g_thread_ready_queue.pop_first_better(cur->current_priority);
194 } else {
195 next = g_thread_ready_queue.pop_first();
196 }
197 if (next < 0) {
198 return NULL;
199 }
200 return Kernel::g_object_pool.GetFast<Thread>(next);
201}
202
203/// Resumes a thread from waiting by marking it as "ready"
204void __ResumeThreadFromWait(Handle handle) {
205 u32 error;
206 Thread* t = Kernel::g_object_pool.Get<Thread>(handle, error);
207 if (t) {
208 t->status &= ~THREADSTATUS_WAIT;
209 if (!(t->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) {
210 __ChangeReadyState(t, true);
211 }
212 }
213}
214
215/// Puts a thread in the wait state for the given type/reason
216void __WaitCurThread(WaitType wait_type, const char* reason) {
217 Thread* t = __GetCurrentThread();
218 t->wait_type = wait_type;
219 __ChangeThreadState(t, ThreadStatus(THREADSTATUS_WAIT | (t->status & THREADSTATUS_SUSPEND)));
162} 220}
163 221
164/// Creates a new thread 222/// Creates a new thread
165Thread* __KernelCreateThread(Handle& handle, const char* name, u32 entry_point, s32 priority, 223Thread* CreateThread(Handle& handle, const char* name, u32 entry_point, s32 priority,
166 s32 processor_id, u32 stack_top, int stack_size) { 224 s32 processor_id, u32 stack_top, int stack_size) {
167 225
168 Thread* t = new Thread; 226 Thread* t = new Thread;
@@ -187,31 +245,31 @@ Thread* __KernelCreateThread(Handle& handle, const char* name, u32 entry_point,
187} 245}
188 246
189/// Creates a new thread - wrapper for external user 247/// Creates a new thread - wrapper for external user
190Handle __KernelCreateThread(const char* name, u32 entry_point, s32 priority, s32 processor_id, 248Handle CreateThread(const char* name, u32 entry_point, s32 priority, s32 processor_id,
191 u32 stack_top, int stack_size) { 249 u32 stack_top, int stack_size) {
192 if (name == NULL) { 250 if (name == NULL) {
193 ERROR_LOG(KERNEL, "__KernelCreateThread(): NULL name"); 251 ERROR_LOG(KERNEL, "CreateThread(): NULL name");
194 return -1; 252 return -1;
195 } 253 }
196 if ((u32)stack_size < 0x200) { 254 if ((u32)stack_size < 0x200) {
197 ERROR_LOG(KERNEL, "__KernelCreateThread(name=%s): invalid stack_size=0x%08X", name, 255 ERROR_LOG(KERNEL, "CreateThread(name=%s): invalid stack_size=0x%08X", name,
198 stack_size); 256 stack_size);
199 return -1; 257 return -1;
200 } 258 }
201 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { 259 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) {
202 s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); 260 s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
203 WARN_LOG(KERNEL, "__KernelCreateThread(name=%s): invalid priority=0x%08X, clamping to %08X", 261 WARN_LOG(KERNEL, "CreateThread(name=%s): invalid priority=0x%08X, clamping to %08X",
204 name, priority, new_priority); 262 name, priority, new_priority);
205 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm 263 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
206 // validity of this 264 // validity of this
207 priority = new_priority; 265 priority = new_priority;
208 } 266 }
209 if (!Memory::GetPointer(entry_point)) { 267 if (!Memory::GetPointer(entry_point)) {
210 ERROR_LOG(KERNEL, "__KernelCreateThread(name=%s): invalid entry %08x", name, entry_point); 268 ERROR_LOG(KERNEL, "CreateThread(name=%s): invalid entry %08x", name, entry_point);
211 return -1; 269 return -1;
212 } 270 }
213 Handle handle; 271 Handle handle;
214 Thread* t = __KernelCreateThread(handle, name, entry_point, priority, processor_id, stack_top, 272 Thread* t = CreateThread(handle, name, entry_point, priority, processor_id, stack_top,
215 stack_size); 273 stack_size);
216 274
217 HLE::EatCycles(32000); 275 HLE::EatCycles(32000);
@@ -220,114 +278,62 @@ Handle __KernelCreateThread(const char* name, u32 entry_point, s32 priority, s32
220 // Technically, this should not eat all at once, and reschedule in the middle, but that's hard. 278 // Technically, this should not eat all at once, and reschedule in the middle, but that's hard.
221 HLE::ReSchedule("thread created"); 279 HLE::ReSchedule("thread created");
222 280
223 __KernelCallThread(t); 281 __CallThread(t);
224 282
225 return handle; 283 return handle;
226} 284}
227 285
228/// Switches CPU context to that of the specified thread 286/// Gets the current thread
229void __KernelSwitchContext(Thread* t, const char* reason) { 287Handle GetCurrentThread() {
230 Thread* cur = __GetCurrentThread(); 288 return __GetCurrentThread()->GetHandle();
231
232 // Save context for current thread
233 if (cur) {
234 __KernelSaveContext(cur->context);
235
236 if (cur->IsRunning()) {
237 __KernelChangeReadyState(cur, true);
238 }
239 }
240 // Load context of new thread
241 if (t) {
242 __SetCurrentThread(t);
243 __KernelChangeReadyState(t, false);
244 t->status = (t->status | THREADSTATUS_RUNNING) & ~THREADSTATUS_READY;
245 t->wait_type = WAITTYPE_NONE;
246 __KernelLoadContext(t->context);
247 } else {
248 __SetCurrentThread(NULL);
249 }
250}
251
252/// Gets the next thread that is ready to be run by priority
253Thread* __KernelNextThread() {
254 Handle next;
255 Thread* cur = __GetCurrentThread();
256
257 if (cur && cur->IsRunning()) {
258 next = g_thread_ready_queue.pop_first_better(cur->current_priority);
259 } else {
260 next = g_thread_ready_queue.pop_first();
261 }
262 if (next < 0) {
263 return NULL;
264 }
265 return Kernel::g_object_pool.GetFast<Thread>(next);
266} 289}
267 290
268/// Sets up the primary application thread 291/// Sets up the primary application thread
269Handle __KernelSetupMainThread(s32 priority, int stack_size) { 292Handle SetupMainThread(s32 priority, int stack_size) {
270 Handle handle; 293 Handle handle;
271 294
272 // Initialize new "main" thread 295 // Initialize new "main" thread
273 Thread* t = __KernelCreateThread(handle, "main", Core::g_app_core->GetPC(), priority, 296 Thread* t = CreateThread(handle, "main", Core::g_app_core->GetPC(), priority,
274 THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size); 297 THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size);
275 298
276 __KernelResetThread(t, 0); 299 __ResetThread(t, 0);
277 300
278 // If running another thread already, set it to "ready" state 301 // If running another thread already, set it to "ready" state
279 Thread* cur = __GetCurrentThread(); 302 Thread* cur = __GetCurrentThread();
280 if (cur && cur->IsRunning()) { 303 if (cur && cur->IsRunning()) {
281 __KernelChangeReadyState(cur, true); 304 __ChangeReadyState(cur, true);
282 } 305 }
283 306
284 // Run new "main" thread 307 // Run new "main" thread
285 __SetCurrentThread(t); 308 __SetCurrentThread(t);
286 t->status = THREADSTATUS_RUNNING; 309 t->status = THREADSTATUS_RUNNING;
287 __KernelLoadContext(t->context); 310 __LoadContext(t->context);
288 311
289 return handle; 312 return handle;
290} 313}
291 314
292/// Resumes a thread from waiting by marking it as "ready"
293void __KernelResumeThreadFromWait(Handle handle) {
294 u32 error;
295 Thread* t = Kernel::g_object_pool.Get<Thread>(handle, error);
296 if (t) {
297 t->status &= ~THREADSTATUS_WAIT;
298 if (!(t->status & (THREADSTATUS_WAITSUSPEND | THREADSTATUS_DORMANT | THREADSTATUS_DEAD))) {
299 __KernelChangeReadyState(t, true);
300 }
301 }
302}
303
304/// Puts a thread in the wait state for the given type/reason
305void __KernelWaitCurThread(WaitType wait_type, const char* reason) {
306 Thread* t = __GetCurrentThread();
307 t->wait_type = wait_type;
308 __KernelChangeThreadState(t, ThreadStatus(THREADSTATUS_WAIT | (t->status & THREADSTATUS_SUSPEND)));
309}
310
311/// Reschedules to the next available thread (call after current thread is suspended) 315/// Reschedules to the next available thread (call after current thread is suspended)
312void __KernelReschedule(const char* reason) { 316void Reschedule(const char* reason) {
313 Thread* next = __KernelNextThread(); 317 Thread* next = __NextThread();
314 if (next > 0) { 318 if (next > 0) {
315 __KernelSwitchContext(next, reason); 319 __SwitchContext(next, reason);
316 } 320 }
317} 321}
318 322
319//////////////////////////////////////////////////////////////////////////////////////////////////// 323////////////////////////////////////////////////////////////////////////////////////////////////////
320 324
321/// Put current thread in a wait state - on WaitSynchronization 325/// Put current thread in a wait state - on WaitSynchronization
322void __KernelWaitThread_Synchronization() { 326void WaitThread_Synchronization() {
323 // TODO(bunnei): Just a placeholder function for now... FixMe 327 // TODO(bunnei): Just a placeholder function for now... FixMe
324 __KernelWaitCurThread(WAITTYPE_SYNCH, "waitSynchronization called"); 328 __WaitCurThread(WAITTYPE_SYNCH, "waitSynchronization called");
325} 329}
326 330
327//////////////////////////////////////////////////////////////////////////////////////////////////// 331////////////////////////////////////////////////////////////////////////////////////////////////////
328 332
329void __KernelThreadingInit() { 333void ThreadingInit() {
330} 334}
331 335
332void __KernelThreadingShutdown() { 336void ThreadingShutdown() {
333} 337}
338
339} // namespace