diff options
| author | 2020-02-27 10:47:02 -0400 | |
|---|---|---|
| committer | 2020-06-27 11:35:18 -0400 | |
| commit | cc3aa959265480e1990b10ee37ebf1c0ade3da64 (patch) | |
| tree | 0188b3adeab5cb83362f296e6894d70b53cb86e0 /src | |
| parent | SVC: Add locks to the memory management. (diff) | |
| download | yuzu-cc3aa959265480e1990b10ee37ebf1c0ade3da64.tar.gz yuzu-cc3aa959265480e1990b10ee37ebf1c0ade3da64.tar.xz yuzu-cc3aa959265480e1990b10ee37ebf1c0ade3da64.zip | |
NVFlinger: Lock race condition between CPU, Host Timing, VSync.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/nvflinger/nvflinger.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nvflinger/nvflinger.h | 7 | ||||
| -rw-r--r-- | src/core/hle/service/vi/vi.cpp | 2 |
3 files changed, 11 insertions, 0 deletions
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index aaf28995d..b97f71350 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp | |||
| @@ -36,10 +36,12 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) { | |||
| 36 | displays.emplace_back(2, "Edid", system); | 36 | displays.emplace_back(2, "Edid", system); |
| 37 | displays.emplace_back(3, "Internal", system); | 37 | displays.emplace_back(3, "Internal", system); |
| 38 | displays.emplace_back(4, "Null", system); | 38 | displays.emplace_back(4, "Null", system); |
| 39 | guard = std::make_shared<std::mutex>(); | ||
| 39 | 40 | ||
| 40 | // Schedule the screen composition events | 41 | // Schedule the screen composition events |
| 41 | composition_event = | 42 | composition_event = |
| 42 | Core::Timing::CreateEvent("ScreenComposition", [this](u64 userdata, s64 ns_late) { | 43 | Core::Timing::CreateEvent("ScreenComposition", [this](u64 userdata, s64 ns_late) { |
| 44 | Lock(); | ||
| 43 | Compose(); | 45 | Compose(); |
| 44 | const auto ticks = GetNextTicks(); | 46 | const auto ticks = GetNextTicks(); |
| 45 | this->system.CoreTiming().ScheduleEvent(std::max<s64>(0LL, ticks - ns_late), | 47 | this->system.CoreTiming().ScheduleEvent(std::max<s64>(0LL, ticks - ns_late), |
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index 57a21f33b..02c081494 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <mutex> | ||
| 8 | #include <optional> | 9 | #include <optional> |
| 9 | #include <string> | 10 | #include <string> |
| 10 | #include <string_view> | 11 | #include <string_view> |
| @@ -79,6 +80,10 @@ public: | |||
| 79 | 80 | ||
| 80 | s64 GetNextTicks() const; | 81 | s64 GetNextTicks() const; |
| 81 | 82 | ||
| 83 | std::unique_lock<std::mutex> Lock() { | ||
| 84 | return std::unique_lock{*guard}; | ||
| 85 | } | ||
| 86 | |||
| 82 | private: | 87 | private: |
| 83 | /// Finds the display identified by the specified ID. | 88 | /// Finds the display identified by the specified ID. |
| 84 | VI::Display* FindDisplay(u64 display_id); | 89 | VI::Display* FindDisplay(u64 display_id); |
| @@ -108,6 +113,8 @@ private: | |||
| 108 | /// Event that handles screen composition. | 113 | /// Event that handles screen composition. |
| 109 | std::shared_ptr<Core::Timing::EventType> composition_event; | 114 | std::shared_ptr<Core::Timing::EventType> composition_event; |
| 110 | 115 | ||
| 116 | std::shared_ptr<std::mutex> guard; | ||
| 117 | |||
| 111 | Core::System& system; | 118 | Core::System& system; |
| 112 | }; | 119 | }; |
| 113 | 120 | ||
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 46e14c2a3..157092074 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -511,6 +511,7 @@ private: | |||
| 511 | LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id, | 511 | LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id, |
| 512 | static_cast<u32>(transaction), flags); | 512 | static_cast<u32>(transaction), flags); |
| 513 | 513 | ||
| 514 | nv_flinger->Lock(); | ||
| 514 | auto& buffer_queue = nv_flinger->FindBufferQueue(id); | 515 | auto& buffer_queue = nv_flinger->FindBufferQueue(id); |
| 515 | 516 | ||
| 516 | switch (transaction) { | 517 | switch (transaction) { |
| @@ -550,6 +551,7 @@ private: | |||
| 550 | [=](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx, | 551 | [=](std::shared_ptr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx, |
| 551 | Kernel::ThreadWakeupReason reason) { | 552 | Kernel::ThreadWakeupReason reason) { |
| 552 | // Repeat TransactParcel DequeueBuffer when a buffer is available | 553 | // Repeat TransactParcel DequeueBuffer when a buffer is available |
| 554 | nv_flinger->Lock(); | ||
| 553 | auto& buffer_queue = nv_flinger->FindBufferQueue(id); | 555 | auto& buffer_queue = nv_flinger->FindBufferQueue(id); |
| 554 | auto result = buffer_queue.DequeueBuffer(width, height); | 556 | auto result = buffer_queue.DequeueBuffer(width, height); |
| 555 | ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer."); | 557 | ASSERT_MSG(result != std::nullopt, "Could not dequeue buffer."); |