summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/thread.cpp
diff options
context:
space:
mode:
authorGravatar bunnei2014-05-17 00:56:00 -0400
committerGravatar bunnei2014-05-17 00:56:00 -0400
commit14ae026386cf3f984d60401e2104165c3ca3266b (patch)
treeccd112ad636e166799d321a8072582a4e66150c1 /src/core/hle/kernel/thread.cpp
parentadded MIN, MAX, and CLAMP macros to common_funcs (diff)
downloadyuzu-14ae026386cf3f984d60401e2104165c3ca3266b.tar.gz
yuzu-14ae026386cf3f984d60401e2104165c3ca3266b.tar.xz
yuzu-14ae026386cf3f984d60401e2104165c3ca3266b.zip
- added enum ThreadProcessorId
- reorganized some kernel thread functions - added placeholder __KernelWaitThread_Synchronization function
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
-rw-r--r--src/core/hle/kernel/thread.cpp141
1 files changed, 90 insertions, 51 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 76a73747d..b967b3c62 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -21,20 +21,14 @@
21 21
22// Enums 22// Enums
23 23
24enum ThreadPriority {
25 THREADPRIO_HIGHEST = 0,
26 THREADPRIO_DEFAULT = 16,
27 THREADPRIO_LOWEST = 31,
28};
29
30enum ThreadStatus { 24enum ThreadStatus {
31 THREADSTATUS_RUNNING = 1, 25 THREADSTATUS_RUNNING = 1,
32 THREADSTATUS_READY = 2, 26 THREADSTATUS_READY = 2,
33 THREADSTATUS_WAIT = 4, 27 THREADSTATUS_WAIT = 4,
34 THREADSTATUS_SUSPEND = 8, 28 THREADSTATUS_SUSPEND = 8,
35 THREADSTATUS_DORMANT = 16, 29 THREADSTATUS_DORMANT = 16,
36 THREADSTATUS_DEAD = 32, 30 THREADSTATUS_DEAD = 32,
37 THREADSTATUS_WAITSUSPEND = THREADSTATUS_WAIT | THREADSTATUS_SUSPEND 31 THREADSTATUS_WAITSUSPEND = THREADSTATUS_WAIT | THREADSTATUS_SUSPEND
38}; 32};
39 33
40enum WaitType { 34enum WaitType {
@@ -46,8 +40,6 @@ enum WaitType {
46 WAITTYPE_VBLANK, 40 WAITTYPE_VBLANK,
47 WAITTYPE_MUTEX, 41 WAITTYPE_MUTEX,
48 WAITTYPE_SYNCH, 42 WAITTYPE_SYNCH,
49
50 NUM_WAITTYPES
51}; 43};
52 44
53typedef s32 Handle; 45typedef s32 Handle;
@@ -164,32 +156,6 @@ void __KernelResetThread(Thread *t, s32 lowest_priority) {
164 t->wait_type = WAITTYPE_NONE; 156 t->wait_type = WAITTYPE_NONE;
165} 157}
166 158
167/// Creates a new thread
168Thread *__KernelCreateThread(Handle &handle, const char *name, u32 entry_point, s32 priority,
169 s32 processor_id, u32 stack_top, int stack_size) {
170 static u32 _handle_count = 1;
171
172 Thread *t = new Thread;
173
174 handle = (_handle_count++);
175
176 g_thread_queue.push_back(handle);
177 g_thread_ready_queue.prepare(priority);
178
179 t->status = THREADSTATUS_DORMANT;
180 t->entry_point = entry_point;
181 t->stack_top = stack_top;
182 t->stack_size = stack_size;
183 t->initial_priority = t->current_priority = priority;
184 t->processor_id = processor_id;
185 t->wait_type = WAITTYPE_NONE;
186
187 strncpy(t->name, name, KERNEL_MAX_NAME_LENGTH);
188 t->name[KERNEL_MAX_NAME_LENGTH] = '\0';
189
190 return t;
191}
192
193/// Change a thread to "ready" state 159/// Change a thread to "ready" state
194void __KernelChangeReadyState(Thread *t, bool ready) { 160void __KernelChangeReadyState(Thread *t, bool ready) {
195 Handle handle = t->GetHandle(); 161 Handle handle = t->GetHandle();
@@ -222,6 +188,79 @@ void __KernelChangeThreadState(Thread *t, ThreadStatus new_status) {
222 } 188 }
223} 189}
224 190
191/// Calls a thread by marking it as "ready" (note: will not actually execute until current thread yields)
192void __KernelCallThread(Thread *t) {
193 // Stop waiting
194 if (t->wait_type != WAITTYPE_NONE) {
195 t->wait_type = WAITTYPE_NONE;
196 }
197 __KernelChangeThreadState(t, THREADSTATUS_READY);
198}
199
200/// Creates a new thread
201Thread *__KernelCreateThread(Handle &handle, const char *name, u32 entry_point, s32 priority,
202 s32 processor_id, u32 stack_top, int stack_size) {
203
204 Thread *t = new Thread;
205
206 handle = g_kernel_objects.Create(t);
207
208 g_thread_queue.push_back(handle);
209 g_thread_ready_queue.prepare(priority);
210
211 t->status = THREADSTATUS_DORMANT;
212 t->entry_point = entry_point;
213 t->stack_top = stack_top;
214 t->stack_size = stack_size;
215 t->initial_priority = t->current_priority = priority;
216 t->processor_id = processor_id;
217 t->wait_type = WAITTYPE_NONE;
218
219 strncpy(t->name, name, KERNEL_MAX_NAME_LENGTH);
220 t->name[KERNEL_MAX_NAME_LENGTH] = '\0';
221
222 return t;
223}
224
225/// Creates a new thread - wrapper for external user
226Handle __KernelCreateThread(const char *name, u32 entry_point, s32 priority, s32 processor_id,
227 u32 stack_top, int stack_size) {
228 if (name == NULL) {
229 ERROR_LOG(KERNEL, "__KernelCreateThread(): NULL name");
230 return -1;
231 }
232 if ((u32)stack_size < 0x200) {
233 ERROR_LOG(KERNEL, "__KernelCreateThread(name=%s): invalid stack_size=0x%08X", name,
234 stack_size);
235 return -1;
236 }
237 if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) {
238 s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST);
239 WARN_LOG(KERNEL, "__KernelCreateThread(name=%s): invalid priority=0x%08X, clamping to %08X",
240 name, priority, new_priority);
241 // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
242 // validity of this
243 priority = new_priority;
244 }
245 if (!Memory::GetPointer(entry_point)) {
246 ERROR_LOG(KERNEL, "__KernelCreateThread(name=%s): invalid entry %08x", name, entry_point);
247 return -1;
248 }
249 Handle handle;
250 Thread *t = __KernelCreateThread(handle, name, entry_point, priority, processor_id, stack_top,
251 stack_size);
252
253 HLE::EatCycles(32000);
254
255 // This won't schedule to the new thread, but it may to one woken from eating cycles.
256 // Technically, this should not eat all at once, and reschedule in the middle, but that's hard.
257 HLE::ReSchedule("thread created");
258
259 __KernelCallThread(t);
260
261 return handle;
262}
263
225/// Switches CPU context to that of the specified thread 264/// Switches CPU context to that of the specified thread
226void __KernelSwitchContext(Thread* t, const char *reason) { 265void __KernelSwitchContext(Thread* t, const char *reason) {
227 Thread *cur = __GetCurrentThread(); 266 Thread *cur = __GetCurrentThread();
@@ -262,22 +301,13 @@ Thread *__KernelNextThread() {
262 return g_kernel_objects.GetFast<Thread>(next); 301 return g_kernel_objects.GetFast<Thread>(next);
263} 302}
264 303
265/// Calls a thread by marking it as "ready" (note: will not actually execute until current thread yields)
266void __KernelCallThread(Thread *t) {
267 // Stop waiting
268 if (t->wait_type != WAITTYPE_NONE) {
269 t->wait_type = WAITTYPE_NONE;
270 }
271 __KernelChangeThreadState(t, THREADSTATUS_READY);
272}
273
274/// Sets up the primary application thread 304/// Sets up the primary application thread
275Handle __KernelSetupMainThread(s32 priority, int stack_size) { 305Handle __KernelSetupMainThread(s32 priority, int stack_size) {
276 Handle handle; 306 Handle handle;
277 307
278 // Initialize new "main" thread 308 // Initialize new "main" thread
279 Thread *t = __KernelCreateThread(handle, "main", Core::g_app_core->GetPC(), priority, 309 Thread *t = __KernelCreateThread(handle, "main", Core::g_app_core->GetPC(), priority,
280 0xFFFFFFFE, Memory::SCRATCHPAD_VADDR_END, stack_size); 310 THREADPROCESSORID_0, Memory::SCRATCHPAD_VADDR_END, stack_size);
281 311
282 __KernelResetThread(t, 0); 312 __KernelResetThread(t, 0);
283 313
@@ -322,6 +352,15 @@ void __KernelReschedule(const char *reason) {
322 } 352 }
323} 353}
324 354
355////////////////////////////////////////////////////////////////////////////////////////////////////
356
357/// Wait thread - on WaitSynchronization
358void __KernelWaitThread_Synchronization() {
359 // TODO(bunnei): Just a placeholder function for now... FixMe
360 __KernelWaitCurThread(WAITTYPE_SYNCH, "waitSynchronization called");
361}
362
363////////////////////////////////////////////////////////////////////////////////////////////////////
325 364
326void __KernelThreadingInit() { 365void __KernelThreadingInit() {
327} 366}