Explorar o código

core: barrier service thread shutdown

Liam %!s(int64=3) %!d(string=hai) anos
pai
achega
2d90a927c9

+ 1 - 0
src/core/core.cpp

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

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

@@ -48,8 +48,8 @@ namespace Kernel {
 
 struct KernelCore::Impl {
     explicit Impl(Core::System& system_, KernelCore& kernel_)
-        : time_manager{system_},
-          service_threads_manager{1, "ServiceThreadsManager"}, system{system_} {}
+        : time_manager{system_}, service_threads_manager{1, "ServiceThreadsManager"},
+          service_thread_barrier{2}, system{system_} {}
 
     void SetMulticore(bool is_multi) {
         is_multicore = is_multi;
@@ -737,7 +737,12 @@ struct KernelCore::Impl {
     }
 
     void ClearServiceThreads() {
-        service_threads_manager.QueueWork([this]() { service_threads.clear(); });
+        service_threads_manager.QueueWork([this] {
+            service_threads.clear();
+            default_service_thread.reset();
+            service_thread_barrier.Sync();
+        });
+        service_thread_barrier.Sync();
     }
 
     std::mutex server_objects_lock;
@@ -802,6 +807,7 @@ struct KernelCore::Impl {
     std::unordered_set<std::shared_ptr<ServiceThread>> service_threads;
     std::weak_ptr<ServiceThread> default_service_thread;
     Common::ThreadWorker service_threads_manager;
+    Common::Barrier service_thread_barrier;
 
     std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads;
     std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};

+ 8 - 4
src/core/hle/service/nvflinger/nvflinger.cpp

@@ -102,15 +102,19 @@ NVFlinger::~NVFlinger() {
         system.CoreTiming().UnscheduleEvent(single_composition_event, {});
     }
 
+    ShutdownLayers();
+
+    if (nvdrv) {
+        nvdrv->Close(disp_fd);
+    }
+}
+
+void NVFlinger::ShutdownLayers() {
     for (auto& display : displays) {
         for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) {
             display.GetLayer(layer).Core().NotifyShutdown();
         }
     }
-
-    if (nvdrv) {
-        nvdrv->Close(disp_fd);
-    }
 }
 
 void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {

+ 2 - 0
src/core/hle/service/nvflinger/nvflinger.h

@@ -48,6 +48,8 @@ public:
     explicit NVFlinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_);
     ~NVFlinger();
 
+    void ShutdownLayers();
+
     /// Sets the NVDrv module instance to use to send buffers to the GPU.
     void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance);
 

+ 4 - 0
src/core/hle/service/service.cpp

@@ -303,4 +303,8 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
 
 Services::~Services() = default;
 
+void Services::KillNVNFlinger() {
+    nv_flinger->ShutdownLayers();
+}
+
 } // namespace Service

+ 2 - 0
src/core/hle/service/service.h

@@ -238,6 +238,8 @@ public:
     explicit Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system);
     ~Services();
 
+    void KillNVNFlinger();
+
 private:
     std::unique_ptr<NVFlinger::HosBinderDriverServer> hos_binder_driver_server;
     std::unique_ptr<NVFlinger::NVFlinger> nv_flinger;