libstdc++: Loop when futex waits against arbitrary clock
authorMike Crowe <mac@mcrowe.com>
Fri, 11 Sep 2020 13:25:00 +0000 (14:25 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Fri, 11 Sep 2020 13:28:50 +0000 (14:28 +0100)
commitb9faa3301c523c2c165387da4b19e659f7362a92
treefb1249738ad5942d228fd766eea59de654143ea3
parent87fce1923fcc8d6ef508500475c149082dc9d338
libstdc++: Loop when futex waits against arbitrary clock

If std::future::wait_until is passed a time point measured against a
clock that is neither std::chrono::steady_clock nor
std::chrono::system_clock then the generic implementation of
__atomic_futex_unsigned::_M_load_when_equal_until is called which
calculates the timeout based on __clock_t and calls the
_M_load_when_equal_until method for that clock to perform the actual
wait.

There's no guarantee that __clock_t is running at the same speed as the
caller's clock, so if the underlying wait times out timeout we need to
check the timeout against the caller's clock again before potentially
looping.

Also add two extra tests to the testsuite's async.cc:

* run test03 with steady_clock_copy, which behaves identically to
  chrono::steady_clock, but isn't chrono::steady_clock. This causes
  the overload of __atomic_futex_unsigned::_M_load_when_equal_until
  that takes an arbitrary clock to be called.

* invent test04 which uses a deliberately slow running clock in order
  to exercise the looping behaviour of
  __atomic_futex_unsigned::_M_load_when_equal_until described above.

libstdc++-v3/ChangeLog:

* include/bits/atomic_futex.h
(__atomic_futex_unsigned::_M_load_when_equal_until): Add
loop on generic _Clock to check the timeout against _Clock
again after _M_load_when_equal_until returns indicating a
timeout.
* testsuite/30_threads/async/async.cc: Invent slow_clock
that runs at an eleventh of steady_clock's speed. Use it
to test the user-supplied-clock variant of
__atomic_futex_unsigned::_M_load_when_equal_until works
generally with test03 and loops correctly when the timeout
time hasn't been reached in test04.
libstdc++-v3/include/bits/atomic_futex.h
libstdc++-v3/testsuite/30_threads/async/async.cc