Change sleep_for, sleep_until, and the condition_variable timed wait
functions to protect against duration and time_point overflow. Since
we're about to wait anyway, we can afford to spend a few more cycles on
this checking. I purposefully did not treat the timed try_locks with
overflow checking. This fixes
http://llvm.org/bugs/show_bug.cgi?id=13721 . I'm unsure if the standard
needs clarification in this area, or if this is simply QOI. The
<chrono> facilities were never intended to overflow check, but just to
not overflow if durations stayed within +/- 292 years.
llvm-svn: 162925
Cr-Mirrored-From: sso://chromium.googlesource.com/_direct/external/github.com/llvm/llvm-project
Cr-Mirrored-Commit: aad745a024a3d0fd573ac9649d4c659e6a713702
diff --git a/src/thread.cpp b/src/thread.cpp
index 4445b8d..8747adf 100644
--- a/src/thread.cpp
+++ b/src/thread.cpp
@@ -11,6 +11,7 @@
#include "exception"
#include "vector"
#include "future"
+#include "limits"
#include <sys/types.h>
#if !_WIN32
#if !__sun__ && !__linux__
@@ -83,11 +84,22 @@
sleep_for(const chrono::nanoseconds& ns)
{
using namespace chrono;
- if (ns >= nanoseconds::zero())
+ if (ns > nanoseconds::zero())
{
+ seconds s = duration_cast<seconds>(ns);
timespec ts;
- ts.tv_sec = static_cast<decltype(ts.tv_sec)>(duration_cast<seconds>(ns).count());
- ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns - seconds(ts.tv_sec)).count());
+ typedef decltype(ts.tv_sec) ts_sec;
+ _LIBCPP_CONSTEXPR ts_sec ts_sec_max = numeric_limits<ts_sec>::max();
+ if (s.count() < ts_sec_max)
+ {
+ ts.tv_sec = static_cast<ts_sec>(s.count());
+ ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((ns-s).count());
+ }
+ else
+ {
+ ts.tv_sec = ts_sec_max;
+ ts.tv_nsec = giga::num - 1;
+ }
nanosleep(&ts, 0);
}
}