[committed] libstdc++: Optimise std::future::wait_for and fix futex polling

Jonathan Wakely jwakely@redhat.com
Fri Nov 13 17:25:22 GMT 2020


On 13/11/20 11:02 +0000, Jonathan Wakely wrote:
>On 12/11/20 23:49 +0000, Jonathan Wakely wrote:
>>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.
>>
>>Tested powerpc64le-linux. Committed to trunk.
>>
>>I think the shortcut in future::wait_for is worth backporting. The
>>changes in src/c++11/futex.cc are not needed because the code using
>>absolute timeouts with futex waits is not present on any release
>>branch.
>
>I've committed this fix for the new test.

Backporting the change to gcc-10 revealed an overflow bug in the
existing code, resulting in blocking for years when given an absolute
timeout in the distant past. There's still a similar bug in the new
code (using futexes with absolute timeouts against clocks) where a
large chrono::seconds value can overflow and produce an incorrect
tv_sec value. Apart from the overflow itself being UB, the result in
that case is just a spurious wakeup (the call says it timed out when
it didn't reach the specified time). That should still be fixed, but
I'll do it separately.

Tested x86_64-linux. Committed to trunk.


-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch.txt
Type: text/x-patch
Size: 4902 bytes
Desc: not available
URL: <https://gcc.gnu.org/pipermail/gcc-patches/attachments/20201113/562e457d/attachment.bin>


More information about the Gcc-patches mailing list