about summary refs log tree commit diff
path: root/src/libstd/sys
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2015-07-28 21:13:02 -0700
committerAlex Crichton <alex@alexcrichton.com>2015-07-29 10:24:40 -0700
commit43b2c4781e5d6e25dedfc480218ceda92d9dffad (patch)
treec333c753befe153331acb5443fcf8a38bd61ab0c /src/libstd/sys
parent68fc2d98d547a7045e918b03117c740179addb77 (diff)
downloadrust-43b2c4781e5d6e25dedfc480218ceda92d9dffad.tar.gz
rust-43b2c4781e5d6e25dedfc480218ceda92d9dffad.zip
std: Fix sub-second Condvar::wait_timeout_ms
The API we're calling requires us to pass an absolute point in time as an
argument (`pthread_cond_timedwait`) so we call `gettimeofday` ahead of time to
then add the specified duration to. Unfortuantely the current "add the duration"
logic forgot to take into account the current time's sub-second precision (e.g.
the `tv_usec` field was ignored), causing sub-second duration waits to return
spuriously.
Diffstat (limited to 'src/libstd/sys')
-rw-r--r--src/libstd/sys/unix/condvar.rs27
1 files changed, 14 insertions, 13 deletions
diff --git a/src/libstd/sys/unix/condvar.rs b/src/libstd/sys/unix/condvar.rs
index c8708190a2e..beecb445e8d 100644
--- a/src/libstd/sys/unix/condvar.rs
+++ b/src/libstd/sys/unix/condvar.rs
@@ -60,21 +60,22 @@ impl Condvar {
         let r = ffi::gettimeofday(&mut sys_now, ptr::null_mut());
         debug_assert_eq!(r, 0);
 
+        let nsec = dur.extra_nanos() as libc::c_long +
+                   (sys_now.tv_usec * 1000) as libc::c_long;
+        let extra = (nsec / 1_000_000_000) as libc::time_t;
+        let nsec = nsec % 1_000_000_000;
         let seconds = dur.secs() as libc::time_t;
-        let timeout = match sys_now.tv_sec.checked_add(seconds) {
-            Some(sec) => {
-                libc::timespec {
-                    tv_sec: sec,
-                    tv_nsec: dur.extra_nanos() as libc::c_long,
-                }
-            }
-            None => {
-                libc::timespec {
-                    tv_sec: <libc::time_t>::max_value(),
-                    tv_nsec: 1_000_000_000 - 1,
-                }
+
+        let timeout = sys_now.tv_sec.checked_add(extra).and_then(|s| {
+            s.checked_add(seconds)
+        }).map(|s| {
+            libc::timespec { tv_sec: s, tv_nsec: nsec }
+        }).unwrap_or_else(|| {
+            libc::timespec {
+                tv_sec: <libc::time_t>::max_value(),
+                tv_nsec: 1_000_000_000 - 1,
             }
-        };
+        });
 
         // And wait!
         let r = ffi::pthread_cond_timedwait(self.inner.get(), mutex::raw(mutex),