Skip to content

Commit

Permalink
Fix thread_ctrl::wait_for_accurate
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed May 24, 2023
1 parent 3aa15c8 commit 9a67e02
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 12 deletions.
26 changes: 17 additions & 9 deletions Utilities/Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2371,7 +2371,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, [[maybe_unused]] bool alert /* true */)
{
auto _this = g_tls_this_thread;

Expand Down Expand Up @@ -2415,29 +2415,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 & (4 + 1)))
{
return;
// Notified or aborted
return false;
}

// Wait for signal and thread state abort
atomic_wait::list<2> list{};
list.set<0>(_this->m_sync, 0, 4 + 1);
list.set<0>(_this->m_sync, 0, alert ? 4 + 1 : 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});
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)
{
return;
}

const auto _this = g_tls_this_thread;

using namespace std::chrono_literals;

const auto until = std::chrono::steady_clock::now() + 1us * usec;
Expand All @@ -2456,11 +2460,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 @@ -2479,7 +2487,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

0 comments on commit 9a67e02

Please sign in to comment.