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

Jonathan Wakely jwakely@redhat.com
Fri Nov 13 21:16:50 GMT 2020


On 13/11/20 21:12 +0000, Jonathan Wakely wrote:
>On 13/11/20 20:29 +0000, Mike Crowe via Libstdc++ wrote:
>>On Friday 13 November 2020 at 17:25:22 +0000, Jonathan Wakely wrote:
>>>+  // Return the relative duration from (now_s + now_ns) to (abs_s + abs_ns)
>>>+  // as a timespec.
>>>+  struct timespec
>>>+  relative_timespec(chrono::seconds abs_s, chrono::nanoseconds abs_ns,
>>>+		    time_t now_s, long now_ns)
>>>+  {
>>>+    struct timespec rt;
>>>+
>>>+    // Did we already time out?
>>>+    if (now_s > abs_s.count())
>>>+      {
>>>+	rt.tv_sec = -1;
>>>+	return rt;
>>>+      }
>>>+
>>>+    auto rel_s = abs_s.count() - now_s;
>>>+
>>>+    // Avoid overflows
>>>+    if (rel_s > __gnu_cxx::__int_traits<time_t>::__max)
>>>+      rel_s = __gnu_cxx::__int_traits<time_t>::__max;
>>>+    else if (rel_s < __gnu_cxx::__int_traits<time_t>::__min)
>>>+      rel_s = __gnu_cxx::__int_traits<time_t>::__min;
>>
>>I may be missing something, but if the line above executes...
>>
>>>+
>>>+    // Convert the absolute timeout value to a relative timeout
>>>+    rt.tv_sec = rel_s;
>>>+    rt.tv_nsec = abs_ns.count() - now_ns;
>>>+    if (rt.tv_nsec < 0)
>>>+      {
>>>+	rt.tv_nsec += 1000000000;
>>>+	--rt.tv_sec;
>>
>>...and so does this line above, then I think that we'll end up
>>underflowing. (Presumably rt.tv_sec will wrap round to being some time in
>>2038 on most 32-bit targets.)
>
>Ugh.
>
>>I'm currently trying to persuade myself that this can actually happen and
>>if so work out how to come up with a test case for it.
>
>Maybe something like:
>
>auto d = chrono::floor<chrono::seconds>(system_clock::now().time_since_epoch() - seconds(INT_MAX + 2LL));
>fut.wait_until(system_clock::time_point(d));
>
>This will create a sys_time with a value that is slightly more than
>INT_MAX seconds before the current time, with a zero nanoseconds
>component. The difference between the gettimeofday result and this
>time will be slightly more negative than INT_MIN and so will overflow
>a 32-bit time_t, causing the code to use __int_traits<time_t>::__min.
>As long as the gettimeofday call doesn't happen to also have a zero
>nanoseconds component, the difference of the nanoseconds values will
>be negative, and we will decrement the time_t value.
>
>>I don't believe that this part changed in your later patch.
>
>Right. Thanks for catching this.
>
>The attached patch should fix it. There's no point clamping very
>negative values to the minimum time_t value, since any relative
>timeout less than zero has already passed. So we can just use -1
>there (and not bother with the tv_nsec field at all):
>
>    else if (rel_s <= 0) [[unlikely]]
>      {
>	rt.tv_sec = -1;
>      }

Gah, no, this has to be < 0 not <= 0 otherwise we treat 0.1s as -1.1

And we should probably lose the [[unlikely]] there, since it's quite
feasible that an absolute time in the recent past gets used.




More information about the Libstdc++ mailing list