From 71e19153ef9309dbcdd9ada95068917f0d0dd44c Mon Sep 17 00:00:00 2001 From: ameerj <52414509+ameerj@users.noreply.github.com> Date: Sat, 2 Oct 2021 00:39:57 -0400 Subject: [PATCH] nvflinger: Use jthread and stop_token for VSync thread Avoids a destruction data race that may occur on the vsync thread --- src/core/hle/service/nvflinger/nvflinger.cpp | 29 ++++---------------- src/core/hle/service/nvflinger/nvflinger.h | 11 ++------ 2 files changed, 8 insertions(+), 32 deletions(-) diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 3ead813b07..a22811ec12 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -13,28 +13,20 @@ #include "common/thread.h" #include "core/core.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/kernel.h" #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" #include "core/hle/service/nvdrv/nvdrv.h" #include "core/hle/service/nvflinger/buffer_queue.h" #include "core/hle/service/nvflinger/nvflinger.h" #include "core/hle/service/vi/display/vi_display.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 { 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(); std::string name = "yuzu:VSyncThread"; MicroProfileOnThreadCreate(name.c_str()); @@ -45,7 +37,7 @@ void NVFlinger::SplitVSync() { Common::SetCurrentThreadName(name.c_str()); Common::SetCurrentThreadPriority(Common::ThreadPriority::High); s64 delay = 0; - while (is_running) { + while (!stop_token.stop_requested()) { guard->lock(); const s64 time_start = system.CoreTiming().GetGlobalTimeNs().count(); Compose(); @@ -55,7 +47,7 @@ void NVFlinger::SplitVSync() { const s64 next_time = std::max(0, ticks - time_passed - delay); guard->unlock(); 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; } @@ -84,9 +76,7 @@ NVFlinger::NVFlinger(Core::System& system_) }); if (system.IsMulticore()) { - is_running = true; - wait_event = std::make_unique(); - vsync_thread = std::make_unique(VSyncThread, std::ref(*this)); + vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); }); } else { system.CoreTiming().ScheduleEvent(frame_ns, composition_event); } @@ -96,14 +86,7 @@ NVFlinger::~NVFlinger() { for (auto& buffer_queue : buffer_queues) { 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); } } diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index 6d84cafb49..7935cf773a 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h @@ -4,13 +4,10 @@ #pragma once -#include #include #include #include #include -#include -#include #include #include @@ -109,9 +106,7 @@ private: /// Creates a layer with the specified layer ID in the desired display. 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 nvdrv; @@ -133,9 +128,7 @@ private: Core::System& system; - std::unique_ptr vsync_thread; - std::unique_ptr wait_event; - std::atomic is_running{}; + std::jthread vsync_thread; KernelHelpers::ServiceContext service_context; };