Skip to content

Lazily allocate and initialize pthread locks. #97647

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 4, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions library/std/src/sys/hermit/condvar.rs
Original file line number Diff line number Diff line change
@@ -70,9 +70,13 @@ impl Condvar {
mutex.lock();
res == 0
}
}

pub unsafe fn destroy(&self) {
let _ = abi::sem_destroy(self.sem1);
let _ = abi::sem_destroy(self.sem2);
impl Drop for Condvar {
fn drop(&mut self) {
unsafe {
let _ = abi::sem_destroy(self.sem1);
let _ = abi::sem_destroy(self.sem2);
}
}
}
3 changes: 0 additions & 3 deletions library/std/src/sys/hermit/mutex.rs
Original file line number Diff line number Diff line change
@@ -215,7 +215,4 @@ impl Mutex {
}
guard.locked
}

#[inline]
pub unsafe fn destroy(&self) {}
}
6 changes: 0 additions & 6 deletions library/std/src/sys/hermit/rwlock.rs
Original file line number Diff line number Diff line change
@@ -84,12 +84,6 @@ impl RwLock {
// FIXME: should only wake up one of these some of the time
self.cond.notify_all();
}

#[inline]
pub unsafe fn destroy(&self) {
self.lock.destroy();
self.cond.destroy();
}
}

impl State {
2 changes: 0 additions & 2 deletions library/std/src/sys/itron/condvar.rs
Original file line number Diff line number Diff line change
@@ -117,8 +117,6 @@ impl Condvar {
unsafe { mutex.lock() };
success
}

pub unsafe fn destroy(&self) {}
}

mod waiter_queue {
4 changes: 3 additions & 1 deletion library/std/src/sys/itron/mutex.rs
Original file line number Diff line number Diff line change
@@ -64,8 +64,10 @@ impl Mutex {
}
}
}
}

pub unsafe fn destroy(&self) {
impl Drop for Mutex {
fn drop(&mut self) {
if let Some(mtx) = self.mtx.get().map(|x| x.0) {
expect_success_aborting(unsafe { abi::del_mtx(mtx) }, &"del_mtx");
}
15 changes: 8 additions & 7 deletions library/std/src/sys/sgx/condvar.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::sys::locks::Mutex;
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
use crate::time::Duration;

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

pub type MovableCondvar = Box<Condvar>;
pub(crate) type MovableCondvar = LazyBox<Condvar>;

impl LazyInit for Condvar {
fn init() -> Box<Self> {
Box::new(Self::new())
}
}

impl Condvar {
pub const fn new() -> Condvar {
Condvar { inner: SpinMutex::new(WaitVariable::new(())) }
}

#[inline]
pub unsafe fn init(&mut self) {}

#[inline]
pub unsafe fn notify_one(&self) {
let _ = WaitQueue::notify_one(self.inner.lock());
@@ -38,7 +42,4 @@ impl Condvar {
unsafe { mutex.lock() };
success
}

#[inline]
pub unsafe fn destroy(&self) {}
}
12 changes: 8 additions & 4 deletions library/std/src/sys/sgx/mutex.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
use super::waitqueue::{try_lock_or_false, SpinMutex, WaitQueue, WaitVariable};
use crate::sys_common::lazy_box::{LazyBox, LazyInit};

pub struct Mutex {
inner: SpinMutex<WaitVariable<bool>>,
}

// not movable: see UnsafeList implementation
pub type MovableMutex = Box<Mutex>;
pub(crate) type MovableMutex = LazyBox<Mutex>;

impl LazyInit for Mutex {
fn init() -> Box<Self> {
Box::new(Self::new())
}
}

// Implementation according to “Operating Systems: Three Easy Pieces”, chapter 28
impl Mutex {
@@ -52,7 +59,4 @@ impl Mutex {
true
}
}

#[inline]
pub unsafe fn destroy(&self) {}
}
12 changes: 8 additions & 4 deletions library/std/src/sys/sgx/rwlock.rs
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
mod tests;

use crate::num::NonZeroUsize;
use crate::sys_common::lazy_box::{LazyBox, LazyInit};

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

pub type MovableRwLock = Box<RwLock>;
pub(crate) type MovableRwLock = LazyBox<RwLock>;

impl LazyInit for RwLock {
fn init() -> Box<Self> {
Box::new(Self::new())
}
}

// Check at compile time that RwLock size matches C definition (see test_c_rwlock_initializer below)
//
@@ -168,9 +175,6 @@ impl RwLock {
unsafe { self.__read_unlock(rguard, wguard) };
}
}

#[inline]
pub unsafe fn destroy(&self) {}
}

// The following functions are needed by libunwind. These symbols are named
4 changes: 3 additions & 1 deletion library/std/src/sys/solid/rwlock.rs
Original file line number Diff line number Diff line change
@@ -82,9 +82,11 @@ impl RwLock {
let rwl = self.raw();
expect_success_aborting(unsafe { abi::rwl_unl_rwl(rwl) }, &"rwl_unl_rwl");
}
}

impl Drop for RwLock {
#[inline]
pub unsafe fn destroy(&self) {
fn drop(&mut self) {
if let Some(rwl) = self.rwl.get().map(|x| x.0) {
expect_success_aborting(unsafe { abi::rwl_del_rwl(rwl) }, &"rwl_del_rwl");
}
9 changes: 0 additions & 9 deletions library/std/src/sys/unix/locks/futex.rs
Original file line number Diff line number Diff line change
@@ -24,9 +24,6 @@ impl Mutex {
#[inline]
pub unsafe fn init(&mut self) {}

#[inline]
pub unsafe fn destroy(&self) {}

#[inline]
pub unsafe fn try_lock(&self) -> bool {
self.futex.compare_exchange(0, 1, Acquire, Relaxed).is_ok()
@@ -118,12 +115,6 @@ impl Condvar {
Self { futex: AtomicU32::new(0) }
}

#[inline]
pub unsafe fn init(&mut self) {}

#[inline]
pub unsafe fn destroy(&self) {}

// All the memory orderings here are `Relaxed`,
// because synchronization is done by unlocking and locking the mutex.

3 changes: 0 additions & 3 deletions library/std/src/sys/unix/locks/futex_rwlock.rs
Original file line number Diff line number Diff line change
@@ -63,9 +63,6 @@ impl RwLock {
Self { state: AtomicU32::new(0), writer_notify: AtomicU32::new(0) }
}

#[inline]
pub unsafe fn destroy(&self) {}

#[inline]
pub unsafe fn try_read(&self) -> bool {
self.state
10 changes: 5 additions & 5 deletions library/std/src/sys/unix/locks/mod.rs
Original file line number Diff line number Diff line change
@@ -9,14 +9,14 @@ cfg_if::cfg_if! {
))] {
mod futex;
mod futex_rwlock;
pub use futex::{Mutex, MovableMutex, Condvar, MovableCondvar};
pub use futex_rwlock::{RwLock, MovableRwLock};
pub(crate) use futex::{Mutex, MovableMutex, MovableCondvar};
pub(crate) use futex_rwlock::{RwLock, MovableRwLock};
} else {
mod pthread_mutex;
mod pthread_rwlock;
mod pthread_condvar;
pub use pthread_mutex::{Mutex, MovableMutex};
pub use pthread_rwlock::{RwLock, MovableRwLock};
pub use pthread_condvar::{Condvar, MovableCondvar};
pub(crate) use pthread_mutex::{Mutex, MovableMutex};
pub(crate) use pthread_rwlock::{RwLock, MovableRwLock};
pub(crate) use pthread_condvar::MovableCondvar;
}
}
28 changes: 22 additions & 6 deletions library/std/src/sys/unix/locks/pthread_condvar.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crate::cell::UnsafeCell;
use crate::sys::locks::{pthread_mutex, Mutex};
use crate::sys_common::lazy_box::{LazyBox, LazyInit};
use crate::time::Duration;

pub struct Condvar {
inner: UnsafeCell<libc::pthread_cond_t>,
}

pub type MovableCondvar = Box<Condvar>;
pub(crate) type MovableCondvar = LazyBox<Condvar>;

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

impl LazyInit for Condvar {
fn init() -> Box<Self> {
let mut condvar = Box::new(Self::new());
unsafe { condvar.init() };
condvar
}
}

impl Condvar {
pub const fn new() -> Condvar {
// Might be moved and address is changing it is better to avoid
@@ -32,14 +41,14 @@ impl Condvar {
target_os = "android",
target_os = "redox"
))]
pub unsafe fn init(&mut self) {}
unsafe fn init(&mut self) {}

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

#[inline]
#[cfg(not(target_os = "dragonfly"))]
pub unsafe fn destroy(&self) {
unsafe fn destroy(&mut self) {
let r = libc::pthread_cond_destroy(self.inner.get());
debug_assert_eq!(r, 0);
}

#[inline]
#[cfg(target_os = "dragonfly")]
pub unsafe fn destroy(&self) {
unsafe fn destroy(&mut self) {
let r = libc::pthread_cond_destroy(self.inner.get());
// On DragonFly pthread_cond_destroy() returns EINVAL if called on
// a condvar that was just initialized with
@@ -195,3 +204,10 @@ impl Condvar {
debug_assert!(r == 0 || r == libc::EINVAL);
}
}

impl Drop for Condvar {
#[inline]
fn drop(&mut self) {
unsafe { self.destroy() };
}
}
22 changes: 19 additions & 3 deletions library/std/src/sys/unix/locks/pthread_mutex.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crate::cell::UnsafeCell;
use crate::mem::MaybeUninit;
use crate::sys::cvt_nz;
use crate::sys_common::lazy_box::{LazyBox, LazyInit};

pub struct Mutex {
inner: UnsafeCell<libc::pthread_mutex_t>,
}

pub type MovableMutex = Box<Mutex>;
pub(crate) type MovableMutex = LazyBox<Mutex>;

#[inline]
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 {
unsafe impl Send for Mutex {}
unsafe impl Sync for Mutex {}

impl LazyInit for Mutex {
fn init() -> Box<Self> {
let mut mutex = Box::new(Self::new());
unsafe { mutex.init() };
mutex
}
}

impl Mutex {
pub const fn new() -> Mutex {
// Might be moved to a different address, so it is better to avoid
@@ -73,13 +82,13 @@ impl Mutex {
}
#[inline]
#[cfg(not(target_os = "dragonfly"))]
pub unsafe fn destroy(&self) {
unsafe fn destroy(&mut self) {
let r = libc::pthread_mutex_destroy(self.inner.get());
debug_assert_eq!(r, 0);
}
#[inline]
#[cfg(target_os = "dragonfly")]
pub unsafe fn destroy(&self) {
unsafe fn destroy(&mut self) {
let r = libc::pthread_mutex_destroy(self.inner.get());
// On DragonFly pthread_mutex_destroy() returns EINVAL if called on a
// mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER.
@@ -89,6 +98,13 @@ impl Mutex {
}
}

impl Drop for Mutex {
#[inline]
fn drop(&mut self) {
unsafe { self.destroy() };
}
}

pub(super) struct PthreadMutexAttr<'a>(pub &'a mut MaybeUninit<libc::pthread_mutexattr_t>);

impl Drop for PthreadMutexAttr<'_> {
Loading