Skip to content

Commit 32cbc65

Browse files
committed
Auto merge of #77380 - fusion-engineering-forks:unbox-the-mutex, r=dtolnay
Unbox mutexes and condvars on some platforms Both mutexes and condition variables contained a Box containing the actual os-specific object. This was done because moving these objects may cause undefined behaviour on some platforms. However, this is not needed on Windows[1], Wasm[2], cloudabi[2], and 'unsupported'[3], were the box was only needlessly making them less efficient. This change gets rid of the box on those platforms. On those platforms, `Condvar` can no longer verify it is only used with one `Mutex`, as mutexes no longer have a stable address. This was addressed and considered acceptable in #76932. [1]\: https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-initializesrwlock [2]\: These are just a single atomic integer together with futex wait/wake calls/instructions. [3]\: The `unsupported` platform doesn't support multiple threads at all.
2 parents 2251766 + b1ce7a3 commit 32cbc65

File tree

20 files changed

+121
-83
lines changed

20 files changed

+121
-83
lines changed

library/std/src/sync/condvar.rs

Lines changed: 4 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22
mod tests;
33

44
use crate::fmt;
5-
use crate::sync::atomic::{AtomicUsize, Ordering};
65
use crate::sync::{mutex, MutexGuard, PoisonError};
76
use crate::sys_common::condvar as sys;
8-
use crate::sys_common::mutex as sys_mutex;
97
use crate::sys_common::poison::{self, LockResult};
108
use crate::time::{Duration, Instant};
119

@@ -109,8 +107,7 @@ impl WaitTimeoutResult {
109107
/// ```
110108
#[stable(feature = "rust1", since = "1.0.0")]
111109
pub struct Condvar {
112-
inner: Box<sys::Condvar>,
113-
mutex: AtomicUsize,
110+
inner: sys::Condvar,
114111
}
115112

116113
impl Condvar {
@@ -126,11 +123,7 @@ impl Condvar {
126123
/// ```
127124
#[stable(feature = "rust1", since = "1.0.0")]
128125
pub fn new() -> Condvar {
129-
let mut c = Condvar { inner: box sys::Condvar::new(), mutex: AtomicUsize::new(0) };
130-
unsafe {
131-
c.inner.init();
132-
}
133-
c
126+
Condvar { inner: sys::Condvar::new() }
134127
}
135128

136129
/// Blocks the current thread until this condition variable receives a
@@ -192,7 +185,6 @@ impl Condvar {
192185
pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>) -> LockResult<MutexGuard<'a, T>> {
193186
let poisoned = unsafe {
194187
let lock = mutex::guard_lock(&guard);
195-
self.verify(lock);
196188
self.inner.wait(lock);
197189
mutex::guard_poison(&guard).get()
198190
};
@@ -389,7 +381,6 @@ impl Condvar {
389381
) -> LockResult<(MutexGuard<'a, T>, WaitTimeoutResult)> {
390382
let (poisoned, result) = unsafe {
391383
let lock = mutex::guard_lock(&guard);
392-
self.verify(lock);
393384
let success = self.inner.wait_timeout(lock, dur);
394385
(mutex::guard_poison(&guard).get(), WaitTimeoutResult(!success))
395386
};
@@ -510,7 +501,7 @@ impl Condvar {
510501
/// ```
511502
#[stable(feature = "rust1", since = "1.0.0")]
512503
pub fn notify_one(&self) {
513-
unsafe { self.inner.notify_one() }
504+
self.inner.notify_one()
514505
}
515506

516507
/// Wakes up all blocked threads on this condvar.
@@ -550,27 +541,7 @@ impl Condvar {
550541
/// ```
551542
#[stable(feature = "rust1", since = "1.0.0")]
552543
pub fn notify_all(&self) {
553-
unsafe { self.inner.notify_all() }
554-
}
555-
556-
fn verify(&self, mutex: &sys_mutex::MovableMutex) {
557-
let addr = mutex.raw() as *const _ as usize;
558-
match self.mutex.compare_and_swap(0, addr, Ordering::SeqCst) {
559-
// If we got out 0, then we have successfully bound the mutex to
560-
// this cvar.
561-
0 => {}
562-
563-
// If we get out a value that's the same as `addr`, then someone
564-
// already beat us to the punch.
565-
n if n == addr => {}
566-
567-
// Anything else and we're using more than one mutex on this cvar,
568-
// which is currently disallowed.
569-
_ => panic!(
570-
"attempted to use a condition variable with two \
571-
mutexes"
572-
),
573-
}
544+
self.inner.notify_all()
574545
}
575546
}
576547

@@ -588,10 +559,3 @@ impl Default for Condvar {
588559
Condvar::new()
589560
}
590561
}
591-
592-
#[stable(feature = "rust1", since = "1.0.0")]
593-
impl Drop for Condvar {
594-
fn drop(&mut self) {
595-
unsafe { self.inner.destroy() }
596-
}
597-
}

library/std/src/sync/condvar/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ fn wait_timeout_wake() {
191191

192192
#[test]
193193
#[should_panic]
194-
#[cfg_attr(target_os = "emscripten", ignore)]
194+
#[cfg_attr(not(unix), ignore)]
195195
fn two_mutexes() {
196196
let m = Arc::new(Mutex::new(()));
197197
let m2 = m.clone();

library/std/src/sys/cloudabi/condvar.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ pub struct Condvar {
1515
condvar: UnsafeCell<AtomicU32>,
1616
}
1717

18+
pub type MovableCondvar = Condvar;
19+
1820
unsafe impl Send for Condvar {}
1921
unsafe impl Sync for Condvar {}
2022

library/std/src/sys/cloudabi/mutex.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ extern "C" {
1515
// implemented identically.
1616
pub struct Mutex(RWLock);
1717

18+
pub type MovableMutex = Mutex;
19+
1820
pub unsafe fn raw(m: &Mutex) -> *mut AtomicU32 {
1921
rwlock::raw(&m.0)
2022
}

library/std/src/sys/hermit/condvar.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ pub struct Condvar {
1414
sem2: *const c_void,
1515
}
1616

17+
pub type MovableCondvar = Box<Condvar>;
18+
1719
unsafe impl Send for Condvar {}
1820
unsafe impl Sync for Condvar {}
1921

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ pub struct Condvar {
77
inner: SpinMutex<WaitVariable<()>>,
88
}
99

10+
pub type MovableCondvar = Box<Condvar>;
11+
1012
impl Condvar {
1113
pub const fn new() -> Condvar {
1214
Condvar { inner: SpinMutex::new(WaitVariable::new(())) }

library/std/src/sys/sgx/mutex.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ pub struct Mutex {
88
inner: SpinMutex<WaitVariable<bool>>,
99
}
1010

11+
pub type MovableMutex = Box<Mutex>;
12+
1113
// Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
1214
impl Mutex {
1315
pub const fn new() -> Mutex {

library/std/src/sys/unix/condvar.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ pub struct Condvar {
66
inner: UnsafeCell<libc::pthread_cond_t>,
77
}
88

9+
pub type MovableCondvar = Box<Condvar>;
10+
911
unsafe impl Send for Condvar {}
1012
unsafe impl Sync for Condvar {}
1113

library/std/src/sys/unix/mutex.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ pub struct Mutex {
55
inner: UnsafeCell<libc::pthread_mutex_t>,
66
}
77

8+
pub type MovableMutex = Box<Mutex>;
9+
810
#[inline]
911
pub unsafe fn raw(m: &Mutex) -> *mut libc::pthread_mutex_t {
1012
m.inner.get()

library/std/src/sys/unsupported/condvar.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use crate::time::Duration;
33

44
pub struct Condvar {}
55

6+
pub type MovableCondvar = Condvar;
7+
68
impl Condvar {
79
pub const fn new() -> Condvar {
810
Condvar {}

0 commit comments

Comments
 (0)