Просмотр исходного кода

kernel: wait for threads to stop on pause

Liam 4 лет назад
Родитель
Сommit
24d7aaf43c
3 измененных файлов с 22 добавлено и 0 удалено
  1. 13 0
      src/core/hle/kernel/k_thread.cpp
  2. 2 0
      src/core/hle/kernel/k_thread.h
  3. 7 0
      src/core/hle/kernel/kernel.cpp

+ 13 - 0
src/core/hle/kernel/k_thread.cpp

@@ -748,6 +748,19 @@ void KThread::Continue() {
     KScheduler::OnThreadStateChanged(kernel, this, old_state);
 }
 
+void KThread::WaitUntilSuspended() {
+    // Make sure we have a suspend requested.
+    ASSERT(IsSuspendRequested());
+
+    // Loop until the thread is not executing on any core.
+    for (std::size_t i = 0; i < static_cast<std::size_t>(Core::Hardware::NUM_CPU_CORES); ++i) {
+        KThread* core_thread{};
+        do {
+            core_thread = kernel.Scheduler(i).GetCurrentThread();
+        } while (core_thread == this);
+    }
+}
+
 ResultCode KThread::SetActivity(Svc::ThreadActivity activity) {
     // Lock ourselves.
     KScopedLightLock lk(activity_pause_lock);

+ 2 - 0
src/core/hle/kernel/k_thread.h

@@ -207,6 +207,8 @@ public:
 
     void Continue();
 
+    void WaitUntilSuspended();
+
     constexpr void SetSyncedIndex(s32 index) {
         synced_index = index;
     }

+ 7 - 0
src/core/hle/kernel/kernel.cpp

@@ -1079,6 +1079,13 @@ void KernelCore::Suspend(bool suspended) {
 
     for (auto* process : GetProcessList()) {
         process->SetActivity(activity);
+
+        if (should_suspend) {
+            // Wait for execution to stop
+            for (auto* thread : process->GetThreadList()) {
+                thread->WaitUntilSuspended();
+            }
+        }
     }
 }