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

This commit is contained in:
Fernando Sahmkow 2020-02-27 10:47:02 -04:00
parent 3902067008
commit cc3aa95926
3 changed files with 11 additions and 0 deletions

View File

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

View File

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

View File

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