Skip to content

Commit d14e7f3

Browse files
committed
Propagate MutexState in Condvar
1 parent d5a9984 commit d14e7f3

File tree

8 files changed

+102
-43
lines changed

8 files changed

+102
-43
lines changed

library/std/src/sync/condvar.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use crate::time::{Duration, Instant};
1414
/// [`wait_timeout`]: Condvar::wait_timeout
1515
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
1616
#[stable(feature = "wait_timeout", since = "1.5.0")]
17-
pub struct WaitTimeoutResult(bool);
17+
pub struct WaitTimeoutResult(pub(crate) bool);
1818

1919
impl WaitTimeoutResult {
2020
/// Returns `true` if the wait was known to have timed out.
@@ -189,8 +189,11 @@ impl Condvar {
189189
pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> LockResult<MutexGuard<'a, T>> {
190190
let poisoned = unsafe {
191191
let lock = mutex::guard_lock(&guard);
192-
self.inner.wait(lock);
193-
mutex::guard_poison(&guard).get()
192+
let poison = mutex::guard_poison(&guard);
193+
if self.inner.wait(lock) == sys::MutexState::Poisoned {
194+
poison.set();
195+
}
196+
poison.get()
194197
};
195198
if poisoned { Err(PoisonError::new(guard)) } else { Ok(guard) }
196199
}
@@ -389,8 +392,12 @@ impl Condvar {
389392
) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> {
390393
let (poisoned, result) = unsafe {
391394
let lock = mutex::guard_lock(&guard);
392-
let success = self.inner.wait_timeout(lock, dur);
393-
(mutex::guard_poison(&guard).get(), WaitTimeoutResult(!success))
395+
let poison = mutex::guard_poison(&guard);
396+
let (r, s) = self.inner.wait_timeout(lock, dur);
397+
if s == sys::MutexState::Poisoned {
398+
poison.set();
399+
}
400+
(poison.get(), r)
394401
};
395402
if poisoned { Err(PoisonError::new((guard, result))) } else { Ok((guard, result)) }
396403
}

library/std/src/sys/sync/condvar/futex.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
use crate::sync::WaitTimeoutResult;
12
use crate::sync::atomic::AtomicU32;
23
use crate::sync::atomic::Ordering::Relaxed;
34
use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all};
4-
use crate::sys::sync::Mutex;
5+
use crate::sys::sync::{Mutex, MutexState};
56
use crate::time::Duration;
67

78
pub struct Condvar {
@@ -30,15 +31,23 @@ impl Condvar {
3031
futex_wake_all(&self.futex);
3132
}
3233

33-
pub unsafe fn wait(&self, mutex: &Mutex) {
34-
self.wait_optional_timeout(mutex, None);
34+
pub unsafe fn wait(&self, mutex: &Mutex) -> MutexState {
35+
self.wait_optional_timeout(mutex, None).1
3536
}
3637

37-
pub unsafe fn wait_timeout(&self, mutex: &Mutex, timeout: Duration) -> bool {
38+
pub unsafe fn wait_timeout(
39+
&self,
40+
mutex: &Mutex,
41+
timeout: Duration,
42+
) -> (WaitTimeoutResult, MutexState) {
3843
self.wait_optional_timeout(mutex, Some(timeout))
3944
}
4045

41-
unsafe fn wait_optional_timeout(&self, mutex: &Mutex, timeout: Option<Duration>) -> bool {
46+
unsafe fn wait_optional_timeout(
47+
&self,
48+
mutex: &Mutex,
49+
timeout: Option<Duration>,
50+
) -> (WaitTimeoutResult, MutexState) {
4251
// Examine the notification counter _before_ we unlock the mutex.
4352
let futex_value = self.futex.load(Relaxed);
4453

@@ -50,8 +59,8 @@ impl Condvar {
5059
let r = futex_wait(&self.futex, futex_value, timeout);
5160

5261
// Lock the mutex again.
53-
let _ = mutex.lock();
62+
let s = mutex.lock();
5463

55-
r
64+
(WaitTimeoutResult(!r), s)
5665
}
5766
}

library/std/src/sys/sync/condvar/itron.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
33
use crate::mem::replace;
44
use crate::ptr::NonNull;
5+
use crate::sync::WaitTimeoutResult;
56
use crate::sys::pal::itron::error::expect_success_aborting;
67
use crate::sys::pal::itron::spin::SpinMutex;
78
use crate::sys::pal::itron::time::with_tmos_strong;
89
use crate::sys::pal::itron::{abi, task};
9-
use crate::sys::sync::Mutex;
10+
use crate::sys::sync::{Mutex, MutexState};
1011
use crate::time::Duration;
1112

1213
// The implementation is inspired by the queue-based implementation shown in
@@ -57,7 +58,7 @@ impl Condvar {
5758
});
5859
}
5960

60-
pub unsafe fn wait(&self, mutex: &Mutex) {
61+
pub unsafe fn wait(&self, mutex: &Mutex) -> MutexState {
6162
// Construct `Waiter`.
6263
let mut waiter = waiter_queue::Waiter::new();
6364
let waiter = NonNull::from(&mut waiter);
@@ -79,9 +80,15 @@ impl Condvar {
7980
}
8081

8182
mutex.lock();
83+
84+
MutexState::Normal
8285
}
8386

84-
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
87+
pub unsafe fn wait_timeout(
88+
&self,
89+
mutex: &Mutex,
90+
dur: Duration,
91+
) -> (WaitTimeoutResult, MutexState) {
8592
// Construct and pin `Waiter`
8693
let mut waiter = waiter_queue::Waiter::new();
8794
let waiter = NonNull::from(&mut waiter);
@@ -117,7 +124,7 @@ impl Condvar {
117124
let success = self.waiters.with_locked(|waiters| unsafe { !waiters.remove(waiter) });
118125

119126
mutex.lock();
120-
success
127+
(WaitTimeoutResult(!success), MutexState::Normal)
121128
}
122129
}
123130

library/std/src/sys/sync/condvar/no_threads.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use crate::sys::sync::Mutex;
1+
use crate::sync::WaitTimeoutResult;
2+
use crate::sys::sync::{Mutex, MutexState};
23
use crate::time::Duration;
34

45
pub struct Condvar {}
@@ -16,11 +17,15 @@ impl Condvar {
1617
#[inline]
1718
pub fn notify_all(&self) {}
1819

19-
pub unsafe fn wait(&self, _mutex: &Mutex) {
20+
pub unsafe fn wait(&self, _mutex: &Mutex) -> MutexState {
2021
panic!("condvar wait not supported")
2122
}
2223

23-
pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool {
24+
pub unsafe fn wait_timeout(
25+
&self,
26+
_mutex: &Mutex,
27+
_dur: Duration,
28+
) -> (WaitTimeoutResult, MutexState) {
2429
panic!("condvar wait not supported");
2530
}
2631
}

library/std/src/sys/sync/condvar/pthread.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
use crate::cell::UnsafeCell;
22
use crate::ptr;
3+
use crate::sync::WaitTimeoutResult;
34
use crate::sync::atomic::AtomicPtr;
45
use crate::sync::atomic::Ordering::Relaxed;
5-
use crate::sys::sync::{Mutex, OnceBox};
6+
use crate::sys::sync::{Mutex, MutexState, OnceBox};
67
#[cfg(not(target_os = "nto"))]
78
use crate::sys::time::TIMESPEC_MAX;
89
#[cfg(target_os = "nto")]
@@ -107,11 +108,12 @@ impl Condvar {
107108
}
108109

109110
#[inline]
110-
pub unsafe fn wait(&self, mutex: &Mutex) {
111+
pub unsafe fn wait(&self, mutex: &Mutex) -> MutexState {
111112
let mutex = mutex.get_assert_locked();
112113
self.verify(mutex);
113114
let r = libc::pthread_cond_wait(self.get(), mutex);
114115
debug_assert_eq!(r, 0);
116+
MutexState::Normal
115117
}
116118

117119
// This implementation is used on systems that support pthread_condattr_setclock
@@ -124,7 +126,11 @@ impl Condvar {
124126
target_os = "horizon",
125127
target_vendor = "apple",
126128
)))]
127-
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
129+
pub unsafe fn wait_timeout(
130+
&self,
131+
mutex: &Mutex,
132+
dur: Duration,
133+
) -> (WaitTimeoutResult, MutexState) {
128134
use crate::sys::time::Timespec;
129135

130136
let mutex = mutex.get_assert_locked();
@@ -144,7 +150,7 @@ impl Condvar {
144150

145151
let r = libc::pthread_cond_timedwait(self.get(), mutex, &timeout);
146152
assert!(r == libc::ETIMEDOUT || r == 0);
147-
r == 0
153+
(WaitTimeoutResult(r != 0), MutexState::Normal)
148154
}
149155

150156
// This implementation is modeled after libcxx's condition_variable
@@ -156,7 +162,11 @@ impl Condvar {
156162
target_os = "horizon",
157163
target_vendor = "apple",
158164
))]
159-
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
165+
pub unsafe fn wait_timeout(
166+
&self,
167+
mutex: &Mutex,
168+
dur: Duration,
169+
) -> (WaitTimeoutResult, MutexState) {
160170
use crate::sys::time::SystemTime;
161171
use crate::time::Instant;
162172

@@ -191,6 +201,6 @@ impl Condvar {
191201

192202
// ETIMEDOUT is not a totally reliable method of determining timeout due
193203
// to clock shifts, so do the check ourselves
194-
now.elapsed() < dur
204+
(WaitTimeoutResult(now.elapsed() >= dur), MutexState::Normal)
195205
}
196206
}

library/std/src/sys/sync/condvar/sgx.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
use crate::sync::WaitTimeoutResult;
12
use crate::sys::pal::waitqueue::{SpinMutex, WaitQueue, WaitVariable};
2-
use crate::sys::sync::{Mutex, OnceBox};
3+
use crate::sys::sync::{Mutex, MutexState, OnceBox};
34
use crate::time::Duration;
45

56
pub struct Condvar {
@@ -26,15 +27,20 @@ impl Condvar {
2627
let _ = WaitQueue::notify_all(self.get().lock());
2728
}
2829

29-
pub unsafe fn wait(&self, mutex: &Mutex) {
30+
pub unsafe fn wait(&self, mutex: &Mutex) -> MutexState {
3031
let guard = self.get().lock();
3132
WaitQueue::wait(guard, || unsafe { mutex.unlock() });
32-
mutex.lock()
33+
mutex.lock();
34+
MutexState::Normal
3335
}
3436

35-
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
37+
pub unsafe fn wait_timeout(
38+
&self,
39+
mutex: &Mutex,
40+
dur: Duration,
41+
) -> (WaitTimeoutResult, MutexState) {
3642
let success = WaitQueue::wait_timeout(self.get(), dur, || unsafe { mutex.unlock() });
3743
mutex.lock();
38-
success
44+
(WaitTimeoutResult(!success), MutexState::Normal)
3945
}
4046
}

library/std/src/sys/sync/condvar/windows7.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::cell::UnsafeCell;
2-
use crate::sys::sync::{Mutex, mutex};
2+
use crate::sync::WaitTimeoutResult;
3+
use crate::sys::sync::{Mutex, MutexState, mutex};
34
use crate::sys::{c, os};
45
use crate::time::Duration;
56

@@ -17,24 +18,32 @@ impl Condvar {
1718
}
1819

1920
#[inline]
20-
pub unsafe fn wait(&self, mutex: &Mutex) {
21+
pub unsafe fn wait(&self, mutex: &Mutex) -> MutexState {
2122
let r = c::SleepConditionVariableSRW(self.inner.get(), mutex::raw(mutex), c::INFINITE, 0);
2223
debug_assert!(r != 0);
24+
MutexState::Normal
2325
}
2426

25-
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
27+
pub unsafe fn wait_timeout(
28+
&self,
29+
mutex: &Mutex,
30+
dur: Duration,
31+
) -> (WaitTimeoutResult, MutexState) {
2632
let r = c::SleepConditionVariableSRW(
2733
self.inner.get(),
2834
mutex::raw(mutex),
2935
crate::sys::pal::dur2timeout(dur),
3036
0,
3137
);
32-
if r == 0 {
33-
debug_assert_eq!(os::errno() as usize, c::ERROR_TIMEOUT as usize);
34-
false
35-
} else {
36-
true
37-
}
38+
(
39+
WaitTimeoutResult(if r == 0 {
40+
debug_assert_eq!(os::errno() as usize, c::ERROR_TIMEOUT as usize);
41+
true
42+
} else {
43+
false
44+
}),
45+
MutexState::Normal,
46+
)
3847
}
3948

4049
#[inline]

library/std/src/sys/sync/condvar/xous.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use core::sync::atomic::{AtomicUsize, Ordering};
22

33
use crate::os::xous::ffi::{blocking_scalar, scalar};
44
use crate::os::xous::services::{TicktimerScalar, ticktimer_server};
5-
use crate::sys::sync::Mutex;
5+
use crate::sync::WaitTimeoutResult;
6+
use crate::sys::sync::{Mutex, MutexState};
67
use crate::time::Duration;
78

89
// The implementation is inspired by Andrew D. Birrell's paper
@@ -119,18 +120,23 @@ impl Condvar {
119120
awoken
120121
}
121122

122-
pub unsafe fn wait(&self, mutex: &Mutex) {
123+
pub unsafe fn wait(&self, mutex: &Mutex) -> MutexState {
123124
// Wait for 0 ms, which is a special case to "wait forever"
124125
self.wait_ms(mutex, 0);
126+
MutexState::Normal
125127
}
126128

127-
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
129+
pub unsafe fn wait_timeout(
130+
&self,
131+
mutex: &Mutex,
132+
dur: Duration,
133+
) -> (WaitTimeoutResult, MutexState) {
128134
let mut millis = dur.as_millis() as usize;
129135
// Ensure we don't wait for 0 ms, which would cause us to wait forever
130136
if millis == 0 {
131137
millis = 1;
132138
}
133-
self.wait_ms(mutex, millis)
139+
(WaitTimeoutResult(!self.wait_ms(mutex, millis)), MutexState::Normal)
134140
}
135141
}
136142

0 commit comments

Comments
 (0)