Allow WaitListEvent to require multiple signals. Change the atomic bool in WaitListEvent to a counter and require multiple Signal calls before marking the event as complete. Bug: 406522796 Change-Id: I2bb5c8d24d0af550a37c54c5dd70a5a57db290f2 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/259254 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Loko Kung <lokokung@google.com> Commit-Queue: Geoff Lang <geofflang@chromium.org>
diff --git a/src/dawn/native/WaitListEvent.cpp b/src/dawn/native/WaitListEvent.cpp index 70f4420..3cf921b 100644 --- a/src/dawn/native/WaitListEvent.cpp +++ b/src/dawn/native/WaitListEvent.cpp
@@ -33,16 +33,21 @@ namespace dawn::native { -WaitListEvent::WaitListEvent() = default; +WaitListEvent::WaitListEvent(uint64_t requiredSignalCount) + : mRemainingSignalCount(requiredSignalCount) { + DAWN_ASSERT(mRemainingSignalCount > 0); +} WaitListEvent::~WaitListEvent() = default; bool WaitListEvent::IsSignaled() const { - return mSignaled.load(std::memory_order_acquire); + return mRemainingSignalCount.load(std::memory_order_acquire) == 0; } void WaitListEvent::Signal() { - std::lock_guard<std::mutex> lock(mMutex); - if (!mSignaled.exchange(true, std::memory_order_release)) { + uint64_t prevSignalCount = mRemainingSignalCount.fetch_sub(1, std::memory_order_release); + DAWN_ASSERT(prevSignalCount != 0); + if (prevSignalCount == 1) { + std::lock_guard<std::mutex> lock(mMutex); for (SyncWaiter* w : std::move(mSyncWaiters)) { { std::lock_guard<std::mutex> waiterLock(w->mutex);
diff --git a/src/dawn/native/WaitListEvent.h b/src/dawn/native/WaitListEvent.h index fbb85b0..109df76 100644 --- a/src/dawn/native/WaitListEvent.h +++ b/src/dawn/native/WaitListEvent.h
@@ -45,7 +45,7 @@ class WaitListEvent : public RefCounted { public: - WaitListEvent(); + explicit WaitListEvent(uint64_t requiredSignalCount = 1); bool IsSignaled() const; void Signal(); @@ -65,7 +65,7 @@ }; mutable std::mutex mMutex; - std::atomic_bool mSignaled{false}; + std::atomic<uint64_t> mRemainingSignalCount; std::vector<raw_ptr<SyncWaiter>> mSyncWaiters; std::vector<SystemEventPipeSender> mAsyncWaiters; };
diff --git a/src/dawn/tests/white_box/WaitListEventTests.cpp b/src/dawn/tests/white_box/WaitListEventTests.cpp index b97c7c9..bc66255 100644 --- a/src/dawn/tests/white_box/WaitListEventTests.cpp +++ b/src/dawn/tests/white_box/WaitListEventTests.cpp
@@ -347,5 +347,16 @@ signaler.join(); } +// Test events that require multiple signal calls +TEST(WaitListEventTests, MultipleSignals) { + constexpr uint64_t kSignalCount = 10; + Ref<WaitListEvent> event1 = AcquireRef(new WaitListEvent(kSignalCount)); + for (uint64_t i = 0; i < kSignalCount; i++) { + EXPECT_FALSE(event1->IsSignaled()); + event1->Signal(); + } + EXPECT_TRUE(event1->IsSignaled()); +} + } // namespace } // namespace dawn::native