From 0a5742587a82f8d77ec83852a6984d3d1b906a86 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 6 Nov 2020 12:53:49 +0300 Subject: [PATCH] atomic.cpp: upgrade raw_notify() Now it searches all semaphores if data arg is nullptr. Also it tries to wake up all threads if thread_id is 0. --- rpcs3/util/atomic.cpp | 61 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/rpcs3/util/atomic.cpp b/rpcs3/util/atomic.cpp index 7ad6b42b7b..99e740ac45 100644 --- a/rpcs3/util/atomic.cpp +++ b/rpcs3/util/atomic.cpp @@ -977,6 +977,67 @@ void atomic_wait_engine::set_notify_callback(void(*cb)(const void*, u64)) bool atomic_wait_engine::raw_notify(const void* data, u64 thread_id) { + // Special operation mode. Note that this is not atomic. + if (!data) + { + // Special path: search thread_id without pointer information + for (u32 i = 1; i < UINT16_MAX; i++) + { + const auto [_, ok] = s_cond_refs[i].fetch_op([&](u32& ref) + { + if (!ref) + { + // Skip dead semaphores + return false; + } + + if (thread_id) + { + u64 tid = 0; + std::memcpy(&tid, &cond_get(i)->tid, sizeof(tid)); + + if (tid != thread_id) + { + // Check thread first without locking (memory may be uninitialized) + return false; + } + } + + if (ref < UINT32_MAX) + { + // Need to busy loop otherwise (TODO) + ref++; + } + + return true; + }); + + if (ok) [[unlikely]] + { + const auto cond = cond_get(i); + + if (!thread_id || cond->tid == thread_id) + { + if (cond->forced_wakeup()) + { + cond->alert_native(); + + if (thread_id) + { + // Only if thread_id is speficied, stop only it and return true. + cond_free(i); + return true; + } + } + } + + cond_free(i); + } + } + + return false; + } + const std::uintptr_t iptr = reinterpret_cast(data); const auto slot = slot_get(iptr, &s_hashtable[(iptr) % s_hashtable_size]);