diff options
| author | 2015-01-07 16:40:08 -0500 | |
|---|---|---|
| committer | 2015-01-08 18:39:12 -0500 | |
| commit | dfc440785af73e400e7672377bdf7f65c9eca61c (patch) | |
| tree | 16981e2ec3d97455abe361bf6ebb6ef161df1c19 /src/core/hle/kernel/thread.cpp | |
| parent | Merge pull request #439 from Subv/idle_thread_m (diff) | |
| download | yuzu-dfc440785af73e400e7672377bdf7f65c9eca61c.tar.gz yuzu-dfc440785af73e400e7672377bdf7f65c9eca61c.tar.xz yuzu-dfc440785af73e400e7672377bdf7f65c9eca61c.zip | |
SVC: Fixed SleepThread.
It will now properly wait the specified number of nanoseconds and then wake up the thread.
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 40 |
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 | ||
| 312 | static int ThreadWakeupEventType = -1; | ||
| 313 | |||
| 314 | /// Callback that will wake up the thread it was scheduled for | ||
| 315 | static 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 | |||
| 327 | void 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" |
| 312 | void ResumeThreadFromWait(Handle handle) { | 343 | void 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 | ||
| 512 | bool IsIdleThread(Handle handle) { | 535 | bool IsIdleThread(Handle handle) { |
| @@ -533,6 +556,7 @@ ResultCode GetThreadId(u32* thread_id, Handle handle) { | |||
| 533 | 556 | ||
| 534 | void ThreadingInit() { | 557 | void 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 | ||
| 538 | void ThreadingShutdown() { | 562 | void ThreadingShutdown() { |