|
9 | 9 | // except according to those terms.
|
10 | 10 |
|
11 | 11 | use cell::UnsafeCell;
|
12 |
| -use intrinsics::{atomic_cxchg, atomic_xadd, atomic_xchg}; |
| 12 | +use intrinsics::{atomic_cxchg, atomic_load, atomic_xadd, atomic_xchg}; |
13 | 13 | use ptr;
|
14 | 14 | use time::Duration;
|
15 | 15 |
|
16 | 16 | use sys::mutex::{mutex_unlock, Mutex};
|
17 |
| -use sys::syscall::{futex, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE}; |
| 17 | +use sys::syscall::{futex, TimeSpec, FUTEX_WAIT, FUTEX_WAKE, FUTEX_REQUEUE}; |
18 | 18 |
|
19 | 19 | pub struct Condvar {
|
20 | 20 | lock: UnsafeCell<*mut i32>,
|
@@ -63,33 +63,50 @@ impl Condvar {
|
63 | 63 | }
|
64 | 64 |
|
65 | 65 | #[inline]
|
66 |
| - pub fn wait(&self, mutex: &Mutex) { |
67 |
| - unsafe { |
68 |
| - let lock = self.lock.get(); |
69 |
| - let seq = self.seq.get(); |
70 |
| - |
71 |
| - if *lock != mutex.lock.get() { |
72 |
| - if *lock != ptr::null_mut() { |
73 |
| - panic!("Condvar used with more than one Mutex"); |
74 |
| - } |
| 66 | + unsafe fn wait_inner(&self, mutex: &Mutex, timeout_ptr: *const TimeSpec) -> bool { |
| 67 | + let lock = self.lock.get(); |
| 68 | + let seq = self.seq.get(); |
75 | 69 |
|
76 |
| - atomic_cxchg(lock as *mut usize, 0, mutex.lock.get() as usize); |
| 70 | + if *lock != mutex.lock.get() { |
| 71 | + if *lock != ptr::null_mut() { |
| 72 | + panic!("Condvar used with more than one Mutex"); |
77 | 73 | }
|
78 | 74 |
|
79 |
| - mutex_unlock(*lock); |
| 75 | + atomic_cxchg(lock as *mut usize, 0, mutex.lock.get() as usize); |
| 76 | + } |
80 | 77 |
|
81 |
| - let _ = futex(seq, FUTEX_WAIT, *seq, 0, ptr::null_mut()); |
| 78 | + mutex_unlock(*lock); |
82 | 79 |
|
83 |
| - while atomic_xchg(*lock, 2) != 0 { |
84 |
| - let _ = futex(*lock, FUTEX_WAIT, 2, 0, ptr::null_mut()); |
85 |
| - } |
| 80 | + let seq_before = atomic_load(seq); |
| 81 | + |
| 82 | + let _ = futex(seq, FUTEX_WAIT, seq_before, timeout_ptr as usize, ptr::null_mut()); |
| 83 | + |
| 84 | + let seq_after = atomic_load(seq); |
| 85 | + |
| 86 | + while atomic_xchg(*lock, 2) != 0 { |
| 87 | + let _ = futex(*lock, FUTEX_WAIT, 2, 0, ptr::null_mut()); |
| 88 | + } |
| 89 | + |
| 90 | + seq_before != seq_after |
| 91 | + } |
| 92 | + |
| 93 | + #[inline] |
| 94 | + pub fn wait(&self, mutex: &Mutex) { |
| 95 | + unsafe { |
| 96 | + assert!(self.wait_inner(mutex, ptr::null())); |
86 | 97 | }
|
87 | 98 | }
|
88 | 99 |
|
89 | 100 | #[inline]
|
90 |
| - pub fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { |
91 |
| - ::sys_common::util::dumb_print(format_args!("condvar wait_timeout\n")); |
92 |
| - unimplemented!(); |
| 101 | + pub fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { |
| 102 | + unsafe { |
| 103 | + let timeout = TimeSpec { |
| 104 | + tv_sec: dur.as_secs() as i64, |
| 105 | + tv_nsec: dur.subsec_nanos() as i32 |
| 106 | + }; |
| 107 | + |
| 108 | + self.wait_inner(mutex, &timeout as *const TimeSpec) |
| 109 | + } |
93 | 110 | }
|
94 | 111 |
|
95 | 112 | #[inline]
|
|
0 commit comments