mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-28 13:28:01 +03:00
SPU: Implement execution wake-up delay
This commit is contained in:
parent
149c593d89
commit
cf0fcf5a2a
7 changed files with 83 additions and 64 deletions
|
@ -2322,14 +2322,14 @@ thread_state thread_ctrl::state()
|
|||
return static_cast<thread_state>(_this->m_sync & 3);
|
||||
}
|
||||
|
||||
void thread_ctrl::_wait_for(u64 usec, [[maybe_unused]] bool alert /* true */)
|
||||
void thread_ctrl::wait_for(u64 usec, [[maybe_unused]] bool alert /* true */)
|
||||
{
|
||||
auto _this = g_tls_this_thread;
|
||||
|
||||
#ifdef __linux__
|
||||
static thread_local struct linux_timer_handle_t
|
||||
{
|
||||
// Allocate timer only if needed (i.e. someone calls _wait_for with alert and short period)
|
||||
// Allocate timer only if needed (i.e. someone calls wait_for with alert and short period)
|
||||
const int m_timer = timerfd_create(CLOCK_MONOTONIC, 0);
|
||||
|
||||
linux_timer_handle_t() noexcept
|
||||
|
@ -2383,6 +2383,58 @@ void thread_ctrl::_wait_for(u64 usec, [[maybe_unused]] bool alert /* true */)
|
|||
list.wait(atomic_wait_timeout{usec <= 0xffff'ffff'ffff'ffff / 1000 ? usec * 1000 : 0xffff'ffff'ffff'ffff});
|
||||
}
|
||||
|
||||
void thread_ctrl::wait_for_accurate(u64 usec)
|
||||
{
|
||||
if (!usec)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
const auto until = std::chrono::steady_clock::now() + 1us * usec;
|
||||
|
||||
while (true)
|
||||
{
|
||||
#ifdef __linux__
|
||||
// NOTE: Assumption that timer initialization has succeeded
|
||||
u64 host_min_quantum = usec <= 1000 ? 10 : 50;
|
||||
#else
|
||||
// Host scheduler quantum for windows (worst case)
|
||||
// NOTE: On ps3 this function has very high accuracy
|
||||
constexpr u64 host_min_quantum = 500;
|
||||
#endif
|
||||
if (usec >= host_min_quantum)
|
||||
{
|
||||
#ifdef __linux__
|
||||
// Do not wait for the last quantum to avoid loss of accuracy
|
||||
wait_for(usec - ((usec % host_min_quantum) + host_min_quantum), false);
|
||||
#else
|
||||
// Wait on multiple of min quantum for large durations to avoid overloading low thread cpus
|
||||
wait_for(usec - (usec % host_min_quantum), false);
|
||||
#endif
|
||||
}
|
||||
// TODO: Determine best value for yield delay
|
||||
else if (usec >= host_min_quantum / 2)
|
||||
{
|
||||
std::this_thread::yield();
|
||||
}
|
||||
else
|
||||
{
|
||||
busy_wait(100);
|
||||
}
|
||||
|
||||
const auto current = std::chrono::steady_clock::now();
|
||||
|
||||
if (current >= until)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
usec = (until - current).count();
|
||||
}
|
||||
}
|
||||
|
||||
std::string thread_ctrl::get_name_cached()
|
||||
{
|
||||
auto _this = thread_ctrl::g_tls_this_thread;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue