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/condition_variable.cpp b/src/condition_variable.cpp
index 552bce3..de0f6f4 100644
--- a/src/condition_variable.cpp
+++ b/src/condition_variable.cpp
@@ -51,10 +51,22 @@
__throw_system_error(EPERM,
"condition_variable::timed wait: mutex not locked");
nanoseconds d = tp.time_since_epoch();
+ if (d > nanoseconds(0x59682F000000E941))
+ d = nanoseconds(0x59682F000000E941);
timespec ts;
seconds s = duration_cast<seconds>(d);
- ts.tv_sec = static_cast<decltype(ts.tv_sec)>(s.count());
- ts.tv_nsec = static_cast<decltype(ts.tv_nsec)>((d - s).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)>((d - s).count());
+ }
+ else
+ {
+ ts.tv_sec = ts_sec_max;
+ ts.tv_nsec = giga::num - 1;
+ }
int ec = pthread_cond_timedwait(&__cv_, lk.mutex()->native_handle(), &ts);
if (ec != 0 && ec != ETIMEDOUT)
__throw_system_error(ec, "condition_variable timed_wait failed");