[libcxx-dev] Questions regarding implementation of std::this_thread::sleep_until

Erik Rigtorp via libcxx-dev libcxx-dev at lists.llvm.org
Thu Mar 5 12:30:02 PST 2020


Hi!

libcxx seems to have a suboptimal implementation of
std::this_thread::sleep_until for Linux.

Currently it's implemented using pthread_cond_timedwait:
template <class _Clock, class _Duration>
void
sleep_until(const chrono::time_point<_Clock, _Duration>& __t)
{
  using namespace chrono;
  mutex __mut;
  condition_variable __cv;
  unique_lock<mutex> __lk(__mut);
  while (_Clock::now() < __t)
    __cv.wait_until(__lk, __t);
}
(https://github.com/llvm/llvm-project/blob/master/libcxx/include/thread#L391)

This leads to unnecessary stores to the stack and useless atomic
operations that can potential cause memory bus traffic. On Linux this
could be implemented using the clock_nanosleep() function with the
TIMER_ABSTIME flag.

For std::chrono::steady_clock there is a specialization:
template <class _Duration>
inline _LIBCPP_INLINE_VISIBILITY
void
sleep_until(const chrono::time_point<chrono::steady_clock, _Duration>& __t)
{
  using namespace chrono;
  sleep_for(__t - steady_clock::now());
}
(https://github.com/llvm/llvm-project/blob/master/libcxx/include/thread#L404)

This has a race condition where the thread could be preempted after
calling now() but before sleeping. The race window is extremely small,
but will lead to increased jitter in actual deadline. If the thread is
using something like linux SCHED_IDLE or competing with threads using
SCHED_FIFO/SCHED_RR the likelihood of hitting this race could be high.
Using clock_nanosleep() would also help here.

Linux and most BSDs support the clock_nanosleep() function, it makes
sense to add a feature detection for it and use it if supported.

Regards,
Erik Rigtorp


More information about the libcxx-dev mailing list