]> gcc.gnu.org Git - gcc.git/commit
libstdc++: Optimise std::future::wait_for and fix futex polling
authorJonathan Wakely <jwakely@redhat.com>
Thu, 12 Nov 2020 21:25:14 +0000 (21:25 +0000)
committerJonathan Wakely <jwakely@redhat.com>
Thu, 12 Nov 2020 23:47:04 +0000 (23:47 +0000)
commit93fc47746815ea9dac413322fcade2931f757e7f
tree3d205d29fd50ca30fc087007cc18c36eab357f7e
parent421d0d0f54294a7bf2872b3b2ac521ce0fa9869e
libstdc++: Optimise std::future::wait_for and fix futex polling

To poll a std::future to see if it's ready you have to call one of the
timed waiting functions. The most obvious way is wait_for(0s) but this
was previously very inefficient because it would turn the relative
timeout to an absolute one by calling system_clock::now(). When the
relative timeout is zero (or less) we're obviously going to get a time
that has already passed, but the overhead of obtaining the current time
can be dozens of microseconds. The alternative is to call wait_until
with an absolute timeout that is in the past. If you know the clock's
epoch is in the past you can use a default constructed time_point.
Alternatively, using some_clock::time_point::min() gives the earliest
time point supported by the clock, which should be safe to assume is in
the past. However, using a futex wait with an absolute timeout before
the UNIX epoch fails and sets errno=EINVAL. The new code using futex
waits with absolute timeouts was not checking for this case, which could
result in hangs (or killing the process if the libray is built with
assertions enabled).

This patch checks for times before the epoch before attempting to wait
on a futex with an absolute timeout, which fixes the hangs or crashes.
It also makes it very fast to poll using an absolute timeout before the
epoch (because we skip the futex syscall).

It also makes future::wait_for avoid waiting at all when the relative
timeout is zero or less, to avoid the unnecessary overhead of getting
the current time. This makes polling with wait_for(0s) take only a few
cycles instead of dozens of milliseconds.

libstdc++-v3/ChangeLog:

* include/std/future (future::wait_for): Do not wait for
durations less than or equal to zero.
* src/c++11/futex.cc (_M_futex_wait_until)
(_M_futex_wait_until_steady): Do not wait for timeouts before
the epoch.
* testsuite/30_threads/future/members/poll.cc: New test.
libstdc++-v3/include/std/future
libstdc++-v3/src/c++11/futex.cc
libstdc++-v3/testsuite/30_threads/future/members/poll.cc [new file with mode: 0644]
This page took 0.052633 seconds and 5 git commands to generate.