summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2015-05-11 16:09:10 -0300
committerGravatar Yuri Kunde Schlesner2015-05-11 22:39:39 -0300
commit4f7a055081dff4299ee049a03c7a6f1659406942 (patch)
treea9ba4323003af89d5fcb8b993a27bcad98401e06 /src
parentMerge pull request #749 from yuriks/stack-top (diff)
downloadyuzu-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.cpp4
-rw-r--r--src/core/hle/kernel/thread.cpp46
-rw-r--r--src/core/hle/kernel/thread.h17
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
26void RunLoop(int tight_loop) { 26void 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 */
171static void SwitchContext(Thread* new_thread) { 171static 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
451SharedPtr<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
461SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) { 455SharedPtr<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
476void Reschedule() { 470void 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
497void Thread::SetWaitSynchronizationResult(ResultCode result) { 492void 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
524void ThreadingShutdown() { 516void 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
174private: 165private:
175 Thread(); 166 Thread();
176 ~Thread() override; 167 ~Thread() override;
@@ -229,14 +220,6 @@ void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wa
229void WaitCurrentThread_ArbitrateAddress(VAddr wait_address); 220void 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 */
237SharedPtr<Thread> SetupIdleThread();
238
239/**
240 * Initialize threading 223 * Initialize threading
241 */ 224 */
242void ThreadingInit(); 225void ThreadingInit();