summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/thread.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
-rw-r--r--src/core/hle/kernel/thread.cpp40
1 files changed, 32 insertions, 8 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 58fb62e89..954bd09a0 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -308,6 +308,37 @@ void WaitCurrentThread(WaitType wait_type, Handle wait_handle, VAddr wait_addres
308 GetCurrentThread()->wait_address = wait_address; 308 GetCurrentThread()->wait_address = wait_address;
309} 309}
310 310
311/// Event type for the thread wake up event
312static int ThreadWakeupEventType = -1;
313
314/// Callback that will wake up the thread it was scheduled for
315static void ThreadWakeupCallback(u64 parameter, int cycles_late) {
316 Handle handle = static_cast<Handle>(parameter);
317 Thread* thread = Kernel::g_handle_table.Get<Thread>(handle);
318 if (thread == nullptr) {
319 LOG_ERROR(Kernel, "Thread doesn't exist %u", handle);
320 return;
321 }
322
323 Kernel::ResumeThreadFromWait(handle);
324}
325
326
327void WakeThreadAfterDelay(Handle handle, s64 nanoseconds) {
328 // Don't schedule a wakeup if the thread wants to wait forever
329 if (nanoseconds == -1)
330 return;
331
332 Thread* thread = Kernel::g_handle_table.Get<Thread>(handle);
333 if (thread == nullptr) {
334 LOG_ERROR(Kernel, "Thread doesn't exist %u", handle);
335 return;
336 }
337
338 u64 microseconds = nanoseconds / 1000;
339 CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, handle);
340}
341
311/// Resumes a thread from waiting by marking it as "ready" 342/// Resumes a thread from waiting by marking it as "ready"
312void ResumeThreadFromWait(Handle handle) { 343void ResumeThreadFromWait(Handle handle) {
313 Thread* thread = Kernel::g_handle_table.Get<Thread>(handle); 344 Thread* thread = Kernel::g_handle_table.Get<Thread>(handle);
@@ -499,14 +530,6 @@ void Reschedule() {
499 thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, thread->wait_handle); 530 thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, thread->wait_handle);
500 } 531 }
501 } 532 }
502
503 // TODO(bunnei): Hack - There is no timing mechanism yet to wake up a thread if it has been put
504 // to sleep. So, we'll just immediately set it to "ready" again after an attempted context
505 // switch has occurred. This results in the current thread yielding on a sleep once, and then it
506 // will immediately be placed back in the queue for execution.
507
508 if (CheckWaitType(prev, WAITTYPE_SLEEP))
509 ResumeThreadFromWait(prev->GetHandle());
510} 533}
511 534
512bool IsIdleThread(Handle handle) { 535bool IsIdleThread(Handle handle) {
@@ -533,6 +556,7 @@ ResultCode GetThreadId(u32* thread_id, Handle handle) {
533 556
534void ThreadingInit() { 557void ThreadingInit() {
535 next_thread_id = INITIAL_THREAD_ID; 558 next_thread_id = INITIAL_THREAD_ID;
559 ThreadWakeupEventType = CoreTiming::RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback);
536} 560}
537 561
538void ThreadingShutdown() { 562void ThreadingShutdown() {