diff --git a/rpcs3/util/atomic.cpp b/rpcs3/util/atomic.cpp index 04b390a590..87caf13817 100644 --- a/rpcs3/util/atomic.cpp +++ b/rpcs3/util/atomic.cpp @@ -284,6 +284,8 @@ void atomic_storage_futex::notify_one(const void* data) atomic_t& entry = s_hashtable[iptr % s_hashtable_size]; + bool fallback = false; + const auto [prev, ok] = entry.fetch_op([&](u64& value) { if (value & s_waiter_mask && (value & s_pointer_mask) == (iptr & s_pointer_mask)) @@ -305,30 +307,41 @@ void atomic_storage_futex::notify_one(const void* data) } value += s_signal_mask & -s_signal_mask; + + if ((value & s_signal_mask) == s_signal_mask) + { + // Signal will overflow, fallback + fallback = true; + return false; + } #endif return true; } + if (value & s_waiter_mask && (value & s_pointer_mask) == s_pointer_mask) + { + // Collision, notify everything + fallback = true; + } + return false; }); + if (fallback) + { + notify_all(data); + return; + } + if (ok) { #ifdef _WIN32 NtReleaseKeyedEvent(nullptr, &entry, false, nullptr); - return; #else futex(reinterpret_cast(&entry) + 4 * IS_BE_MACHINE, FUTEX_WAKE_PRIVATE, 1); - return; #endif } - - if ((prev & s_pointer_mask) == s_pointer_mask) - { - // Collision, notify everything - notify_all(data); - } } void atomic_storage_futex::notify_all(const void* data)