diff options
| author | 2015-01-08 18:45:35 -0500 | |
|---|---|---|
| committer | 2015-01-08 18:45:35 -0500 | |
| commit | cf1bbe8705b04776be49c01265b11babbda59b2e (patch) | |
| tree | 0bf742b6be09aa56c4a49f57667b463399b45d93 /src | |
| parent | Merge pull request #446 from lioncash/umaal (diff) | |
| parent | SVC: Fixed SleepThread. (diff) | |
| download | yuzu-cf1bbe8705b04776be49c01265b11babbda59b2e.tar.gz yuzu-cf1bbe8705b04776be49c01265b11babbda59b2e.tar.xz yuzu-cf1bbe8705b04776be49c01265b11babbda59b2e.zip | |
Merge pull request #443 from Subv/sleep_thread
SVC: Fixed SleepThread
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 40 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 7 | ||||
| -rw-r--r-- | src/core/hle/svc.cpp | 4 |
3 files changed, 43 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() { |
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(); | |||
| 88 | void WaitCurrentThread(WaitType wait_type, Handle wait_handle=GetCurrentThreadHandle()); | 88 | void WaitCurrentThread(WaitType wait_type, Handle wait_handle=GetCurrentThreadHandle()); |
| 89 | 89 | ||
| 90 | /** | 90 | /** |
| 91 | * Schedules an event to wake up the specified thread after the specified delay. | ||
| 92 | * @param handle The thread handle. | ||
| 93 | * @param nanoseconds The time this thread will be allowed to sleep for. | ||
| 94 | */ | ||
| 95 | void WakeThreadAfterDelay(Handle handle, s64 nanoseconds); | ||
| 96 | |||
| 97 | /** | ||
| 91 | * Puts the current thread in the wait state for the given type | 98 | * Puts the current thread in the wait state for the given type |
| 92 | * @param wait_type Type of wait | 99 | * @param wait_type Type of wait |
| 93 | * @param wait_handle Handle of Kernel object that we are waiting on, defaults to current thread | 100 | * @param wait_handle Handle of Kernel object that we are waiting on, defaults to current thread |
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index c25409a9f..4003e0ba9 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -344,6 +344,10 @@ static void SleepThread(s64 nanoseconds) { | |||
| 344 | 344 | ||
| 345 | // Sleep current thread and check for next thread to schedule | 345 | // Sleep current thread and check for next thread to schedule |
| 346 | Kernel::WaitCurrentThread(WAITTYPE_SLEEP); | 346 | Kernel::WaitCurrentThread(WAITTYPE_SLEEP); |
| 347 | |||
| 348 | // Create an event to wake the thread up after the specified nanosecond delay has passed | ||
| 349 | Kernel::WakeThreadAfterDelay(Kernel::GetCurrentThreadHandle(), nanoseconds); | ||
| 350 | |||
| 347 | HLE::Reschedule(__func__); | 351 | HLE::Reschedule(__func__); |
| 348 | } | 352 | } |
| 349 | 353 | ||