Skip to content

Commit 8f8fabb

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 f8673e0 + e0d5bc1 commit 8f8fabb

Some content is hidden

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

63 files changed

+561
-4023
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/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"]
@@ -73,6 +73,9 @@ wasm-bindgen-threads = []
7373
std_detect_file_io = []
7474
std_detect_dlsym_getauxval = []
7575

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

src/libstd/io/lazy.rs

+3-5
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,7 +16,7 @@ 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
}

src/libstd/io/stdio.rs

+28-6
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};
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! {
@@ -256,7 +257,7 @@ impl Stdin {
256257
/// ```
257258
#[stable(feature = "rust1", since = "1.0.0")]
258259
pub fn lock(&self) -> StdinLock<'_> {
259-
StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
260+
StdinLock { inner: self.inner.lock() }
260261
}
261262

262263
/// Locks this handle and reads a line of input into the specified buffer.
@@ -467,7 +468,7 @@ impl Stdout {
467468
/// ```
468469
#[stable(feature = "rust1", since = "1.0.0")]
469470
pub fn lock(&self) -> StdoutLock<'_> {
470-
StdoutLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
471+
StdoutLock { inner: self.inner.lock() }
471472
}
472473
}
473474

@@ -493,6 +494,12 @@ impl Write for Stdout {
493494
self.lock().write_fmt(args)
494495
}
495496
}
497+
498+
#[stable(feature = "rust1", since = "1.0.0")]
499+
impl UnwindSafe for Stdout {}
500+
#[stable(feature = "rust1", since = "1.0.0")]
501+
impl RefUnwindSafe for Stdout {}
502+
496503
#[stable(feature = "rust1", since = "1.0.0")]
497504
impl Write for StdoutLock<'_> {
498505
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
@@ -510,6 +517,11 @@ impl fmt::Debug for StdoutLock<'_> {
510517
}
511518
}
512519

520+
#[stable(feature = "rust1", since = "1.0.0")]
521+
impl UnwindSafe for StdoutLock<'_> {}
522+
#[stable(feature = "rust1", since = "1.0.0")]
523+
impl RefUnwindSafe for StdoutLock<'_> {}
524+
513525
/// A handle to the standard error stream of a process.
514526
///
515527
/// For more information, see the [`io::stderr`] method.
@@ -620,7 +632,7 @@ impl Stderr {
620632
/// ```
621633
#[stable(feature = "rust1", since = "1.0.0")]
622634
pub fn lock(&self) -> StderrLock<'_> {
623-
StderrLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
635+
StderrLock { inner: self.inner.lock() }
624636
}
625637
}
626638

@@ -646,6 +658,12 @@ impl Write for Stderr {
646658
self.lock().write_fmt(args)
647659
}
648660
}
661+
662+
#[stable(feature = "rust1", since = "1.0.0")]
663+
impl UnwindSafe for Stderr {}
664+
#[stable(feature = "rust1", since = "1.0.0")]
665+
impl RefUnwindSafe for Stderr {}
666+
649667
#[stable(feature = "rust1", since = "1.0.0")]
650668
impl Write for StderrLock<'_> {
651669
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
@@ -663,6 +681,11 @@ impl fmt::Debug for StderrLock<'_> {
663681
}
664682
}
665683

684+
#[stable(feature = "rust1", since = "1.0.0")]
685+
impl UnwindSafe for StderrLock<'_> {}
686+
#[stable(feature = "rust1", since = "1.0.0")]
687+
impl RefUnwindSafe for StderrLock<'_> {}
688+
666689
/// Resets the thread-local stderr handle to the specified writer
667690
///
668691
/// This will replace the current thread's stderr handle, returning the old
@@ -767,7 +790,6 @@ pub use realstd::io::{_eprint, _print};
767790

768791
#[cfg(test)]
769792
mod tests {
770-
use crate::panic::{UnwindSafe, RefUnwindSafe};
771793
use crate::thread;
772794
use super::*;
773795

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)