浏览代码

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

bunnei 12 年之前
父节点
当前提交
ba98e25e97
共有 1 个文件被更改,包括 18 次插入0 次删除
  1. 18 0
      src/core/hle/kernel/thread.cpp

+ 18 - 0
src/core/hle/kernel/thread.cpp

@@ -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);
     }
     }
 }
 }