summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
/// Run the core CPU loop
void RunLoop(int tight_loop) {
- // If the current thread is an idle thread, then don't execute instructions,
+ // If we don't have a currently active thread then don't execute instructions,
// instead advance to the next event and try to yield to the next thread
- if (Kernel::GetCurrentThread()->IsIdle()) {
+ if (Kernel::GetCurrentThread() == nullptr) {
LOG_TRACE(Core_ARM11, "Idling");
CoreTiming::Idle();
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() {
u64 delta = current_ticks - thread->last_running_ticks;
- if (thread->status == THREADSTATUS_READY && delta > boost_timeout && !thread->idle) {
+ if (thread->status == THREADSTATUS_READY && delta > boost_timeout) {
const s32 priority = std::max(ready_queue.get_first()->current_priority - 1, 0);
thread->BoostPriority(priority);
}
@@ -169,8 +169,6 @@ static void PriorityBoostStarvedThreads() {
* @param new_thread The thread to switch to
*/
static void SwitchContext(Thread* new_thread) {
- DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running.");
-
Thread* previous_thread = GetCurrentThread();
// Save context for previous thread
@@ -188,6 +186,8 @@ static void SwitchContext(Thread* new_thread) {
// Load context of new thread
if (new_thread) {
+ DEBUG_ASSERT_MSG(new_thread->status == THREADSTATUS_READY, "Thread must be ready to become running.");
+
current_thread = new_thread;
ready_queue.remove(new_thread->current_priority, new_thread);
@@ -215,6 +215,10 @@ static Thread* PopNextReadyThread() {
// We have to do better than the current thread.
// This call returns null when that's not possible.
next = ready_queue.pop_first_better(thread->current_priority);
+ if (!next) {
+ // Otherwise just keep going with the current thread
+ next = thread;
+ }
} else {
next = ready_queue.pop_first();
}
@@ -448,16 +452,6 @@ void Thread::BoostPriority(s32 priority) {
current_priority = priority;
}
-SharedPtr<Thread> SetupIdleThread() {
- // We need to pass a few valid values to get around parameter checking in Thread::Create.
- // TODO(yuriks): Figure out a way to avoid passing the bogus VAddr parameter
- auto thread = Thread::Create("idle", Memory::TLS_AREA_VADDR, THREADPRIO_LOWEST, 0,
- THREADPROCESSORID_0, 0).MoveFrom();
-
- thread->idle = true;
- return thread;
-}
-
SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) {
DEBUG_ASSERT(!GetCurrentThread());
@@ -474,24 +468,25 @@ SharedPtr<Thread> SetupMainThread(u32 entry_point, s32 priority) {
}
void Reschedule() {
- Thread* prev = GetCurrentThread();
-
PriorityBoostStarvedThreads();
+ Thread* cur = GetCurrentThread();
Thread* next = PopNextReadyThread();
HLE::g_reschedule = false;
- if (next != nullptr) {
- LOG_TRACE(Kernel, "context switch %u -> %u", prev->GetObjectId(), next->GetObjectId());
- SwitchContext(next);
- } else {
- LOG_TRACE(Kernel, "cannot context switch from %u, no higher priority thread!", prev->GetObjectId());
+ // Don't bother switching to the same thread
+ if (next == cur)
+ return;
- for (auto& thread : thread_list) {
- LOG_TRACE(Kernel, "\tid=%u prio=0x%02X, status=0x%08X", thread->GetObjectId(),
- thread->current_priority, thread->status);
- }
+ if (cur && next) {
+ LOG_TRACE(Kernel, "context switch %u -> %u", cur->GetObjectId(), next->GetObjectId());
+ } else if (cur) {
+ LOG_TRACE(Kernel, "context switch %u -> idle", cur->GetObjectId());
+ } else {
+ LOG_TRACE(Kernel, "context switch idle -> %u", next->GetObjectId());
}
+
+ SwitchContext(next);
}
void Thread::SetWaitSynchronizationResult(ResultCode result) {
@@ -516,9 +511,6 @@ void ThreadingInit() {
thread_list.clear();
ready_queue.clear();
-
- // Setup the idle thread
- SetupIdleThread();
}
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:
void Acquire() override;
/**
- * Checks if the thread is an idle (stub) thread
- * @return True if the thread is an idle (stub) thread, false otherwise
- */
- inline bool IsIdle() const { return idle; }
-
- /**
* Gets the thread's current priority
* @return The current thread's priority
*/
@@ -168,9 +162,6 @@ public:
std::string name;
- /// Whether this thread is intended to never actually be executed, i.e. always idle
- bool idle = false;
-
private:
Thread();
~Thread() override;
@@ -229,14 +220,6 @@ void WaitCurrentThread_WaitSynchronization(std::vector<SharedPtr<WaitObject>> wa
void WaitCurrentThread_ArbitrateAddress(VAddr wait_address);
/**
- * Sets up the idle thread, this is a thread that is intended to never execute instructions,
- * only to advance the timing. It is scheduled when there are no other ready threads in the thread queue
- * and will try to yield on every call.
- * @return The handle of the idle thread
- */
-SharedPtr<Thread> SetupIdleThread();
-
-/**
* Initialize threading
*/
void ThreadingInit();