diff options
author | Subv <subv2112@gmail.com> | 2015-01-07 22:40:08 +0100 |
---|---|---|
committer | Subv <subv2112@gmail.com> | 2015-01-09 00:39:12 +0100 |
commit | dfc440785af73e400e7672377bdf7f65c9eca61c (patch) | |
tree | 16981e2ec3d97455abe361bf6ebb6ef161df1c19 /src/core/hle/kernel | |
parent | Merge pull request #439 from Subv/idle_thread_m (diff) | |
download | yuzu-dfc440785af73e400e7672377bdf7f65c9eca61c.tar yuzu-dfc440785af73e400e7672377bdf7f65c9eca61c.tar.gz yuzu-dfc440785af73e400e7672377bdf7f65c9eca61c.tar.bz2 yuzu-dfc440785af73e400e7672377bdf7f65c9eca61c.tar.lz yuzu-dfc440785af73e400e7672377bdf7f65c9eca61c.tar.xz yuzu-dfc440785af73e400e7672377bdf7f65c9eca61c.tar.zst yuzu-dfc440785af73e400e7672377bdf7f65c9eca61c.zip |
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r-- | src/core/hle/kernel/thread.cpp | 40 | ||||
-rw-r--r-- | src/core/hle/kernel/thread.h | 7 |
2 files changed, 39 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 GetCurrentThread()->wait_address = wait_address; } +/// Event type for the thread wake up event +static int ThreadWakeupEventType = -1; + +/// Callback that will wake up the thread it was scheduled for +static void ThreadWakeupCallback(u64 parameter, int cycles_late) { + Handle handle = static_cast<Handle>(parameter); + Thread* thread = Kernel::g_handle_table.Get<Thread>(handle); + if (thread == nullptr) { + LOG_ERROR(Kernel, "Thread doesn't exist %u", handle); + return; + } + + Kernel::ResumeThreadFromWait(handle); +} + + +void WakeThreadAfterDelay(Handle handle, s64 nanoseconds) { + // Don't schedule a wakeup if the thread wants to wait forever + if (nanoseconds == -1) + return; + + Thread* thread = Kernel::g_handle_table.Get<Thread>(handle); + if (thread == nullptr) { + LOG_ERROR(Kernel, "Thread doesn't exist %u", handle); + return; + } + + u64 microseconds = nanoseconds / 1000; + CoreTiming::ScheduleEvent(usToCycles(microseconds), ThreadWakeupEventType, handle); +} + /// Resumes a thread from waiting by marking it as "ready" void ResumeThreadFromWait(Handle handle) { Thread* thread = Kernel::g_handle_table.Get<Thread>(handle); @@ -499,14 +530,6 @@ void Reschedule() { thread->GetHandle(), thread->current_priority, thread->status, thread->wait_type, thread->wait_handle); } } - - // TODO(bunnei): Hack - There is no timing mechanism yet to wake up a thread if it has been put - // to sleep. So, we'll just immediately set it to "ready" again after an attempted context - // switch has occurred. This results in the current thread yielding on a sleep once, and then it - // will immediately be placed back in the queue for execution. - - if (CheckWaitType(prev, WAITTYPE_SLEEP)) - ResumeThreadFromWait(prev->GetHandle()); } bool IsIdleThread(Handle handle) { @@ -533,6 +556,7 @@ ResultCode GetThreadId(u32* thread_id, Handle handle) { void ThreadingInit() { next_thread_id = INITIAL_THREAD_ID; + ThreadWakeupEventType = CoreTiming::RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback); } void ThreadingShutdown() { diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index dfe92d162..e6961e279 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -88,6 +88,13 @@ Handle GetCurrentThreadHandle(); void WaitCurrentThread(WaitType wait_type, Handle wait_handle=GetCurrentThreadHandle()); /** + * Schedules an event to wake up the specified thread after the specified delay. + * @param handle The thread handle. + * @param nanoseconds The time this thread will be allowed to sleep for. + */ +void WakeThreadAfterDelay(Handle handle, s64 nanoseconds); + +/** * Puts the current thread in the wait state for the given type * @param wait_type Type of wait * @param wait_handle Handle of Kernel object that we are waiting on, defaults to current thread |