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

nvflinger: Use jthread and stop_token for VSync thread

Avoids a destruction data race that may occur on the vsync thread
ameerj 4 лет назад
Родитель
Сommit
71e19153ef
2 измененных файлов с 8 добавлено и 32 удалено
  1. 6 23
      src/core/hle/service/nvflinger/nvflinger.cpp
  2. 2 9
      src/core/hle/service/nvflinger/nvflinger.h

+ 6 - 23
src/core/hle/service/nvflinger/nvflinger.cpp

@@ -13,28 +13,20 @@
 #include "common/thread.h"
 #include "common/thread.h"
 #include "core/core.h"
 #include "core/core.h"
 #include "core/core_timing.h"
 #include "core/core_timing.h"
-#include "core/core_timing_util.h"
-#include "core/hardware_properties.h"
 #include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/k_readable_event.h"
-#include "core/hle/kernel/kernel.h"
 #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
 #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
 #include "core/hle/service/nvdrv/nvdrv.h"
 #include "core/hle/service/nvdrv/nvdrv.h"
 #include "core/hle/service/nvflinger/buffer_queue.h"
 #include "core/hle/service/nvflinger/buffer_queue.h"
 #include "core/hle/service/nvflinger/nvflinger.h"
 #include "core/hle/service/nvflinger/nvflinger.h"
 #include "core/hle/service/vi/display/vi_display.h"
 #include "core/hle/service/vi/display/vi_display.h"
 #include "core/hle/service/vi/layer/vi_layer.h"
 #include "core/hle/service/vi/layer/vi_layer.h"
-#include "core/perf_stats.h"
-#include "video_core/renderer_base.h"
+#include "video_core/gpu.h"
 
 
 namespace Service::NVFlinger {
 namespace Service::NVFlinger {
 
 
 constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60};
 constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60};
 
 
-void NVFlinger::VSyncThread(NVFlinger& nv_flinger) {
-    nv_flinger.SplitVSync();
-}
-
-void NVFlinger::SplitVSync() {
+void NVFlinger::SplitVSync(std::stop_token stop_token) {
     system.RegisterHostThread();
     system.RegisterHostThread();
     std::string name = "yuzu:VSyncThread";
     std::string name = "yuzu:VSyncThread";
     MicroProfileOnThreadCreate(name.c_str());
     MicroProfileOnThreadCreate(name.c_str());
@@ -45,7 +37,7 @@ void NVFlinger::SplitVSync() {
     Common::SetCurrentThreadName(name.c_str());
     Common::SetCurrentThreadName(name.c_str());
     Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
     Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
     s64 delay = 0;
     s64 delay = 0;
-    while (is_running) {
+    while (!stop_token.stop_requested()) {
         guard->lock();
         guard->lock();
         const s64 time_start = system.CoreTiming().GetGlobalTimeNs().count();
         const s64 time_start = system.CoreTiming().GetGlobalTimeNs().count();
         Compose();
         Compose();
@@ -55,7 +47,7 @@ void NVFlinger::SplitVSync() {
         const s64 next_time = std::max<s64>(0, ticks - time_passed - delay);
         const s64 next_time = std::max<s64>(0, ticks - time_passed - delay);
         guard->unlock();
         guard->unlock();
         if (next_time > 0) {
         if (next_time > 0) {
-            wait_event->WaitFor(std::chrono::nanoseconds{next_time});
+            std::this_thread::sleep_for(std::chrono::nanoseconds{next_time});
         }
         }
         delay = (system.CoreTiming().GetGlobalTimeNs().count() - time_end) - next_time;
         delay = (system.CoreTiming().GetGlobalTimeNs().count() - time_end) - next_time;
     }
     }
@@ -84,9 +76,7 @@ NVFlinger::NVFlinger(Core::System& system_)
         });
         });
 
 
     if (system.IsMulticore()) {
     if (system.IsMulticore()) {
-        is_running = true;
-        wait_event = std::make_unique<Common::Event>();
-        vsync_thread = std::make_unique<std::thread>(VSyncThread, std::ref(*this));
+        vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); });
     } else {
     } else {
         system.CoreTiming().ScheduleEvent(frame_ns, composition_event);
         system.CoreTiming().ScheduleEvent(frame_ns, composition_event);
     }
     }
@@ -96,14 +86,7 @@ NVFlinger::~NVFlinger() {
     for (auto& buffer_queue : buffer_queues) {
     for (auto& buffer_queue : buffer_queues) {
         buffer_queue->Disconnect();
         buffer_queue->Disconnect();
     }
     }
-
-    if (system.IsMulticore()) {
-        is_running = false;
-        wait_event->Set();
-        vsync_thread->join();
-        vsync_thread.reset();
-        wait_event.reset();
-    } else {
+    if (!system.IsMulticore()) {
         system.CoreTiming().UnscheduleEvent(composition_event, 0);
         system.CoreTiming().UnscheduleEvent(composition_event, 0);
     }
     }
 }
 }

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

@@ -4,13 +4,10 @@
 
 
 #pragma once
 #pragma once
 
 
-#include <atomic>
 #include <list>
 #include <list>
 #include <memory>
 #include <memory>
 #include <mutex>
 #include <mutex>
 #include <optional>
 #include <optional>
-#include <string>
-#include <string_view>
 #include <thread>
 #include <thread>
 #include <vector>
 #include <vector>
 
 
@@ -109,9 +106,7 @@ private:
     /// Creates a layer with the specified layer ID in the desired display.
     /// Creates a layer with the specified layer ID in the desired display.
     void CreateLayerAtId(VI::Display& display, u64 layer_id);
     void CreateLayerAtId(VI::Display& display, u64 layer_id);
 
 
-    static void VSyncThread(NVFlinger& nv_flinger);
-
-    void SplitVSync();
+    void SplitVSync(std::stop_token stop_token);
 
 
     std::shared_ptr<Nvidia::Module> nvdrv;
     std::shared_ptr<Nvidia::Module> nvdrv;
 
 
@@ -133,9 +128,7 @@ private:
 
 
     Core::System& system;
     Core::System& system;
 
 
-    std::unique_ptr<std::thread> vsync_thread;
-    std::unique_ptr<Common::Event> wait_event;
-    std::atomic<bool> is_running{};
+    std::jthread vsync_thread;
 
 
     KernelHelpers::ServiceContext service_context;
     KernelHelpers::ServiceContext service_context;
 };
 };