Skip to content

Commit e9ec022

Browse files
authored
Rollup merge of #97647 - m-ou-se:lazy-box-locks, r=Amanieu
Lazily allocate and initialize pthread locks. Lazily allocate and initialize pthread locks. This allows {Mutex, Condvar, RwLock}::new() to be const, while still using the platform's native locks for features like priority inheritance and debug tooling. E.g. on macOS, we cannot directly use the (private) APIs that pthread's locks are implemented with, making it impossible for us to use anything other than pthread while still preserving priority inheritance, etc. This PR doesn't yet make the public APIs const. That's for a separate PR with an FCP. Tracking issue: #93740
2 parents 07f586f + 6a417d4 commit e9ec022

29 files changed

+184
-123
lines changed

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

+7-3
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,13 @@ impl Condvar {
7070
mutex.lock();
7171
res == 0
7272
}
73+
}
7374

74-
pub unsafe fn destroy(&self) {
75-
let _ = abi::sem_destroy(self.sem1);
76-
let _ = abi::sem_destroy(self.sem2);
75+
impl Drop for Condvar {
76+
fn drop(&mut self) {
77+
unsafe {
78+
let _ = abi::sem_destroy(self.sem1);
79+
let _ = abi::sem_destroy(self.sem2);
80+
}
7781
}
7882
}

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

-3
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,4 @@ impl Mutex {
215215
}
216216
guard.locked
217217
}
218-
219-
#[inline]
220-
pub unsafe fn destroy(&self) {}
221218
}

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

-6
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,6 @@ impl RwLock {
8484
// FIXME: should only wake up one of these some of the time
8585
self.cond.notify_all();
8686
}
87-
88-
#[inline]
89-
pub unsafe fn destroy(&self) {
90-
self.lock.destroy();
91-
self.cond.destroy();
92-
}
9387
}
9488

9589
impl State {

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

-2
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,6 @@ impl Condvar {
117117
unsafe { mutex.lock() };
118118
success
119119
}
120-
121-
pub unsafe fn destroy(&self) {}
122120
}
123121

124122
mod waiter_queue {

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

+3-1
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@ impl Mutex {
6464
}
6565
}
6666
}
67+
}
6768

68-
pub unsafe fn destroy(&self) {
69+
impl Drop for Mutex {
70+
fn drop(&mut self) {
6971
if let Some(mtx) = self.mtx.get().map(|x| x.0) {
7072
expect_success_aborting(unsafe { abi::del_mtx(mtx) }, &"del_mtx");
7173
}

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

+8-7
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::sys::locks::Mutex;
2+
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
23
use crate::time::Duration;
34

45
use super::waitqueue::{SpinMutex, WaitQueue, WaitVariable};
@@ -7,16 +8,19 @@ pub struct Condvar {
78
inner: SpinMutex<WaitVariable<()>>,
89
}
910

10-
pub type MovableCondvar = Box<Condvar>;
11+
pub(crate) type MovableCondvar = LazyBox<Condvar>;
12+
13+
impl LazyInit for Condvar {
14+
fn init() -> Box<Self> {
15+
Box::new(Self::new())
16+
}
17+
}
1118

1219
impl Condvar {
1320
pub const fn new() -> Condvar {
1421
Condvar { inner: SpinMutex::new(WaitVariable::new(())) }
1522
}
1623

17-
#[inline]
18-
pub unsafe fn init(&mut self) {}
19-
2024
#[inline]
2125
pub unsafe fn notify_one(&self) {
2226
let _ = WaitQueue::notify_one(self.inner.lock());
@@ -38,7 +42,4 @@ impl Condvar {
3842
unsafe { mutex.lock() };
3943
success
4044
}
41-
42-
#[inline]
43-
pub unsafe fn destroy(&self) {}
4445
}

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

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
use super::waitqueue::{try_lock_or_false, SpinMutex, WaitQueue, WaitVariable};
2+
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
23

34
pub struct Mutex {
45
inner: SpinMutex<WaitVariable<bool>>,
56
}
67

78
// not movable: see UnsafeList implementation
8-
pub type MovableMutex = Box<Mutex>;
9+
pub(crate) type MovableMutex = LazyBox<Mutex>;
10+
11+
impl LazyInit for Mutex {
12+
fn init() -> Box<Self> {
13+
Box::new(Self::new())
14+
}
15+
}
916

1017
// Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
1118
impl Mutex {
@@ -52,7 +59,4 @@ impl Mutex {
5259
true
5360
}
5461
}
55-
56-
#[inline]
57-
pub unsafe fn destroy(&self) {}
5862
}

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

+8-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
mod tests;
33

44
use crate::num::NonZeroUsize;
5+
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
56

67
use super::waitqueue::{
78
try_lock_or_false, NotifiedTcs, SpinMutex, SpinMutexGuard, WaitQueue, WaitVariable,
@@ -13,7 +14,13 @@ pub struct RwLock {
1314
writer: SpinMutex<WaitVariable<bool>>,
1415
}
1516

16-
pub type MovableRwLock = Box<RwLock>;
17+
pub(crate) type MovableRwLock = LazyBox<RwLock>;
18+
19+
impl LazyInit for RwLock {
20+
fn init() -> Box<Self> {
21+
Box::new(Self::new())
22+
}
23+
}
1724

1825
// Check at compile time that RwLock size matches C definition (see test_c_rwlock_initializer below)
1926
//
@@ -168,9 +175,6 @@ impl RwLock {
168175
unsafe { self.__read_unlock(rguard, wguard) };
169176
}
170177
}
171-
172-
#[inline]
173-
pub unsafe fn destroy(&self) {}
174178
}
175179

176180
// The following functions are needed by libunwind. These symbols are named

library/std/src/sys/solid/rwlock.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -82,9 +82,11 @@ impl RwLock {
8282
let rwl = self.raw();
8383
expect_success_aborting(unsafe { abi::rwl_unl_rwl(rwl) }, &"rwl_unl_rwl");
8484
}
85+
}
8586

87+
impl Drop for RwLock {
8688
#[inline]
87-
pub unsafe fn destroy(&self) {
89+
fn drop(&mut self) {
8890
if let Some(rwl) = self.rwl.get().map(|x| x.0) {
8991
expect_success_aborting(unsafe { abi::rwl_del_rwl(rwl) }, &"rwl_del_rwl");
9092
}

library/std/src/sys/unix/locks/futex.rs

-9
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ impl Mutex {
2424
#[inline]
2525
pub unsafe fn init(&mut self) {}
2626

27-
#[inline]
28-
pub unsafe fn destroy(&self) {}
29-
3027
#[inline]
3128
pub unsafe fn try_lock(&self) -> bool {
3229
self.futex.compare_exchange(0, 1, Acquire, Relaxed).is_ok()
@@ -118,12 +115,6 @@ impl Condvar {
118115
Self { futex: AtomicU32::new(0) }
119116
}
120117

121-
#[inline]
122-
pub unsafe fn init(&mut self) {}
123-
124-
#[inline]
125-
pub unsafe fn destroy(&self) {}
126-
127118
// All the memory orderings here are `Relaxed`,
128119
// because synchronization is done by unlocking and locking the mutex.
129120

library/std/src/sys/unix/locks/futex_rwlock.rs

-3
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,6 @@ impl RwLock {
6363
Self { state: AtomicU32::new(0), writer_notify: AtomicU32::new(0) }
6464
}
6565

66-
#[inline]
67-
pub unsafe fn destroy(&self) {}
68-
6966
#[inline]
7067
pub unsafe fn try_read(&self) -> bool {
7168
self.state

library/std/src/sys/unix/locks/mod.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,14 @@ cfg_if::cfg_if! {
99
))] {
1010
mod futex;
1111
mod futex_rwlock;
12-
pub use futex::{Mutex, MovableMutex, Condvar, MovableCondvar};
13-
pub use futex_rwlock::{RwLock, MovableRwLock};
12+
pub(crate) use futex::{Mutex, MovableMutex, MovableCondvar};
13+
pub(crate) use futex_rwlock::{RwLock, MovableRwLock};
1414
} else {
1515
mod pthread_mutex;
1616
mod pthread_rwlock;
1717
mod pthread_condvar;
18-
pub use pthread_mutex::{Mutex, MovableMutex};
19-
pub use pthread_rwlock::{RwLock, MovableRwLock};
20-
pub use pthread_condvar::{Condvar, MovableCondvar};
18+
pub(crate) use pthread_mutex::{Mutex, MovableMutex};
19+
pub(crate) use pthread_rwlock::{RwLock, MovableRwLock};
20+
pub(crate) use pthread_condvar::MovableCondvar;
2121
}
2222
}

library/std/src/sys/unix/locks/pthread_condvar.rs

+22-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use crate::cell::UnsafeCell;
22
use crate::sys::locks::{pthread_mutex, Mutex};
3+
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
34
use crate::time::Duration;
45

56
pub struct Condvar {
67
inner: UnsafeCell<libc::pthread_cond_t>,
78
}
89

9-
pub type MovableCondvar = Box<Condvar>;
10+
pub(crate) type MovableCondvar = LazyBox<Condvar>;
1011

1112
unsafe impl Send for Condvar {}
1213
unsafe impl Sync for Condvar {}
@@ -18,6 +19,14 @@ fn saturating_cast_to_time_t(value: u64) -> libc::time_t {
1819
if value > <libc::time_t>::MAX as u64 { <libc::time_t>::MAX } else { value as libc::time_t }
1920
}
2021

22+
impl LazyInit for Condvar {
23+
fn init() -> Box<Self> {
24+
let mut condvar = Box::new(Self::new());
25+
unsafe { condvar.init() };
26+
condvar
27+
}
28+
}
29+
2130
impl Condvar {
2231
pub const fn new() -> Condvar {
2332
// Might be moved and address is changing it is better to avoid
@@ -32,14 +41,14 @@ impl Condvar {
3241
target_os = "android",
3342
target_os = "redox"
3443
))]
35-
pub unsafe fn init(&mut self) {}
44+
unsafe fn init(&mut self) {}
3645

3746
// NOTE: ESP-IDF's PTHREAD_COND_INITIALIZER support is not released yet
3847
// So on that platform, init() should always be called
3948
// Moreover, that platform does not have pthread_condattr_setclock support,
4049
// hence that initialization should be skipped as well
4150
#[cfg(target_os = "espidf")]
42-
pub unsafe fn init(&mut self) {
51+
unsafe fn init(&mut self) {
4352
let r = libc::pthread_cond_init(self.inner.get(), crate::ptr::null());
4453
assert_eq!(r, 0);
4554
}
@@ -52,7 +61,7 @@ impl Condvar {
5261
target_os = "redox",
5362
target_os = "espidf"
5463
)))]
55-
pub unsafe fn init(&mut self) {
64+
unsafe fn init(&mut self) {
5665
use crate::mem::MaybeUninit;
5766
let mut attr = MaybeUninit::<libc::pthread_condattr_t>::uninit();
5867
let r = libc::pthread_condattr_init(attr.as_mut_ptr());
@@ -179,14 +188,14 @@ impl Condvar {
179188

180189
#[inline]
181190
#[cfg(not(target_os = "dragonfly"))]
182-
pub unsafe fn destroy(&self) {
191+
unsafe fn destroy(&mut self) {
183192
let r = libc::pthread_cond_destroy(self.inner.get());
184193
debug_assert_eq!(r, 0);
185194
}
186195

187196
#[inline]
188197
#[cfg(target_os = "dragonfly")]
189-
pub unsafe fn destroy(&self) {
198+
unsafe fn destroy(&mut self) {
190199
let r = libc::pthread_cond_destroy(self.inner.get());
191200
// On DragonFly pthread_cond_destroy() returns EINVAL if called on
192201
// a condvar that was just initialized with
@@ -195,3 +204,10 @@ impl Condvar {
195204
debug_assert!(r == 0 || r == libc::EINVAL);
196205
}
197206
}
207+
208+
impl Drop for Condvar {
209+
#[inline]
210+
fn drop(&mut self) {
211+
unsafe { self.destroy() };
212+
}
213+
}

library/std/src/sys/unix/locks/pthread_mutex.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
use crate::cell::UnsafeCell;
22
use crate::mem::MaybeUninit;
33
use crate::sys::cvt_nz;
4+
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
45

56
pub struct Mutex {
67
inner: UnsafeCell<libc::pthread_mutex_t>,
78
}
89

9-
pub type MovableMutex = Box<Mutex>;
10+
pub(crate) type MovableMutex = LazyBox<Mutex>;
1011

1112
#[inline]
1213
pub unsafe fn raw(m: &Mutex) -> *mut libc::pthread_mutex_t {
@@ -16,6 +17,14 @@ pub unsafe fn raw(m: &Mutex) -> *mut libc::pthread_mutex_t {
1617
unsafe impl Send for Mutex {}
1718
unsafe impl Sync for Mutex {}
1819

20+
impl LazyInit for Mutex {
21+
fn init() -> Box<Self> {
22+
let mut mutex = Box::new(Self::new());
23+
unsafe { mutex.init() };
24+
mutex
25+
}
26+
}
27+
1928
impl Mutex {
2029
pub const fn new() -> Mutex {
2130
// Might be moved to a different address, so it is better to avoid
@@ -73,13 +82,13 @@ impl Mutex {
7382
}
7483
#[inline]
7584
#[cfg(not(target_os = "dragonfly"))]
76-
pub unsafe fn destroy(&self) {
85+
unsafe fn destroy(&mut self) {
7786
let r = libc::pthread_mutex_destroy(self.inner.get());
7887
debug_assert_eq!(r, 0);
7988
}
8089
#[inline]
8190
#[cfg(target_os = "dragonfly")]
82-
pub unsafe fn destroy(&self) {
91+
unsafe fn destroy(&mut self) {
8392
let r = libc::pthread_mutex_destroy(self.inner.get());
8493
// On DragonFly pthread_mutex_destroy() returns EINVAL if called on a
8594
// mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER.
@@ -89,6 +98,13 @@ impl Mutex {
8998
}
9099
}
91100

101+
impl Drop for Mutex {
102+
#[inline]
103+
fn drop(&mut self) {
104+
unsafe { self.destroy() };
105+
}
106+
}
107+
92108
pub(super) struct PthreadMutexAttr<'a>(pub &'a mut MaybeUninit<libc::pthread_mutexattr_t>);
93109

94110
impl Drop for PthreadMutexAttr<'_> {

0 commit comments

Comments
 (0)