aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/hle/kernel/thread.cpp
diff options
context:
space:
mode:
authorGravatar bunnei <ericbunnie@gmail.com>2014-06-01 10:35:42 -0400
committerGravatar bunnei <ericbunnie@gmail.com>2014-06-01 10:35:42 -0400
commitba98e25e979b1aedaa9b917a7db8f710c83c073c (patch)
tree2dccc232bf7b6bfef741e4a683cca69baab89c22 /src/core/hle/kernel/thread.cpp
parentf7cececc5ca82f97a9fb1ab50c62fd9e3a49ccdc (diff)
thread: updated Reschedule to sit at a synchronization barrier when no other threads are ready for execution
Diffstat (limited to 'src/core/hle/kernel/thread.cpp')
-rw-r--r--src/core/hle/kernel/thread.cpp18
1 files changed, 18 insertions, 0 deletions
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);
}
}