summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
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 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() {
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
176private: 167private:
177 Thread(); 168 Thread();
178 ~Thread() override; 169 ~Thread() override;
@@ -231,14 +222,6 @@ void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wa
231void WaitCurrentThread_ArbitrateAddress(VAddr wait_address); 222void 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 */
239SharedPtr<Thread> SetupIdleThread();
240
241/**
242 * Initialize threading 225 * Initialize threading
243 */ 226 */
244void ThreadingInit(); 227void ThreadingInit();