diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/core.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 46 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 17 |
3 files changed, 21 insertions, 46 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index b5c258230..53aae8c2f 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -24,9 +24,9 @@ ARM_Interface* g_sys_core = nullptr; ///< ARM11 system (OS) core | |||
| 24 | 24 | ||
| 25 | /// Run the core CPU loop | 25 | /// Run the core CPU loop |
| 26 | void RunLoop(int tight_loop) { | 26 | void RunLoop(int tight_loop) { |
| 27 | // If the current thread is an idle thread, then don't execute instructions, | 27 | // If we don't have a currently active thread then don't execute instructions, |
| 28 | // instead advance to the next event and try to yield to the next thread | 28 | // instead advance to the next event and try to yield to the next thread |
| 29 | if (Kernel::GetCurrentThread()->IsIdle()) { | 29 | if (Kernel::GetCurrentThread() == nullptr) { |
| 30 | LOG_TRACE(Core_ARM11, "Idling"); | 30 | LOG_TRACE(Core_ARM11, "Idling"); |
| 31 | CoreTiming::Idle(); | 31 | CoreTiming::Idle(); |
| 32 | CoreTiming::Advance(); | 32 | CoreTiming::Advance(); |
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() { |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 1d4d010fe..a06c7d4fe 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -73,12 +73,6 @@ public: | |||
| 73 | void Acquire() override; | 73 | void Acquire() override; |
| 74 | 74 | ||
| 75 | /** | 75 | /** |
| 76 | * Checks if the thread is an idle (stub) thread | ||
| 77 | * @return True if the thread is an idle (stub) thread, false otherwise | ||
| 78 | */ | ||
| 79 | inline bool IsIdle() const { return idle; } | ||
| 80 | |||
| 81 | /** | ||
| 82 | * Gets the thread's current priority | 76 | * Gets the thread's current priority |
| 83 | * @return The current thread's priority | 77 | * @return The current thread's priority |
| 84 | */ | 78 | */ |
| @@ -170,9 +164,6 @@ public: | |||
| 170 | 164 | ||
| 171 | std::string name; | 165 | std::string name; |
| 172 | 166 | ||
| 173 | /// Whether this thread is intended to never actually be executed, i.e. always idle | ||
| 174 | bool idle = false; | ||
| 175 | |||
| 176 | private: | 167 | private: |
| 177 | Thread(); | 168 | Thread(); |
| 178 | ~Thread() override; | 169 | ~Thread() override; |
| @@ -231,14 +222,6 @@ void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wa | |||
| 231 | void WaitCurrentThread_ArbitrateAddress(VAddr wait_address); | 222 | void WaitCurrentThread_ArbitrateAddress(VAddr wait_address); |
| 232 | 223 | ||
| 233 | /** | 224 | /** |
| 234 | * Sets up the idle thread, this is a thread that is intended to never execute instructions, | ||
| 235 | * only to advance the timing. It is scheduled when there are no other ready threads in the thread queue | ||
| 236 | * and will try to yield on every call. | ||
| 237 | * @return The handle of the idle thread | ||
| 238 | */ | ||
| 239 | SharedPtr<Thread> SetupIdleThread(); | ||
| 240 | |||
| 241 | /** | ||
| 242 | * Initialize threading | 225 | * Initialize threading |
| 243 | */ | 226 | */ |
| 244 | void ThreadingInit(); | 227 | void ThreadingInit(); |