diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-29 01:26:52 -0400 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-29 01:26:52 -0400 |
| commit | e8bc734d1040044abe117a369a9f80a792e51df4 (patch) | |
| tree | 03bc201a0d2d37606b2c785ddef94d963ec851ee /src/video_core/fence_manager.h | |
| parent | 2bb0f8acdf79816ae1c474c42e2b63dbaa4500e8 (diff) | |
video_core: guard the fence manager's uncommitted operations
SyncOperation appended to uncommitted_operations without a lock while
SignalFence moved that list into pending_operations under `guard` on
another thread; a list corrupted this way crashed the fencing thread.
They now share a lock of their own, held for no callbacks (SignalFence
runs callbacks under `guard`, so taking `guard` here could deadlock).
Diffstat (limited to 'src/video_core/fence_manager.h')
| -rw-r--r-- | src/video_core/fence_manager.h | 15 |
1 files changed, 12 insertions, 3 deletions
diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h index 776c01e3fa..65d8f24aae 100644 --- a/src/video_core/fence_manager.h +++ b/src/video_core/fence_manager.h @@ -68,6 +68,10 @@ public: } void SyncOperation(std::function<void()>&& func) { + // Not only the GPU thread queues these (query cache work runs elsewhere too), while + // SignalFence moves the list into pending_operations: unguarded, the list was corrupted + // and the fencing thread crashed walking it. Its own lock, held for no callbacks. + std::scoped_lock lock{uncommitted_guard}; uncommitted_operations.emplace_back(std::move(func)); } @@ -82,10 +86,14 @@ public: if constexpr (can_async_check) { guard.lock(); } - if (delay_fence) { - uncommitted_operations.emplace_back(std::move(func)); + { + std::scoped_lock lock{uncommitted_guard}; + if (delay_fence) { + uncommitted_operations.emplace_back(std::move(func)); + } + pending_operations.emplace_back(std::move(uncommitted_operations)); + uncommitted_operations.clear(); // moved-from: make it empty explicitly } - pending_operations.emplace_back(std::move(uncommitted_operations)); QueueFence(new_fence); if (!delay_fence) { func(); @@ -261,6 +269,7 @@ private: std::mutex guard; std::mutex ring_guard; + std::mutex uncommitted_guard; ///< Guards uncommitted_operations std::condition_variable cv; std::jthread fence_thread; |
