mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-29 22:20:48 +00:00
(Linux) Fixup futex_waitv
This commit is contained in:
parent
eae1c5afdd
commit
c6dcf3f1d3
@ -1,7 +1,6 @@
|
|||||||
#include "atomic.hpp"
|
#include "atomic.hpp"
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
// This definition is unused on Linux
|
|
||||||
#define USE_FUTEX
|
#define USE_FUTEX
|
||||||
#elif !defined(_WIN32)
|
#elif !defined(_WIN32)
|
||||||
#define USE_STD
|
#define USE_STD
|
||||||
@ -29,6 +28,21 @@ namespace utils
|
|||||||
#include "Utilities/sync.h"
|
#include "Utilities/sync.h"
|
||||||
#include "Utilities/StrFmt.h"
|
#include "Utilities/StrFmt.h"
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
|
static bool has_waitv()
|
||||||
|
{
|
||||||
|
static const bool s_has_waitv = []
|
||||||
|
{
|
||||||
|
syscall(SYS_futex_waitv, 0, 0, 0, 0, 0);
|
||||||
|
if (errno == ENOSYS)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
|
||||||
|
return s_has_waitv;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <array>
|
#include <array>
|
||||||
@ -843,7 +857,7 @@ atomic_wait_engine::wait(const void* data, u32 old_value, u64 timeout, atomic_wa
|
|||||||
::timespec ts{};
|
::timespec ts{};
|
||||||
if (timeout + 1)
|
if (timeout + 1)
|
||||||
{
|
{
|
||||||
if (ext) [[unlikely]]
|
if (ext && ext->data) [[unlikely]]
|
||||||
{
|
{
|
||||||
// futex_waitv uses absolute timeout
|
// futex_waitv uses absolute timeout
|
||||||
::clock_gettime(CLOCK_MONOTONIC, &ts);
|
::clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
@ -851,7 +865,7 @@ atomic_wait_engine::wait(const void* data, u32 old_value, u64 timeout, atomic_wa
|
|||||||
|
|
||||||
ts.tv_sec += timeout / 1'000'000'000;
|
ts.tv_sec += timeout / 1'000'000'000;
|
||||||
ts.tv_nsec += timeout % 1'000'000'000;
|
ts.tv_nsec += timeout % 1'000'000'000;
|
||||||
if (ts.tv_nsec > 1'000'000'000)
|
if (ts.tv_nsec >= 1'000'000'000)
|
||||||
{
|
{
|
||||||
ts.tv_sec++;
|
ts.tv_sec++;
|
||||||
ts.tv_nsec -= 1'000'000'000;
|
ts.tv_nsec -= 1'000'000'000;
|
||||||
@ -874,7 +888,7 @@ atomic_wait_engine::wait(const void* data, u32 old_value, u64 timeout, atomic_wa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ext_size) [[unlikely]]
|
if (ext_size && has_waitv()) [[unlikely]]
|
||||||
{
|
{
|
||||||
if (syscall(SYS_futex_waitv, +vec, ext_size + 1, 0, timeout + 1 ? &ts : nullptr, CLOCK_MONOTONIC) == -1)
|
if (syscall(SYS_futex_waitv, +vec, ext_size + 1, 0, timeout + 1 ? &ts : nullptr, CLOCK_MONOTONIC) == -1)
|
||||||
{
|
{
|
||||||
@ -887,8 +901,9 @@ atomic_wait_engine::wait(const void* data, u32 old_value, u64 timeout, atomic_wa
|
|||||||
fmt::throw_exception("futex_waitv: bad param");
|
fmt::throw_exception("futex_waitv: bad param");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
else if (has_waitv())
|
||||||
{
|
{
|
||||||
if (futex(const_cast<void*>(data), FUTEX_WAIT_PRIVATE, old_value, timeout + 1 ? &ts : nullptr) == -1)
|
if (futex(const_cast<void*>(data), FUTEX_WAIT_PRIVATE, old_value, timeout + 1 ? &ts : nullptr) == -1)
|
||||||
{
|
{
|
||||||
@ -897,9 +912,8 @@ atomic_wait_engine::wait(const void* data, u32 old_value, u64 timeout, atomic_wa
|
|||||||
fmt::throw_exception("futex: bad param");
|
fmt::throw_exception("futex: bad param");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!s_tls_wait_cb(data, 0, 0))
|
if (!s_tls_wait_cb(data, 0, 0))
|
||||||
@ -1242,8 +1256,14 @@ void atomic_wait_engine::notify_one(const void* data)
|
|||||||
s_tls_notify_cb(data, 0);
|
s_tls_notify_cb(data, 0);
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
futex(const_cast<void*>(data), FUTEX_WAKE_PRIVATE, 1);
|
if (has_waitv())
|
||||||
#else
|
{
|
||||||
|
futex(const_cast<void*>(data), FUTEX_WAKE_PRIVATE, 1);
|
||||||
|
if (s_tls_notify_cb)
|
||||||
|
s_tls_notify_cb(data, -1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
const uptr iptr = reinterpret_cast<uptr>(data) & (~s_ref_mask >> 16);
|
const uptr iptr = reinterpret_cast<uptr>(data) & (~s_ref_mask >> 16);
|
||||||
|
|
||||||
root_info::slot_search(iptr, [&](u32 cond_id)
|
root_info::slot_search(iptr, [&](u32 cond_id)
|
||||||
@ -1255,7 +1275,6 @@ void atomic_wait_engine::notify_one(const void* data)
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
#endif
|
|
||||||
|
|
||||||
if (s_tls_notify_cb)
|
if (s_tls_notify_cb)
|
||||||
s_tls_notify_cb(data, -1);
|
s_tls_notify_cb(data, -1);
|
||||||
@ -1268,8 +1287,14 @@ atomic_wait_engine::notify_all(const void* data)
|
|||||||
s_tls_notify_cb(data, 0);
|
s_tls_notify_cb(data, 0);
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
futex(const_cast<void*>(data), FUTEX_WAKE_PRIVATE, 1);
|
if (has_waitv())
|
||||||
#else
|
{
|
||||||
|
futex(const_cast<void*>(data), FUTEX_WAKE_PRIVATE, INT_MAX);
|
||||||
|
if (s_tls_notify_cb)
|
||||||
|
s_tls_notify_cb(data, -1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
const uptr iptr = reinterpret_cast<uptr>(data) & (~s_ref_mask >> 16);
|
const uptr iptr = reinterpret_cast<uptr>(data) & (~s_ref_mask >> 16);
|
||||||
|
|
||||||
// Array count for batch notification
|
// Array count for batch notification
|
||||||
@ -1342,7 +1367,6 @@ atomic_wait_engine::notify_all(const void* data)
|
|||||||
{
|
{
|
||||||
cond_free(~*(std::end(cond_ids) - i - 1));
|
cond_free(~*(std::end(cond_ids) - i - 1));
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (s_tls_notify_cb)
|
if (s_tls_notify_cb)
|
||||||
s_tls_notify_cb(data, -1);
|
s_tls_notify_cb(data, -1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user