Skip to content

Commit 2d92fc2

Browse files
committed
Auto merge of #56410 - faern:add-parking-lot, r=<try>
Use the parking_lot locking primitives This PR adds the [`parking_lot`](https://crates.io/crates/parking_lot) code to libstd and uses it for the `sys_common::{mutex,rwlock,condvar,remutex}` implementations. This has been discussed in https://internals.rust-lang.org/t/standard-library-synchronization-primitives-and-undefined-behavior/8439/9 Thanks @Amanieu for mentoring when doing this, and basically all the code is his as well of course. Fixes #35836 Fixes #53127
2 parents 22fa4bb + f40a4ec commit 2d92fc2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+500
-4180
lines changed

.gitmodules

+4
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,7 @@
4747
[submodule "src/doc/embedded-book"]
4848
path = src/doc/embedded-book
4949
url = https://github.com/rust-embedded/book.git
50+
[submodule "src/parking_lot"]
51+
path = src/parking_lot
52+
url = https://github.com/faern/parking_lot
53+

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ exclude = [
2828
"build",
2929
# HACK(eddyb) This hardcodes the fact that our CI uses `/checkout/obj`.
3030
"obj",
31+
"src/parking_lot/benchmark",
3132
]
3233

3334
# Curiously, LLVM 7.0 will segfault if compiled with opt-level=3

src/ci/docker/dist-various-2/Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc
3232
COPY dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/
3333
# We pass the commit id of the port of LLVM's libunwind to the build script.
3434
# Any update to the commit id here, should cause the container image to be re-built from this point on.
35-
RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh "53b586346f2c7870e20b170decdc30729d97c42b"
35+
RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh "a50a70f1394b2e62d6a5d2510330eb110e31dad4"
3636

3737
COPY dist-various-2/build-wasi-toolchain.sh /tmp/
3838
RUN /tmp/build-wasi-toolchain.sh

src/libstd/Cargo.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }
4848
cc = "1.0"
4949

5050
[features]
51-
default = ["compiler_builtins_c", "std_detect_file_io", "std_detect_dlsym_getauxval"]
51+
default = ["compiler_builtins_c", "std_detect_file_io", "std_detect_dlsym_getauxval", "i-am-libstd"]
5252

5353
backtrace = ["backtrace-sys"]
5454
panic-unwind = ["panic_unwind"]
@@ -74,6 +74,9 @@ wasm-bindgen-threads = []
7474
std_detect_file_io = []
7575
std_detect_dlsym_getauxval = []
7676

77+
# Feature used by parking_lot
78+
i-am-libstd = []
79+
7780
[package.metadata.fortanix-sgx]
7881
# Maximum possible number of threads when testing
7982
threads = 125

src/libstd/io/lazy.rs

+8-10
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
use crate::cell::Cell;
22
use crate::ptr;
3-
use crate::sync::Arc;
3+
use crate::sync::{Arc, RawMutex};
44
use crate::sys_common;
5-
use crate::sys_common::mutex::Mutex;
65

76
pub struct Lazy<T> {
8-
// We never call `lock.init()`, so it is UB to attempt to acquire this mutex reentrantly!
9-
lock: Mutex,
7+
lock: RawMutex,
108
ptr: Cell<*mut Arc<T>>,
119
}
1210

@@ -18,24 +16,24 @@ unsafe impl<T> Sync for Lazy<T> {}
1816
impl<T> Lazy<T> {
1917
pub const fn new() -> Lazy<T> {
2018
Lazy {
21-
lock: Mutex::new(),
19+
lock: RawMutex::new(),
2220
ptr: Cell::new(ptr::null_mut()),
2321
}
2422
}
2523
}
2624

2725
impl<T: Send + Sync + 'static> Lazy<T> {
28-
/// Safety: `init` must not call `get` on the variable that is being
29-
/// initialized.
30-
pub unsafe fn get(&'static self, init: fn() -> Arc<T>) -> Option<Arc<T>> {
26+
/// Warning: `init` must not call `get` on the variable that is being
27+
/// initialized. Doing so will cause a deadlock.
28+
pub fn get(&'static self, init: fn() -> Arc<T>) -> Option<Arc<T>> {
3129
let _guard = self.lock.lock();
3230
let ptr = self.ptr.get();
3331
if ptr.is_null() {
34-
Some(self.init(init))
32+
Some(unsafe { self.init(init) })
3533
} else if ptr == done() {
3634
None
3735
} else {
38-
Some((*ptr).clone())
36+
Some(unsafe { (*ptr).clone() })
3937
}
4038
}
4139

src/libstd/io/stdio.rs

+31-15
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ use crate::cell::RefCell;
66
use crate::fmt;
77
use crate::io::lazy::Lazy;
88
use crate::io::{self, Initializer, BufReader, LineWriter, IoVec, IoVecMut};
9-
use crate::sync::{Arc, Mutex, MutexGuard};
9+
use crate::sync::Arc;
1010
use crate::sys::stdio;
11-
use crate::sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
11+
use crate::panic::{UnwindSafe, RefUnwindSafe};
12+
use crate::parking_lot::{Mutex, MutexGuard, ReentrantMutex, ReentrantMutexGuard};
1213
use crate::thread::LocalKey;
1314

1415
thread_local! {
@@ -242,9 +243,7 @@ pub struct StdinLock<'a> {
242243
pub fn stdin() -> Stdin {
243244
static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new();
244245
return Stdin {
245-
inner: unsafe {
246-
INSTANCE.get(stdin_init).expect("cannot access stdin during shutdown")
247-
},
246+
inner: INSTANCE.get(stdin_init).expect("cannot access stdin during shutdown"),
248247
};
249248

250249
fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> {
@@ -285,7 +284,7 @@ impl Stdin {
285284
/// ```
286285
#[stable(feature = "rust1", since = "1.0.0")]
287286
pub fn lock(&self) -> StdinLock<'_> {
288-
StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
287+
StdinLock { inner: self.inner.lock() }
289288
}
290289

291290
/// Locks this handle and reads a line of input into the specified buffer.
@@ -466,9 +465,7 @@ pub struct StdoutLock<'a> {
466465
pub fn stdout() -> Stdout {
467466
static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> = Lazy::new();
468467
return Stdout {
469-
inner: unsafe {
470-
INSTANCE.get(stdout_init).expect("cannot access stdout during shutdown")
471-
},
468+
inner: INSTANCE.get(stdout_init).expect("cannot access stdout during shutdown"),
472469
};
473470

474471
fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> {
@@ -504,7 +501,7 @@ impl Stdout {
504501
/// ```
505502
#[stable(feature = "rust1", since = "1.0.0")]
506503
pub fn lock(&self) -> StdoutLock<'_> {
507-
StdoutLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
504+
StdoutLock { inner: self.inner.lock() }
508505
}
509506
}
510507

@@ -533,6 +530,12 @@ impl Write for Stdout {
533530
self.lock().write_fmt(args)
534531
}
535532
}
533+
534+
#[stable(feature = "rust1", since = "1.0.0")]
535+
impl UnwindSafe for Stdout {}
536+
#[stable(feature = "rust1", since = "1.0.0")]
537+
impl RefUnwindSafe for Stdout {}
538+
536539
#[stable(feature = "rust1", since = "1.0.0")]
537540
impl Write for StdoutLock<'_> {
538541
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
@@ -553,6 +556,11 @@ impl fmt::Debug for StdoutLock<'_> {
553556
}
554557
}
555558

559+
#[stable(feature = "rust1", since = "1.0.0")]
560+
impl UnwindSafe for StdoutLock<'_> {}
561+
#[stable(feature = "rust1", since = "1.0.0")]
562+
impl RefUnwindSafe for StdoutLock<'_> {}
563+
556564
/// A handle to the standard error stream of a process.
557565
///
558566
/// For more information, see the [`io::stderr`] method.
@@ -625,9 +633,7 @@ pub struct StderrLock<'a> {
625633
pub fn stderr() -> Stderr {
626634
static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = Lazy::new();
627635
return Stderr {
628-
inner: unsafe {
629-
INSTANCE.get(stderr_init).expect("cannot access stderr during shutdown")
630-
},
636+
inner: INSTANCE.get(stderr_init).expect("cannot access stderr during shutdown"),
631637
};
632638

633639
fn stderr_init() -> Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> {
@@ -663,7 +669,7 @@ impl Stderr {
663669
/// ```
664670
#[stable(feature = "rust1", since = "1.0.0")]
665671
pub fn lock(&self) -> StderrLock<'_> {
666-
StderrLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
672+
StderrLock { inner: self.inner.lock() }
667673
}
668674
}
669675

@@ -692,6 +698,12 @@ impl Write for Stderr {
692698
self.lock().write_fmt(args)
693699
}
694700
}
701+
702+
#[stable(feature = "rust1", since = "1.0.0")]
703+
impl UnwindSafe for Stderr {}
704+
#[stable(feature = "rust1", since = "1.0.0")]
705+
impl RefUnwindSafe for Stderr {}
706+
695707
#[stable(feature = "rust1", since = "1.0.0")]
696708
impl Write for StderrLock<'_> {
697709
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
@@ -712,6 +724,11 @@ impl fmt::Debug for StderrLock<'_> {
712724
}
713725
}
714726

727+
#[stable(feature = "rust1", since = "1.0.0")]
728+
impl UnwindSafe for StderrLock<'_> {}
729+
#[stable(feature = "rust1", since = "1.0.0")]
730+
impl RefUnwindSafe for StderrLock<'_> {}
731+
715732
/// Resets the thread-local stderr handle to the specified writer
716733
///
717734
/// This will replace the current thread's stderr handle, returning the old
@@ -816,7 +833,6 @@ pub use realstd::io::{_eprint, _print};
816833

817834
#[cfg(test)]
818835
mod tests {
819-
use crate::panic::{UnwindSafe, RefUnwindSafe};
820836
use crate::thread;
821837
use super::*;
822838

src/libstd/lib.rs

+12
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,18 @@ pub mod rt;
499499
#[cfg(not(test))]
500500
mod std_detect;
501501

502+
#[path = "../parking_lot/core/src/lib.rs"]
503+
mod parking_lot_core;
504+
505+
#[path = "../parking_lot/lock_api/src/lib.rs"]
506+
#[allow(dead_code)]
507+
mod lock_api;
508+
509+
#[path = "../parking_lot/src/lib.rs"]
510+
#[allow(dead_code)]
511+
mod parking_lot;
512+
513+
502514
#[doc(hidden)]
503515
#[unstable(feature = "stdsimd", issue = "48556")]
504516
#[cfg(not(test))]

src/libstd/panicking.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ use core::panic::{BoxMeUp, PanicInfo, Location};
1212
use crate::any::Any;
1313
use crate::fmt;
1414
use crate::intrinsics;
15+
use crate::lock_api::RawRwLock as _;
1516
use crate::mem;
17+
use crate::parking_lot::RawRwLock;
1618
use crate::ptr;
1719
use crate::raw;
1820
use crate::sys::stdio::panic_output;
19-
use crate::sys_common::rwlock::RWLock;
2021
use crate::sys_common::thread_info;
2122
use crate::sys_common::util;
2223
use crate::thread;
@@ -54,7 +55,7 @@ enum Hook {
5455
Custom(*mut (dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send)),
5556
}
5657

57-
static HOOK_LOCK: RWLock = RWLock::new();
58+
static HOOK_LOCK: RawRwLock = RawRwLock::INIT;
5859
static mut HOOK: Hook = Hook::Default;
5960

6061
/// Registers a custom panic hook, replacing any that was previously registered.
@@ -97,10 +98,10 @@ pub fn set_hook(hook: Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send>) {
9798
}
9899

99100
unsafe {
100-
HOOK_LOCK.write();
101+
HOOK_LOCK.lock_exclusive();
101102
let old_hook = HOOK;
102103
HOOK = Hook::Custom(Box::into_raw(hook));
103-
HOOK_LOCK.write_unlock();
104+
HOOK_LOCK.unlock_exclusive();
104105

105106
if let Hook::Custom(ptr) = old_hook {
106107
Box::from_raw(ptr);
@@ -142,10 +143,10 @@ pub fn take_hook() -> Box<dyn Fn(&PanicInfo<'_>) + 'static + Sync + Send> {
142143
}
143144

144145
unsafe {
145-
HOOK_LOCK.write();
146+
HOOK_LOCK.lock_exclusive();
146147
let hook = HOOK;
147148
HOOK = Hook::Default;
148-
HOOK_LOCK.write_unlock();
149+
HOOK_LOCK.unlock_exclusive();
149150

150151
match hook {
151152
Hook::Default => Box::new(default_hook),
@@ -463,7 +464,7 @@ fn rust_panic_with_hook(payload: &mut dyn BoxMeUp,
463464
message,
464465
Location::internal_constructor(file, line, col),
465466
);
466-
HOOK_LOCK.read();
467+
HOOK_LOCK.lock_shared();
467468
match HOOK {
468469
// Some platforms know that printing to stderr won't ever actually
469470
// print anything, and if that's the case we can skip the default
@@ -478,7 +479,7 @@ fn rust_panic_with_hook(payload: &mut dyn BoxMeUp,
478479
(*ptr)(&info);
479480
}
480481
};
481-
HOOK_LOCK.read_unlock();
482+
HOOK_LOCK.unlock_shared();
482483
}
483484

484485
if panics > 1 {

0 commit comments

Comments
 (0)