diff options
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 46 |
1 files changed, 19 insertions, 27 deletions
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 3e70d3995..c7731c9e9 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -158,7 +158,7 @@ static void PriorityBoostStarvedThreads() { | |||
| 158 | 158 | ||
| 159 | u64 delta = current_ticks - thread->last_running_ticks; | 159 | u64 delta = current_ticks - thread->last_running_ticks; |
| 160 | 160 | ||
| 161 | if (thread->status == THREADSTATUS_READY && delta > boost_timeout && !thread->idle) { | 161 | if (thread->status == THREADSTATUS_READY && delta > boost_timeout) { |
| 162 | const s32 priority = std::max(ready_queue.get_first()->current_priority - 1, 0); | 162 | const s32 priority = std::max(ready_queue.get_first()->current_priority - 1, 0); |
| 163 | thread->BoostPriority(priority); | 163 | thread->BoostPriority(priority); |
| 164 | } | 164 | } |
| @@ -170,8 +170,6 @@ static void PriorityBoostStarvedThreads() { | |||
| 170 | * @param new_thread The thread to switch to | 170 | * @param new_thread The thread to switch to |
| 171 | */ | 171 | */ |
| 172 | static void SwitchContext(Thread* new_thread) { | 172 | static void SwitchContext(Thread* new_thread) { |
| 173 | DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running."); | ||
| 174 | |||
| 175 | Thread* previous_thread = GetCurrentThread(); | 173 | Thread* previous_thread = GetCurrentThread(); |
| 176 | 174 | ||
| 177 | // Save context for previous thread | 175 | // Save context for previous thread |
| @@ -189,6 +187,8 @@ static void SwitchContext(Thread* new_thread) { | |||
| 189 | 187 | ||
| 190 | // Load context of new thread | 188 | // Load context of new thread |
| 191 | if (new_thread) { | 189 | if (new_thread) { |
| 190 | DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running."); | ||
| 191 | |||
| 192 | current_thread = new_thread; | 192 | current_thread = new_thread; |
| 193 | 193 | ||
| 194 | ready_queue.remove(new_thread->current_priority, new_thread); | 194 | ready_queue.remove(new_thread->current_priority, new_thread); |
| @@ -216,6 +216,10 @@ static Thread* PopNextReadyThread() { | |||
| 216 | // We have to do better than the current thread. | 216 | // We have to do better than the current thread. |
| 217 | // This call returns null when that's not possible. | 217 | // This call returns null when that's not possible. |
| 218 | next = ready_queue.pop_first_better(thread->current_priority); | 218 | next = ready_queue.pop_first_better(thread->current_priority); |
| 219 | if (!next) { | ||
| 220 | // Otherwise just keep going with the current thread | ||
| 221 | next = thread; | ||
| 222 | } | ||
| 219 | } else { | 223 | } else { |
| 220 | next = ready_queue.pop_first(); | 224 | next = ready_queue.pop_first(); |
| 221 | } | 225 | } |
| @@ -452,16 +456,6 @@ void Thread::BoostPriority(s32 priority) { | |||
| 452 | current_priority = priority; | 456 | current_priority = priority; |
| 453 | } | 457 | } |
| 454 | 458 | ||
| 455 | SharedPtr<Thread> SetupIdleThread() { | ||
| 456 | // We need to pass a few valid values to get around parameter checking in Thread::Create. | ||
| 457 | // TODO(yuriks): Figure out a way to avoid passing the bogus VAddr parameter | ||
| 458 | auto thread = Thread::Create("idle", Memory::TLS_AREA_VADDR, THREADPRIO_LOWEST, 0, | ||
| 459 | THREADPROCESSORID_0, 0).MoveFrom(); | ||
| 460 | |||
| 461 | thread->idle = true; | ||
| 462 | return thread; | ||
| 463 | } | ||
| 464 | |||
| 465 | SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) { | 459 | SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) { |
| 466 | DEBUG_ASSERT(!GetCurrentThread()); | 460 | DEBUG_ASSERT(!GetCurrentThread()); |
| 467 | 461 | ||
| @@ -478,24 +472,25 @@ SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) { | |||
| 478 | } | 472 | } |
| 479 | 473 | ||
| 480 | void Reschedule() { | 474 | void Reschedule() { |
| 481 | Thread* prev = GetCurrentThread(); | ||
| 482 | |||
| 483 | PriorityBoostStarvedThreads(); | 475 | PriorityBoostStarvedThreads(); |
| 484 | 476 | ||
| 477 | Thread* cur = GetCurrentThread(); | ||
| 485 | Thread* next = PopNextReadyThread(); | 478 | Thread* next = PopNextReadyThread(); |
| 486 | HLE::g_reschedule = false; | 479 | HLE::g_reschedule = false; |
| 487 | 480 | ||
| 488 | if (next != nullptr) { | 481 | // Don't bother switching to the same thread |
| 489 | LOG_TRACE(Kernel, "context switch %u -> %u", prev->GetObjectId(), next->GetObjectId()); | 482 | if (next == cur) |
| 490 | SwitchContext(next); | 483 | return; |
| 491 | } else { | ||
| 492 | LOG_TRACE(Kernel, "cannot context switch from %u, no higher priority thread!", prev->GetObjectId()); | ||
| 493 | 484 | ||
| 494 | for (auto& thread : thread_list) { | 485 | if (cur && next) { |
| 495 | LOG_TRACE(Kernel, "\tid=%u prio=0x%02X, status=0x%08X", thread->GetObjectId(), | 486 | LOG_TRACE(Kernel, "context switch %u -> %u", cur->GetObjectId(), next->GetObjectId()); |
| 496 | thread->current_priority, thread->status); | 487 | } else if (cur) { |
| 497 | } | 488 | LOG_TRACE(Kernel, "context switch %u -> idle", cur->GetObjectId()); |
| 489 | } else { | ||
| 490 | LOG_TRACE(Kernel, "context switch idle -> %u", next->GetObjectId()); | ||
| 498 | } | 491 | } |
| 492 | |||
| 493 | SwitchContext(next); | ||
| 499 | } | 494 | } |
| 500 | 495 | ||
| 501 | void Thread::SetWaitSynchronizationResult(ResultCode result) { | 496 | void Thread::SetWaitSynchronizationResult(ResultCode result) { |
| @@ -520,9 +515,6 @@ void ThreadingInit() { | |||
| 520 | 515 | ||
| 521 | thread_list.clear(); | 516 | thread_list.clear(); |
| 522 | ready_queue.clear(); | 517 | ready_queue.clear(); |
| 523 | |||
| 524 | // Setup the idle thread | ||
| 525 | SetupIdleThread(); | ||
| 526 | } | 518 | } |
| 527 | 519 | ||
| 528 | void ThreadingShutdown() { | 520 | void ThreadingShutdown() { |