mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-16 16:21:02 +00:00
atomic.hpp: implement wait callback interface
Will be used to wake up threads uniformly.
This commit is contained in:
parent
53e7f6c5a5
commit
1668d6ee1b
@ -18,6 +18,12 @@ static constexpr s64 s_waiter_mask = 0x3fff;
|
|||||||
// Implementation detail (remaining bits out of 32)
|
// Implementation detail (remaining bits out of 32)
|
||||||
static constexpr s64 s_signal_mask = 0xffffffff & ~s_waiter_mask;
|
static constexpr s64 s_signal_mask = 0xffffffff & ~s_waiter_mask;
|
||||||
|
|
||||||
|
// Callback for wait() function, returns false if wait should return
|
||||||
|
static thread_local bool(*s_tls_wait_cb)(const void* data) = [](const void*)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
static inline bool ptr_cmp(const void* data, std::size_t size, u64 old_value)
|
static inline bool ptr_cmp(const void* data, std::size_t size, u64 old_value)
|
||||||
{
|
{
|
||||||
switch (size)
|
switch (size)
|
||||||
@ -73,7 +79,7 @@ namespace
|
|||||||
// Update node key
|
// Update node key
|
||||||
s_tls_waiter.key() = data;
|
s_tls_waiter.key() = data;
|
||||||
|
|
||||||
if (std::unique_lock lock(wmap.mutex); ptr_cmp(data, size, old_value))
|
if (std::unique_lock lock(wmap.mutex); ptr_cmp(data, size, old_value) && s_tls_wait_cb(data))
|
||||||
{
|
{
|
||||||
// Add node to the waiter list
|
// Add node to the waiter list
|
||||||
std::condition_variable& cond = wmap.list.insert(std::move(s_tls_waiter))->second.cond;
|
std::condition_variable& cond = wmap.list.insert(std::move(s_tls_waiter))->second.cond;
|
||||||
@ -140,14 +146,6 @@ void atomic_storage_futex::notify_all(const void* data)
|
|||||||
|
|
||||||
void atomic_storage_futex::wait(const void* data, std::size_t size, u64 old_value)
|
void atomic_storage_futex::wait(const void* data, std::size_t size, u64 old_value)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
|
||||||
if (OptWaitOnAddress)
|
|
||||||
{
|
|
||||||
OptWaitOnAddress(const_cast<volatile void*>(data), &old_value, size, INFINITE);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const std::intptr_t iptr = reinterpret_cast<std::intptr_t>(data);
|
const std::intptr_t iptr = reinterpret_cast<std::intptr_t>(data);
|
||||||
|
|
||||||
atomic_t<s64>& entry = s_hashtable[iptr % s_hashtable_size];
|
atomic_t<s64>& entry = s_hashtable[iptr % s_hashtable_size];
|
||||||
@ -182,7 +180,7 @@ void atomic_storage_futex::wait(const void* data, std::size_t size, u64 old_valu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ptr_cmp(data, size, old_value))
|
if (ptr_cmp(data, size, old_value) && s_tls_wait_cb(data))
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
NtWaitForKeyedEvent(nullptr, &entry, false, nullptr);
|
NtWaitForKeyedEvent(nullptr, &entry, false, nullptr);
|
||||||
@ -234,14 +232,6 @@ void atomic_storage_futex::wait(const void* data, std::size_t size, u64 old_valu
|
|||||||
|
|
||||||
void atomic_storage_futex::notify_one(const void* data)
|
void atomic_storage_futex::notify_one(const void* data)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
|
||||||
if (OptWaitOnAddress)
|
|
||||||
{
|
|
||||||
OptWakeByAddressSingle(const_cast<void*>(data));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const std::intptr_t iptr = reinterpret_cast<std::intptr_t>(data);
|
const std::intptr_t iptr = reinterpret_cast<std::intptr_t>(data);
|
||||||
|
|
||||||
atomic_t<s64>& entry = s_hashtable[iptr % s_hashtable_size];
|
atomic_t<s64>& entry = s_hashtable[iptr % s_hashtable_size];
|
||||||
@ -295,14 +285,6 @@ void atomic_storage_futex::notify_one(const void* data)
|
|||||||
|
|
||||||
void atomic_storage_futex::notify_all(const void* data)
|
void atomic_storage_futex::notify_all(const void* data)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
|
||||||
if (OptWaitOnAddress)
|
|
||||||
{
|
|
||||||
OptWakeByAddressAll(const_cast<void*>(data));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const std::intptr_t iptr = reinterpret_cast<std::intptr_t>(data);
|
const std::intptr_t iptr = reinterpret_cast<std::intptr_t>(data);
|
||||||
|
|
||||||
atomic_t<s64>& entry = s_hashtable[iptr % s_hashtable_size];
|
atomic_t<s64>& entry = s_hashtable[iptr % s_hashtable_size];
|
||||||
@ -339,3 +321,19 @@ void atomic_storage_futex::notify_all(const void* data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void atomic_storage_futex::set_wait_callback(bool(*cb)(const void* data))
|
||||||
|
{
|
||||||
|
if (cb)
|
||||||
|
{
|
||||||
|
s_tls_wait_cb = cb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void atomic_storage_futex::raw_notify(const void* data)
|
||||||
|
{
|
||||||
|
if (data)
|
||||||
|
{
|
||||||
|
notify_all(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,6 +17,10 @@ private:
|
|||||||
static void wait(const void* data, std::size_t size, u64 old_value);
|
static void wait(const void* data, std::size_t size, u64 old_value);
|
||||||
static void notify_one(const void* data);
|
static void notify_one(const void* data);
|
||||||
static void notify_all(const void* data);
|
static void notify_all(const void* data);
|
||||||
|
|
||||||
|
public:
|
||||||
|
static void set_wait_callback(bool(*)(const void* data));
|
||||||
|
static void raw_notify(const void* data);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper class, provides access to compiler-specific atomic intrinsics
|
// Helper class, provides access to compiler-specific atomic intrinsics
|
||||||
|
Loading…
x
Reference in New Issue
Block a user