فهرست منبع

NVFlinger: Lock race condition between CPU, Host Timing, VSync.

Fernando Sahmkow 6 سال پیش
والد
کامیت
cc3aa95926
3فایلهای تغییر یافته به همراه11 افزوده شده و 0 حذف شده
  1. 2 0
      src/core/hle/service/nvflinger/nvflinger.cpp
  2. 7 0
      src/core/hle/service/nvflinger/nvflinger.h
  3. 2 0
      src/core/hle/service/vi/vi.cpp

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

@@ -36,10 +36,12 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) {
     displays.emplace_back(2, "Edid", system);
     displays.emplace_back(3, "Internal", system);
     displays.emplace_back(4, "Null", system);
+    guard = std::make_shared<std::mutex>();
 
     // Schedule the screen composition events
     composition_event =
         Core::Timing::CreateEvent("ScreenComposition", [this](u64 userdata, s64 ns_late) {
+            Lock();
             Compose();
             const auto ticks = GetNextTicks();
             this->system.CoreTiming().ScheduleEvent(std::max<s64>(0LL, ticks - ns_late),

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

@@ -5,6 +5,7 @@
 #pragma once
 
 #include <memory>
+#include <mutex>
 #include <optional>
 #include <string>
 #include <string_view>
@@ -79,6 +80,10 @@ public:
 
     s64 GetNextTicks() const;
 
+    std::unique_lock<std::mutex> Lock() {
+        return std::unique_lock{*guard};
+    }
+
 private:
     /// Finds the display identified by the specified ID.
     VI::Display* FindDisplay(u64 display_id);
@@ -108,6 +113,8 @@ private:
     /// Event that handles screen composition.
     std::shared_ptr<Core::Timing::EventType> composition_event;
 
+    std::shared_ptr<std::mutex> guard;
+
     Core::System& system;
 };
 

+ 2 - 0
src/core/hle/service/vi/vi.cpp

@@ -511,6 +511,7 @@ private:
         LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id,
                   static_cast<u32>(transaction), flags);
 
+        nv_flinger->Lock();
         auto& buffer_queue = nv_flinger->FindBufferQueue(id);
 
         switch (transaction) {
@@ -550,6 +551,7 @@ private:
                     [=](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
                         Kernel::ThreadWakeupReason reason) {
                         // Repeat TransactParcel DequeueBuffer when a buffer is available
+                        nv_flinger->Lock();
                         auto& buffer_queue = nv_flinger->FindBufferQueue(id);
                         auto result = buffer_queue.DequeueBuffer(width, height);
                         ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer.");