Преглед на файлове

general: improve handling of system startup failure

Liam преди 3 години
родител
ревизия
9704acb982
променени са 5 файла, в които са добавени 27 реда и са изтрити 21 реда
  1. 7 4
      src/common/thread.h
  2. 3 1
      src/core/core.cpp
  3. 7 8
      src/core/cpu_manager.cpp
  4. 1 3
      src/core/cpu_manager.h
  5. 9 5
      src/core/hle/kernel/kernel.cpp

+ 7 - 4
src/common/thread.h

@@ -11,6 +11,7 @@
 #include <mutex>
 #include <thread>
 #include "common/common_types.h"
+#include "common/polyfill_thread.h"
 
 namespace Common {
 
@@ -69,7 +70,7 @@ public:
     explicit Barrier(std::size_t count_) : count(count_) {}
 
     /// Blocks until all "count" threads have called Sync()
-    void Sync() {
+    bool Sync(std::stop_token token = {}) {
         std::unique_lock lk{mutex};
         const std::size_t current_generation = generation;
 
@@ -77,14 +78,16 @@ public:
             generation++;
             waiting = 0;
             condvar.notify_all();
+            return true;
         } else {
-            condvar.wait(lk,
-                         [this, current_generation] { return current_generation != generation; });
+            CondvarWait(condvar, lk, token,
+                        [this, current_generation] { return current_generation != generation; });
+            return !token.stop_requested();
         }
     }
 
 private:
-    std::condition_variable condvar;
+    std::condition_variable_any condvar;
     std::mutex mutex;
     std::size_t count;
     std::size_t waiting = 0;

+ 3 - 1
src/core/core.cpp

@@ -389,7 +389,9 @@ struct System::Impl {
         kernel.ShutdownCores();
         cpu_manager.Shutdown();
         debugger.reset();
-        services->KillNVNFlinger();
+        if (services) {
+            services->KillNVNFlinger();
+        }
         kernel.CloseServices();
         services.reset();
         service_manager.reset();

+ 7 - 8
src/core/cpu_manager.cpp

@@ -20,23 +20,20 @@ namespace Core {
 CpuManager::CpuManager(System& system_) : system{system_} {}
 CpuManager::~CpuManager() = default;
 
-void CpuManager::ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager,
-                             std::size_t core) {
-    cpu_manager.RunThread(core);
-}
-
 void CpuManager::Initialize() {
     num_cores = is_multicore ? Core::Hardware::NUM_CPU_CORES : 1;
     gpu_barrier = std::make_unique<Common::Barrier>(num_cores + 1);
 
     for (std::size_t core = 0; core < num_cores; core++) {
-        core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core);
+        core_data[core].host_thread =
+            std::jthread([this, core](std::stop_token token) { RunThread(token, core); });
     }
 }
 
 void CpuManager::Shutdown() {
     for (std::size_t core = 0; core < num_cores; core++) {
         if (core_data[core].host_thread.joinable()) {
+            core_data[core].host_thread.request_stop();
             core_data[core].host_thread.join();
         }
     }
@@ -184,7 +181,7 @@ void CpuManager::ShutdownThread() {
     UNREACHABLE();
 }
 
-void CpuManager::RunThread(std::size_t core) {
+void CpuManager::RunThread(std::stop_token token, std::size_t core) {
     /// Initialization
     system.RegisterCoreThread(core);
     std::string name;
@@ -206,7 +203,9 @@ void CpuManager::RunThread(std::size_t core) {
     });
 
     // Running
-    gpu_barrier->Sync();
+    if (!gpu_barrier->Sync(token)) {
+        return;
+    }
 
     if (!is_async_gpu && !is_multicore) {
         system.GPU().ObtainContext();

+ 1 - 3
src/core/cpu_manager.h

@@ -81,12 +81,10 @@ private:
     void SingleCoreRunGuestThread();
     void SingleCoreRunIdleThread();
 
-    static void ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, std::size_t core);
-
     void GuestActivate();
     void HandleInterrupt();
     void ShutdownThread();
-    void RunThread(std::size_t core);
+    void RunThread(std::stop_token stop_token, std::size_t core);
 
     struct CoreData {
         std::shared_ptr<Common::Fiber> host_context;

+ 9 - 5
src/core/hle/kernel/kernel.cpp

@@ -104,12 +104,16 @@ struct KernelCore::Impl {
     }
 
     void CloseCurrentProcess() {
-        (*current_process).Finalize();
-        // current_process->Close();
-        // TODO: The current process should be destroyed based on accurate ref counting after
+        KProcess* old_process = current_process.exchange(nullptr);
+        if (old_process == nullptr) {
+            return;
+        }
+
+        // old_process->Close();
+        // TODO: The process should be destroyed based on accurate ref counting after
         // calling Close(). Adding a manual Destroy() call instead to avoid a memory leak.
-        (*current_process).Destroy();
-        current_process = nullptr;
+        old_process->Finalize();
+        old_process->Destroy();
     }
 
     void Shutdown() {