diff options
| author | 2015-05-11 16:09:10 -0300 | |
|---|---|---|
| committer | 2015-05-11 22:39:39 -0300 | |
| commit | 4f7a055081dff4299ee049a03c7a6f1659406942 (patch) | |
| tree | a9ba4323003af89d5fcb8b993a27bcad98401e06 /src | |
| parent | Merge pull request #749 from yuriks/stack-top (diff) | |
| download | yuzu-4f7a055081dff4299ee049a03c7a6f1659406942.tar.gz yuzu-4f7a055081dff4299ee049a03c7a6f1659406942.tar.xz yuzu-4f7a055081dff4299ee049a03c7a6f1659406942.zip | |
Thread: Remove the idle thread
Instead just use nullptr to represent no thread is active.
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 957cbdfee..b962da8f0 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -157,7 +157,7 @@ static void PriorityBoostStarvedThreads() { | |||
| 157 | 157 | ||
| 158 | u64 delta = current_ticks - thread->last_running_ticks; | 158 | u64 delta = current_ticks - thread->last_running_ticks; |
| 159 | 159 | ||
| 160 | if (thread->status == THREADSTATUS_READY && delta > boost_timeout && !thread->idle) { | 160 | if (thread->status == THREADSTATUS_READY && delta > boost_timeout) { |
| 161 | const s32 priority = std::max(ready_queue.get_first()->current_priority - 1, 0); | 161 | const s32 priority = std::max(ready_queue.get_first()->current_priority - 1, 0); |
| 162 | thread->BoostPriority(priority); | 162 | thread->BoostPriority(priority); |
| 163 | } | 163 | } |
| @@ -169,8 +169,6 @@ static void PriorityBoostStarvedThreads() { | |||
| 169 | * @param new_thread The thread to switch to | 169 | * @param new_thread The thread to switch to |
| 170 | */ | 170 | */ |
| 171 | static void SwitchContext(Thread* new_thread) { | 171 | static void SwitchContext(Thread* new_thread) { |
| 172 | DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running."); | ||
| 173 | |||
| 174 | Thread* previous_thread = GetCurrentThread(); | 172 | Thread* previous_thread = GetCurrentThread(); |
| 175 | 173 | ||
| 176 | // Save context for previous thread | 174 | // Save context for previous thread |
| @@ -188,6 +186,8 @@ static void SwitchContext(Thread* new_thread) { | |||
| 188 | 186 | ||
| 189 | // Load context of new thread | 187 | // Load context of new thread |
| 190 | if (new_thread) { | 188 | if (new_thread) { |
| 189 | DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running."); | ||
| 190 | |||
| 191 | current_thread = new_thread; | 191 | current_thread = new_thread; |
| 192 | 192 | ||
| 193 | ready_queue.remove(new_thread->current_priority, new_thread); | 193 | ready_queue.remove(new_thread->current_priority, new_thread); |
| @@ -215,6 +215,10 @@ static Thread* PopNextReadyThread() { | |||
| 215 | // We have to do better than the current thread. | 215 | // We have to do better than the current thread. |
| 216 | // This call returns null when that's not possible. | 216 | // This call returns null when that's not possible. |
| 217 | next = ready_queue.pop_first_better(thread->current_priority); | 217 | next = ready_queue.pop_first_better(thread->current_priority); |
| 218 | if (!next) { | ||
| 219 | // Otherwise just keep going with the current thread | ||
| 220 | next = thread; | ||
| 221 | } | ||
| 218 | } else { | 222 | } else { |
| 219 | next = ready_queue.pop_first(); | 223 | next = ready_queue.pop_first(); |
| 220 | } | 224 | } |
| @@ -448,16 +452,6 @@ void Thread::BoostPriority(s32 priority) { | |||
| 448 | current_priority = priority; | 452 | current_priority = priority; |
| 449 | } | 453 | } |
| 450 | 454 | ||
| 451 | SharedPtr<Thread> SetupIdleThread() { | ||
| 452 | // We need to pass a few valid values to get around parameter checking in Thread::Create. | ||
| 453 | // TODO(yuriks): Figure out a way to avoid passing the bogus VAddr parameter | ||
| 454 | auto thread = Thread::Create("idle", Memory::TLS_AREA_VADDR, THREADPRIO_LOWEST, 0, | ||
| 455 | THREADPROCESSORID_0, 0).MoveFrom(); | ||
| 456 | |||
| 457 | thread->idle = true; | ||
| 458 | return thread; | ||
| 459 | } | ||
| 460 | |||
| 461 | SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) { | 455 | SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) { |
| 462 | DEBUG_ASSERT(!GetCurrentThread()); | 456 | DEBUG_ASSERT(!GetCurrentThread()); |
| 463 | 457 | ||
| @@ -474,24 +468,25 @@ SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) { | |||
| 474 | } | 468 | } |
| 475 | 469 | ||
| 476 | void Reschedule() { | 470 | void Reschedule() { |
| 477 | Thread* prev = GetCurrentThread(); | ||
| 478 | |||
| 479 | PriorityBoostStarvedThreads(); | 471 | PriorityBoostStarvedThreads(); |
| 480 | 472 | ||
| 473 | Thread* cur = GetCurrentThread(); | ||
| 481 | Thread* next = PopNextReadyThread(); | 474 | Thread* next = PopNextReadyThread(); |
| 482 | HLE::g_reschedule = false; | 475 | HLE::g_reschedule = false; |
| 483 | 476 | ||
| 484 | if (next != nullptr) { | 477 | // Don't bother switching to the same thread |
| 485 | LOG_TRACE(Kernel, "context switch %u -> %u", prev->GetObjectId(), next->GetObjectId()); | 478 | if (next == cur) |
| 486 | SwitchContext(next); | 479 | return; |
| 487 | } else { | ||
| 488 | LOG_TRACE(Kernel, "cannot context switch from %u, no higher priority thread!", prev->GetObjectId()); | ||
| 489 | 480 | ||
| 490 | for (auto& thread : thread_list) { | 481 | if (cur && next) { |
| 491 | LOG_TRACE(Kernel, "\tid=%u prio=0x%02X, status=0x%08X", thread->GetObjectId(), | 482 | LOG_TRACE(Kernel, "context switch %u -> %u", cur->GetObjectId(), next->GetObjectId()); |
| 492 | thread->current_priority, thread->status); | 483 | } else if (cur) { |
| 493 | } | 484 | LOG_TRACE(Kernel, "context switch %u -> idle", cur->GetObjectId()); |
| 485 | } else { | ||
| 486 | LOG_TRACE(Kernel, "context switch idle -> %u", next->GetObjectId()); | ||
| 494 | } | 487 | } |
| 488 | |||
| 489 | SwitchContext(next); | ||
| 495 | } | 490 | } |
| 496 | 491 | ||
| 497 | void Thread::SetWaitSynchronizationResult(ResultCode result) { | 492 | void Thread::SetWaitSynchronizationResult(ResultCode result) { |
| @@ -516,9 +511,6 @@ void ThreadingInit() { | |||
| 516 | 511 | ||
| 517 | thread_list.clear(); | 512 | thread_list.clear(); |
| 518 | ready_queue.clear(); | 513 | ready_queue.clear(); |
| 519 | |||
| 520 | // Setup the idle thread | ||
| 521 | SetupIdleThread(); | ||
| 522 | } | 514 | } |
| 523 | 515 | ||
| 524 | void ThreadingShutdown() { | 516 | void ThreadingShutdown() { |
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index afdaf8511..2ee63d279 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h | |||
| @@ -72,12 +72,6 @@ public: | |||
| 72 | void Acquire() override; | 72 | void Acquire() override; |
| 73 | 73 | ||
| 74 | /** | 74 | /** |
| 75 | * Checks if the thread is an idle (stub) thread | ||
| 76 | * @return True if the thread is an idle (stub) thread, false otherwise | ||
| 77 | */ | ||
| 78 | inline bool IsIdle() const { return idle; } | ||
| 79 | |||
| 80 | /** | ||
| 81 | * Gets the thread's current priority | 75 | * Gets the thread's current priority |
| 82 | * @return The current thread's priority | 76 | * @return The current thread's priority |
| 83 | */ | 77 | */ |
| @@ -168,9 +162,6 @@ public: | |||
| 168 | 162 | ||
| 169 | std::string name; | 163 | std::string name; |
| 170 | 164 | ||
| 171 | /// Whether this thread is intended to never actually be executed, i.e. always idle | ||
| 172 | bool idle = false; | ||
| 173 | |||
| 174 | private: | 165 | private: |
| 175 | Thread(); | 166 | Thread(); |
| 176 | ~Thread() override; | 167 | ~Thread() override; |
| @@ -229,14 +220,6 @@ void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wa | |||
| 229 | void WaitCurrentThread_ArbitrateAddress(VAddr wait_address); | 220 | void WaitCurrentThread_ArbitrateAddress(VAddr wait_address); |
| 230 | 221 | ||
| 231 | /** | 222 | /** |
| 232 | * Sets up the idle thread, this is a thread that is intended to never execute instructions, | ||
| 233 | * only to advance the timing. It is scheduled when there are no other ready threads in the thread queue | ||
| 234 | * and will try to yield on every call. | ||
| 235 | * @return The handle of the idle thread | ||
| 236 | */ | ||
| 237 | SharedPtr<Thread> SetupIdleThread(); | ||
| 238 | |||
| 239 | /** | ||
| 240 | * Initialize threading | 223 | * Initialize threading |
| 241 | */ | 224 | */ |
| 242 | void ThreadingInit(); | 225 | void ThreadingInit(); |