[libcxx-commits] [PATCH] D93456: [libcxx] Avoid overflows in the windows __libcpp_steady_clock_now()

Martin Storsjö via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Thu Dec 17 05:50:26 PST 2020


mstorsjo created this revision.
mstorsjo added reviewers: libc++, amccarth, rnk.
mstorsjo requested review of this revision.
Herald added a project: libc++.
Herald added 1 blocking reviewer(s): libc++.

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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D93456

Files:
  libcxx/src/chrono.cpp
  libcxx/test/std/utilities/time/time.clock/time.clock.steady/now.pass.cpp


Index: libcxx/test/std/utilities/time/time.clock/time.clock.steady/now.pass.cpp
===================================================================
--- libcxx/test/std/utilities/time/time.clock/time.clock.steady/now.pass.cpp
+++ libcxx/test/std/utilities/time/time.clock/time.clock.steady/now.pass.cpp
@@ -25,6 +25,7 @@
     C::time_point t1 = C::now();
     C::time_point t2 = C::now();
     assert(t2 >= t1);
+    assert(t2 > std::chrono::time_point<C>());
 
   return 0;
 }
Index: libcxx/src/chrono.cpp
===================================================================
--- libcxx/src/chrono.cpp
+++ libcxx/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)


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D93456.312472.patch
Type: text/x-patch
Size: 1109 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/libcxx-commits/attachments/20201217/ce4b573c/attachment.bin>


More information about the libcxx-commits mailing list