diff options
| author | Liam <byteslice@airmail.cc> | 2022-11-14 21:00:32 -0500 | 
|---|---|---|
| committer | Liam <byteslice@airmail.cc> | 2022-11-14 21:18:52 -0500 | 
| commit | cf202f371862ebe92dd88924a9f7b8cfbc7ad738 (patch) | |
| tree | d77708003ece5424446ac2824415c98dc1cf0c86 | |
| parent | 040a01a5ddf1dc3c8a3c992034803f54e9f2a7af (diff) | |
nvnflinger: fix lost wakeup
4 files changed, 16 insertions, 12 deletions
| diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.cpp b/src/core/hle/service/nvflinger/buffer_queue_core.cpp index ea4a14ea4..3d1338e66 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_core.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue_core.cpp @@ -23,15 +23,17 @@ void BufferQueueCore::NotifyShutdown() {  }  void BufferQueueCore::SignalDequeueCondition() { +    dequeue_possible.store(true);      dequeue_condition.notify_all();  } -bool BufferQueueCore::WaitForDequeueCondition() { +bool BufferQueueCore::WaitForDequeueCondition(std::unique_lock<std::mutex>& lk) {      if (is_shutting_down) {          return false;      } -    dequeue_condition.wait(mutex); +    dequeue_condition.wait(lk, [&] { return dequeue_possible.load(); }); +    dequeue_possible.store(false);      return true;  } diff --git a/src/core/hle/service/nvflinger/buffer_queue_core.h b/src/core/hle/service/nvflinger/buffer_queue_core.h index ca6baefaf..85b3bc4c1 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_core.h +++ b/src/core/hle/service/nvflinger/buffer_queue_core.h @@ -38,7 +38,7 @@ public:  private:      void SignalDequeueCondition(); -    bool WaitForDequeueCondition(); +    bool WaitForDequeueCondition(std::unique_lock<std::mutex>& lk);      s32 GetMinUndequeuedBufferCountLocked(bool async) const;      s32 GetMinMaxBufferCountLocked(bool async) const; @@ -60,7 +60,8 @@ private:      BufferQueueDefs::SlotsType slots{};      std::vector<BufferItem> queue;      s32 override_max_buffer_count{}; -    mutable std::condition_variable_any dequeue_condition; +    std::condition_variable dequeue_condition; +    std::atomic<bool> dequeue_possible{};      const bool use_async_buffer{}; // This is always disabled on HOS      bool dequeue_buffer_cannot_block{};      PixelFormat default_buffer_format{PixelFormat::Rgba8888}; diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp index 41ba44b21..e601b5da1 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue_producer.cpp @@ -121,8 +121,8 @@ Status BufferQueueProducer::SetBufferCount(s32 buffer_count) {      return Status::NoError;  } -Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, -                                                      Status* return_flags) const { +Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found, Status* return_flags, +                                                      std::unique_lock<std::mutex>& lk) const {      bool try_again = true;      while (try_again) { @@ -214,7 +214,7 @@ Status BufferQueueProducer::WaitForFreeSlotThenRelock(bool async, s32* found,                  return Status::WouldBlock;              } -            if (!core->WaitForDequeueCondition()) { +            if (!core->WaitForDequeueCondition(lk)) {                  // We are no longer running                  return Status::NoError;              } @@ -237,7 +237,7 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool      Status return_flags = Status::NoError;      bool attached_by_consumer = false;      { -        std::scoped_lock lock{core->mutex}; +        std::unique_lock lock{core->mutex};          core->WaitWhileAllocatingLocked();          if (format == PixelFormat::NoFormat) { @@ -248,7 +248,7 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool          usage |= core->consumer_usage_bit;          s32 found{}; -        Status status = WaitForFreeSlotThenRelock(async, &found, &return_flags); +        Status status = WaitForFreeSlotThenRelock(async, &found, &return_flags, lock);          if (status != Status::NoError) {              return status;          } @@ -400,13 +400,13 @@ Status BufferQueueProducer::AttachBuffer(s32* out_slot,          return Status::BadValue;      } -    std::scoped_lock lock{core->mutex}; +    std::unique_lock lock{core->mutex};      core->WaitWhileAllocatingLocked();      Status return_flags = Status::NoError;      s32 found{}; -    const auto status = WaitForFreeSlotThenRelock(false, &found, &return_flags); +    const auto status = WaitForFreeSlotThenRelock(false, &found, &return_flags, lock);      if (status != Status::NoError) {          return status;      } diff --git a/src/core/hle/service/nvflinger/buffer_queue_producer.h b/src/core/hle/service/nvflinger/buffer_queue_producer.h index 7526bf8ec..1d380480f 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_producer.h +++ b/src/core/hle/service/nvflinger/buffer_queue_producer.h @@ -70,7 +70,8 @@ public:  private:      BufferQueueProducer(const BufferQueueProducer&) = delete; -    Status WaitForFreeSlotThenRelock(bool async, s32* found, Status* return_flags) const; +    Status WaitForFreeSlotThenRelock(bool async, s32* found, Status* return_flags, +                                     std::unique_lock<std::mutex>& lk) const;      Kernel::KEvent* buffer_wait_event{};      Service::KernelHelpers::ServiceContext& service_context; | 
