citra-emu
/
citra
Archived
1
0
Fork 0

thread: updated Reschedule to sit at a synchronization barrier when no other threads are ready for execution

This commit is contained in:
bunnei 2014-06-01 10:35:42 -04:00
parent f7cececc5c
commit ba98e25e97
1 changed files with 18 additions and 0 deletions

View File

@ -323,11 +323,29 @@ void Reschedule() {
Thread* prev = GetCurrentThread(); Thread* prev = GetCurrentThread();
Thread* next = NextThread(); Thread* next = NextThread();
if (next > 0) { if (next > 0) {
INFO_LOG(KERNEL, "context switch 0x%08X -> 0x%08X", prev->GetHandle(), next->GetHandle());
SwitchContext(next); SwitchContext(next);
// Hack - automatically change previous thread (which would have been in "wait" state) to // 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 // "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. // 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); ChangeReadyState(prev, true);
} }
} }