Skip to content

Commit 58deb70

Browse files
committed
Make it possible to have unboxed mutexes on specific platforms.
This commit keeps all mutexes boxed on all platforms, but makes it trivial to remove the box on some platforms later.
1 parent a8c2d4f commit 58deb70

File tree

10 files changed

+51
-9
lines changed

10 files changed

+51
-9
lines changed

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 = Box<Mutex>;
19+
1820
pub unsafe fn raw(m: &Mutex) -> *mut AtomicU32 {
1921
rwlock::raw(&m.0)
2022
}

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/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/mutex.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ pub struct Mutex {
44
locked: UnsafeCell<bool>,
55
}
66

7+
pub type MovableMutex = Box<Mutex>;
8+
79
unsafe impl Send for Mutex {}
810
unsafe impl Sync for Mutex {} // no threads on this platform
911

library/std/src/sys/vxworks/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/wasm/mutex_atomics.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ pub struct Mutex {
88
locked: AtomicUsize,
99
}
1010

11+
pub type MovableMutex = Box<Mutex>;
12+
1113
// Mutexes have a pretty simple implementation where they contain an `i32`
1214
// internally that is 0 when unlocked and 1 when the mutex is locked.
1315
// Acquisition has a fast path where it attempts to cmpxchg the 0 to a 1, and

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ pub struct Mutex {
2929
lock: AtomicUsize,
3030
}
3131

32+
pub type MovableMutex = Box<Mutex>;
33+
3234
unsafe impl Send for Mutex {}
3335
unsafe impl Sync for Mutex {}
3436

library/std/src/sys_common/condvar.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use crate::sys::condvar as imp;
2+
use crate::sys::mutex as mutex_imp;
23
use crate::sys_common::mutex::MovableMutex;
34
use crate::time::Duration;
4-
use check::CondvarCheck;
55

66
mod check;
77

8+
type CondvarCheck = <mutex_imp::MovableMutex as check::CondvarCheck>::Check;
9+
810
/// An OS-based condition variable.
911
pub struct Condvar {
1012
inner: Box<imp::Condvar>,

library/std/src/sys_common/condvar/check.rs

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,22 @@ use crate::sync::atomic::{AtomicUsize, Ordering};
22
use crate::sys::mutex as mutex_imp;
33
use crate::sys_common::mutex::MovableMutex;
44

5-
/// A `Condvar` will check it's only ever used with the same mutex, based on
6-
/// its (stable) address.
7-
pub struct CondvarCheck {
5+
pub trait CondvarCheck {
6+
type Check;
7+
}
8+
9+
/// For boxed mutexes, a `Condvar` will check it's only ever used with the same
10+
/// mutex, based on its (stable) address.
11+
impl CondvarCheck for Box<mutex_imp::Mutex> {
12+
type Check = SameMutexCheck;
13+
}
14+
15+
pub struct SameMutexCheck {
816
addr: AtomicUsize,
917
}
1018

11-
impl CondvarCheck {
19+
#[allow(dead_code)]
20+
impl SameMutexCheck {
1221
pub const fn new() -> Self {
1322
Self { addr: AtomicUsize::new(0) }
1423
}
@@ -21,3 +30,19 @@ impl CondvarCheck {
2130
}
2231
}
2332
}
33+
34+
/// Unboxed mutexes may move, so `Condvar` can not require its address to stay
35+
/// constant.
36+
impl CondvarCheck for mutex_imp::Mutex {
37+
type Check = NoCheck;
38+
}
39+
40+
pub struct NoCheck;
41+
42+
#[allow(dead_code)]
43+
impl NoCheck {
44+
pub const fn new() -> Self {
45+
Self
46+
}
47+
pub fn verify(&self, _: &MovableMutex) {}
48+
}

library/std/src/sys_common/mutex.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,16 +58,17 @@ impl Drop for StaticMutexGuard<'_> {
5858
///
5959
/// This mutex does not implement poisoning.
6060
///
61-
/// This is a wrapper around `Box<imp::Mutex>`, to allow the object to be moved
62-
/// without moving the raw mutex.
63-
pub struct MovableMutex(Box<imp::Mutex>);
61+
/// This is either a wrapper around `Box<imp::Mutex>` or `imp::Mutex`,
62+
/// depending on the platform. It is boxed on platforms where `imp::Mutex` may
63+
/// not be moved.
64+
pub struct MovableMutex(imp::MovableMutex);
6465

6566
unsafe impl Sync for MovableMutex {}
6667

6768
impl MovableMutex {
6869
/// Creates a new mutex.
6970
pub fn new() -> Self {
70-
let mut mutex = box imp::Mutex::new();
71+
let mut mutex = imp::MovableMutex::from(imp::Mutex::new());
7172
unsafe { mutex.init() };
7273
Self(mutex)
7374
}

0 commit comments

Comments
 (0)