Skip to content

Commit

Permalink
LV2 Timer: Fix thread wait_for_accurate, use it
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed Jun 5, 2023
1 parent 5e6aa45 commit 66242eb
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 13 deletions.
32 changes: 23 additions & 9 deletions Utilities/Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2396,7 +2396,7 @@ 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 */)
bool thread_ctrl::wait_for(u64 usec, bool alert)
{
auto _this = g_tls_this_thread;

Expand Down Expand Up @@ -2440,23 +2440,33 @@ void thread_ctrl::wait_for(u64 usec, [[maybe_unused]] bool alert /* true */)
timerfd_settime(fd_timer, 0, &timeout, NULL);
if (read(fd_timer, &missed, sizeof(missed)) != sizeof(missed))
sig_log.error("timerfd: read() failed");
return;
return true;
}
#endif

if (_this->m_sync.bit_test_reset(2) || _this->m_taskq)
if ((alert && (_this->m_sync.bit_test_reset(2) || _this->m_taskq)) || _this->m_sync & 1)
{
return;
// Notified or aborted
return false;
}

const atomic_wait_timeout timeout{usec <= 0xffff'ffff'ffff'ffff / 1000 ? usec * 1000 : 0xffff'ffff'ffff'ffff};

if (!alert)
{
_this->m_sync.wait(0, 1, timeout);
return true;
}

// Wait for signal and thread state abort
atomic_wait::list<2> list{};
list.set<0>(_this->m_sync, 0, 4 + 1);
list.set<1>(_this->m_taskq, nullptr);
list.wait(atomic_wait_timeout{usec <= 0xffff'ffff'ffff'ffff / 1000 ? usec * 1000 : 0xffff'ffff'ffff'ffff});
list.wait(timeout);
return true; // Unknown if notified for now
}

void thread_ctrl::wait_for_accurate(u64 usec)
void thread_ctrl::wait_for_accurate(u64 usec, bool alert)
{
if (!usec)
{
Expand All @@ -2481,11 +2491,15 @@ void thread_ctrl::wait_for_accurate(u64 usec)
{
#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);
if (!wait_for(usec - ((usec % host_min_quantum) + host_min_quantum), alert));
#else
// Wait on multiple of min quantum for large durations to avoid overloading low thread cpus
wait_for(usec - (usec % host_min_quantum), false);
if (!wait_for(usec - (usec % host_min_quantum), alert))
#endif
{
// Notified
return;
}
}
// TODO: Determine best value for yield delay
else if (usec >= host_min_quantum / 2)
Expand All @@ -2504,7 +2518,7 @@ void thread_ctrl::wait_for_accurate(u64 usec)
break;
}

usec = (until - current).count();
usec = std::chrono::duration_cast<std::chrono::microseconds>(until - current).count();
}
}

Expand Down
6 changes: 3 additions & 3 deletions Utilities/Thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -260,11 +260,11 @@ class thread_ctrl final
// Read current state, possibly executing some tasks
static thread_state state();

// Wait once with timeout. Infinite value is -1.
static void wait_for(u64 usec, bool alert = true);
// Wait once with timeout. Infinite value is -1. (returns false if known to be notified)
static bool wait_for(u64 usec, bool alert = true);

// Waiting with accurate timeout
static void wait_for_accurate(u64 usec);
static void wait_for_accurate(u64 usec, bool alert = false);

// Wait.
static inline void wait()
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/lv2/sys_timer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ void lv2_timer_thread::operator()()
sleep_time = std::min(sleep_time, u64{umax} / 100) * 100 / g_cfg.core.clocks_scale;
}

thread_ctrl::wait_for(sleep_time);
thread_ctrl::wait_for_accurate(sleep_time);

if (thread_ctrl::state() == thread_state::aborting)
{
Expand Down

0 comments on commit 66242eb

Please sign in to comment.