From ba98e25e979b1aedaa9b917a7db8f710c83c073c Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Jun 2014 10:35:42 -0400 Subject: thread: updated Reschedule to sit at a synchronization barrier when no other threads are ready for execution --- src/core/hle/kernel/thread.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/core/hle/kernel/thread.cpp') diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 6e8b53eb..d1e13c94 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -323,11 +323,29 @@ void Reschedule() { Thread* prev = GetCurrentThread(); Thread* next = NextThread(); if (next > 0) { + INFO_LOG(KERNEL, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle()); + SwitchContext(next); // Hack - automatically change previous thread (which would have been in "wait" state) to // "ready" state, so that we can immediately resume to it when new thread yields. FixMe to // actually wait for whatever event it is supposed to be waiting on. + + ChangeReadyState(prev, true); + } else { + INFO_LOG(KERNEL, "no ready threads, staying on 0x%08X", prev->GetHandle()); + + // Hack - no other threads are available, so decrement current PC to the last instruction, + // and then resume current thread. This should always be called on a blocking instruction + // (e.g. svcWaitSynchronization), and the result should be that the instruction is repeated + // until it no longer blocks. + + // TODO(bunnei): A better solution: Have the CPU switch to an idle thread + + ThreadContext ctx; + SaveContext(ctx); + ctx.pc -= 4; + LoadContext(ctx); ChangeReadyState(prev, true); } } -- cgit v1.2.3