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.cpp46
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 */
172static void SwitchContext(Thread* new_thread) { 172static 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
455SharedPtr<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
465SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) { 459SharedPtr<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
480void Reschedule() { 474void 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
501void Thread::SetWaitSynchronizationResult(ResultCode result) { 496void 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
528void ThreadingShutdown() { 520void ThreadingShutdown() {