commit | 94011155bd920b76613c08cd48f84d1c89ff9636 | [log] [tgz] |
---|---|---|
author | Martin Storsjö <martin@martin.st> | Thu Dec 17 15:40:06 2020 +0200 |
committer | Copybara-Service <copybara-worker@google.com> | Tue Jan 12 14:06:21 2021 -0800 |
tree | bf7eb8435598a5885f5ba63f874804e5fbe94895 | |
parent | f6f550942c6937c82b68f7965dec572218ab4380 [diff] |
[libcxx] Avoid overflows in the windows __libcpp_steady_clock_now() As freq.QuadValue can be in the range of 10000000 to 19200000, the multiplication before division makes the calculation overflow and wrap to negative values every 16-30 minutes. Instead count the whole seconds separately before adding the scaled fractional seconds. Add a testcase for steady_clock to check that the values returned for now() compare as bigger than the zero time origin; this corresponds to a testcase in Qt [1] [2] (that failed spuriously due to this). [1] https://bugreports.qt.io/browse/QTBUG-89539 [2] https://code.qt.io/cgit/qt/qtbase.git/tree/tests/auto/corelib/kernel/qdeadlinetimer/tst_qdeadlinetimer.cpp?id=f8de5e54022b8b7471131b7ad55c83b69b2684c0#n569 Differential Revision: https://reviews.llvm.org/D93456 GitOrigin-RevId: 02f1d28ed6b8f33445dae3beed8b6cc8dada4312
diff --git a/src/chrono.cpp b/src/chrono.cpp index 1419cf2..5291d4f 100644 --- a/src/chrono.cpp +++ b/src/chrono.cpp
@@ -153,7 +153,10 @@ LARGE_INTEGER counter; (void) QueryPerformanceCounter(&counter); - return steady_clock::time_point(steady_clock::duration(counter.QuadPart * nano::den / freq.QuadPart)); + auto seconds = counter.QuadPart / freq.QuadPart; + auto fractions = counter.QuadPart % freq.QuadPart; + auto dur = seconds * nano::den + fractions * nano::den / freq.QuadPart; + return steady_clock::time_point(steady_clock::duration(dur)); } #elif defined(CLOCK_MONOTONIC)
diff --git a/test/std/utilities/time/time.clock/time.clock.steady/now.pass.cpp b/test/std/utilities/time/time.clock/time.clock.steady/now.pass.cpp index 4b8104d..14dc9a9 100644 --- a/test/std/utilities/time/time.clock/time.clock.steady/now.pass.cpp +++ b/test/std/utilities/time/time.clock/time.clock.steady/now.pass.cpp
@@ -25,6 +25,8 @@ C::time_point t1 = C::now(); C::time_point t2 = C::now(); assert(t2 >= t1); + // make sure t2 didn't wrap around + assert(t2 > std::chrono::time_point<C>()); return 0; }