diff options
| author | joboet <jonasboettiger@icloud.com> | 2024-02-15 17:40:33 +0100 |
|---|---|---|
| committer | joboet <jonasboettiger@icloud.com> | 2024-02-16 12:10:49 +0100 |
| commit | 491d1a76646123e1d68e32ab4e52ddbe6065d82a (patch) | |
| tree | 406b8d1d622d9029fa8c6709eefbd68e62c60b3e | |
| parent | 5e343e76e85c7e11afdcf9d76f0b355bbb38153d (diff) | |
| download | rust-491d1a76646123e1d68e32ab4e52ddbe6065d82a.tar.gz rust-491d1a76646123e1d68e32ab4e52ddbe6065d82a.zip | |
std: move locks to `sys` on UNIX and other futex platforms
15 files changed, 55 insertions, 218 deletions
diff --git a/library/std/src/sys/pal/unix/locks/futex_condvar.rs b/library/std/src/sys/locks/condvar/futex.rs index 4bd65dd25c2..3ad93ce07f7 100644 --- a/library/std/src/sys/pal/unix/locks/futex_condvar.rs +++ b/library/std/src/sys/locks/condvar/futex.rs @@ -1,6 +1,6 @@ -use super::Mutex; use crate::sync::atomic::{AtomicU32, Ordering::Relaxed}; use crate::sys::futex::{futex_wait, futex_wake, futex_wake_all}; +use crate::sys::locks::Mutex; use crate::time::Duration; pub struct Condvar { diff --git a/library/std/src/sys/locks/condvar/mod.rs b/library/std/src/sys/locks/condvar/mod.rs index 74494cdf66d..8bae14b5765 100644 --- a/library/std/src/sys/locks/condvar/mod.rs +++ b/library/std/src/sys/locks/condvar/mod.rs @@ -1,5 +1,20 @@ cfg_if::cfg_if! { - if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { + if #[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "freebsd", + target_os = "openbsd", + target_os = "dragonfly", + target_os = "fuchsia", + all(target_family = "wasm", target_feature = "atomics"), + target_os = "hermit", + ))] { + mod futex; + pub use futex::Condvar; + } else if #[cfg(target_family = "unix")] { + mod pthread; + pub use pthread::Condvar; + } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { mod sgx; pub use sgx::Condvar; } else if #[cfg(target_os = "solid_asp3")] { diff --git a/library/std/src/sys/pal/unix/locks/pthread_condvar.rs b/library/std/src/sys/locks/condvar/pthread.rs index 2dc1b0c601e..094738d5a3f 100644 --- a/library/std/src/sys/pal/unix/locks/pthread_condvar.rs +++ b/library/std/src/sys/locks/condvar/pthread.rs @@ -1,7 +1,7 @@ use crate::cell::UnsafeCell; use crate::ptr; use crate::sync::atomic::{AtomicPtr, Ordering::Relaxed}; -use crate::sys::locks::{pthread_mutex, Mutex}; +use crate::sys::locks::{mutex, Mutex}; #[cfg(not(target_os = "nto"))] use crate::sys::time::TIMESPEC_MAX; #[cfg(target_os = "nto")] @@ -112,7 +112,7 @@ impl Condvar { #[inline] pub unsafe fn wait(&self, mutex: &Mutex) { - let mutex = pthread_mutex::raw(mutex); + let mutex = mutex::raw(mutex); self.verify(mutex); let r = libc::pthread_cond_wait(raw(self), mutex); debug_assert_eq!(r, 0); @@ -134,7 +134,7 @@ impl Condvar { pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { use crate::sys::time::Timespec; - let mutex = pthread_mutex::raw(mutex); + let mutex = mutex::raw(mutex); self.verify(mutex); #[cfg(not(target_os = "nto"))] @@ -170,7 +170,7 @@ impl Condvar { use crate::sys::time::SystemTime; use crate::time::Instant; - let mutex = pthread_mutex::raw(mutex); + let mutex = mutex::raw(mutex); self.verify(mutex); // OSX implementation of `pthread_cond_timedwait` is buggy diff --git a/library/std/src/sys/pal/unix/locks/fuchsia_mutex.rs b/library/std/src/sys/locks/mutex/fuchsia.rs index 5d89e5a13fd..5d89e5a13fd 100644 --- a/library/std/src/sys/pal/unix/locks/fuchsia_mutex.rs +++ b/library/std/src/sys/locks/mutex/fuchsia.rs diff --git a/library/std/src/sys/pal/unix/locks/futex_mutex.rs b/library/std/src/sys/locks/mutex/futex.rs index c01229586c3..c01229586c3 100644 --- a/library/std/src/sys/pal/unix/locks/futex_mutex.rs +++ b/library/std/src/sys/locks/mutex/futex.rs diff --git a/library/std/src/sys/locks/mutex/mod.rs b/library/std/src/sys/locks/mutex/mod.rs index b94608c849f..170eb6be98c 100644 --- a/library/std/src/sys/locks/mutex/mod.rs +++ b/library/std/src/sys/locks/mutex/mod.rs @@ -1,5 +1,22 @@ cfg_if::cfg_if! { - if #[cfg(target_os = "teeos")] { + if #[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "freebsd", + target_os = "openbsd", + target_os = "dragonfly", + all(target_family = "wasm", target_feature = "atomics"), + target_os = "hermit", + ))] { + mod futex; + pub use futex::Mutex; + } else if #[cfg(target_os = "fuchsia")] { + mod fuchsia; + pub use fuchsia::Mutex; + } else if #[cfg(any( + target_family = "unix", + target_os = "teeos", + ))] { mod pthread; pub use pthread::{Mutex, raw}; } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { diff --git a/library/std/src/sys/pal/unix/locks/futex_rwlock.rs b/library/std/src/sys/locks/rwlock/futex.rs index aa0de900238..aa0de900238 100644 --- a/library/std/src/sys/pal/unix/locks/futex_rwlock.rs +++ b/library/std/src/sys/locks/rwlock/futex.rs diff --git a/library/std/src/sys/locks/rwlock/mod.rs b/library/std/src/sys/locks/rwlock/mod.rs index 7de4a9d50a8..96a086fc64b 100644 --- a/library/std/src/sys/locks/rwlock/mod.rs +++ b/library/std/src/sys/locks/rwlock/mod.rs @@ -1,5 +1,20 @@ cfg_if::cfg_if! { - if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { + if #[cfg(any( + target_os = "linux", + target_os = "android", + target_os = "freebsd", + target_os = "openbsd", + target_os = "dragonfly", + target_os = "fuchsia", + all(target_family = "wasm", target_feature = "atomics"), + target_os = "hermit", + ))] { + mod futex; + pub use futex::RwLock; + } else if #[cfg(target_family = "unix")] { + mod queue; + pub use queue::RwLock; + } else if #[cfg(all(target_vendor = "fortanix", target_env = "sgx"))] { mod sgx; pub use sgx::RwLock; } else if #[cfg(target_os = "solid_asp3")] { diff --git a/library/std/src/sys/pal/unix/locks/queue_rwlock.rs b/library/std/src/sys/locks/rwlock/queue.rs index 0f02a98dfdd..0f02a98dfdd 100644 --- a/library/std/src/sys/pal/unix/locks/queue_rwlock.rs +++ b/library/std/src/sys/locks/rwlock/queue.rs diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 57cc656e266..ada408107dc 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -39,16 +39,6 @@ pub mod thread_local_dtor; pub mod thread_local_key; pub mod time; -#[path = "../unix/locks"] -pub mod locks { - mod futex_condvar; - mod futex_mutex; - mod futex_rwlock; - pub(crate) use futex_condvar::Condvar; - pub(crate) use futex_mutex::Mutex; - pub(crate) use futex_rwlock::RwLock; -} - use crate::io::ErrorKind; use crate::os::hermit::abi; diff --git a/library/std/src/sys/pal/unix/locks/mod.rs b/library/std/src/sys/pal/unix/locks/mod.rs deleted file mode 100644 index a49247310b5..00000000000 --- a/library/std/src/sys/pal/unix/locks/mod.rs +++ /dev/null @@ -1,31 +0,0 @@ -cfg_if::cfg_if! { - if #[cfg(any( - target_os = "linux", - target_os = "android", - all(target_os = "emscripten", target_feature = "atomics"), - target_os = "freebsd", - target_os = "openbsd", - target_os = "dragonfly", - ))] { - mod futex_mutex; - mod futex_rwlock; - mod futex_condvar; - pub(crate) use futex_mutex::Mutex; - pub(crate) use futex_rwlock::RwLock; - pub(crate) use futex_condvar::Condvar; - } else if #[cfg(target_os = "fuchsia")] { - mod fuchsia_mutex; - mod futex_rwlock; - mod futex_condvar; - pub(crate) use fuchsia_mutex::Mutex; - pub(crate) use futex_rwlock::RwLock; - pub(crate) use futex_condvar::Condvar; - } else { - mod pthread_mutex; - mod pthread_condvar; - mod queue_rwlock; - pub(crate) use pthread_mutex::Mutex; - pub(crate) use queue_rwlock::RwLock; - pub(crate) use pthread_condvar::Condvar; - } -} diff --git a/library/std/src/sys/pal/unix/locks/pthread_mutex.rs b/library/std/src/sys/pal/unix/locks/pthread_mutex.rs deleted file mode 100644 index ee0794334fb..00000000000 --- a/library/std/src/sys/pal/unix/locks/pthread_mutex.rs +++ /dev/null @@ -1,148 +0,0 @@ -use crate::cell::UnsafeCell; -use crate::io::Error; -use crate::mem::{forget, MaybeUninit}; -use crate::sys::cvt_nz; -use crate::sys_common::lazy_box::{LazyBox, LazyInit}; - -struct AllocatedMutex(UnsafeCell<libc::pthread_mutex_t>); - -pub struct Mutex { - inner: LazyBox<AllocatedMutex>, -} - -#[inline] -pub unsafe fn raw(m: &Mutex) -> *mut libc::pthread_mutex_t { - m.inner.0.get() -} - -unsafe impl Send for AllocatedMutex {} -unsafe impl Sync for AllocatedMutex {} - -impl LazyInit for AllocatedMutex { - fn init() -> Box<Self> { - let mutex = Box::new(AllocatedMutex(UnsafeCell::new(libc::PTHREAD_MUTEX_INITIALIZER))); - - // Issue #33770 - // - // A pthread mutex initialized with PTHREAD_MUTEX_INITIALIZER will have - // a type of PTHREAD_MUTEX_DEFAULT, which has undefined behavior if you - // try to re-lock it from the same thread when you already hold a lock - // (https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_init.html). - // This is the case even if PTHREAD_MUTEX_DEFAULT == PTHREAD_MUTEX_NORMAL - // (https://github.com/rust-lang/rust/issues/33770#issuecomment-220847521) -- in that - // case, `pthread_mutexattr_settype(PTHREAD_MUTEX_DEFAULT)` will of course be the same - // as setting it to `PTHREAD_MUTEX_NORMAL`, but not setting any mode will result in - // a Mutex where re-locking is UB. - // - // In practice, glibc takes advantage of this undefined behavior to - // implement hardware lock elision, which uses hardware transactional - // memory to avoid acquiring the lock. While a transaction is in - // progress, the lock appears to be unlocked. This isn't a problem for - // other threads since the transactional memory will abort if a conflict - // is detected, however no abort is generated when re-locking from the - // same thread. - // - // Since locking the same mutex twice will result in two aliasing &mut - // references, we instead create the mutex with type - // PTHREAD_MUTEX_NORMAL which is guaranteed to deadlock if we try to - // re-lock it from the same thread, thus avoiding undefined behavior. - unsafe { - let mut attr = MaybeUninit::<libc::pthread_mutexattr_t>::uninit(); - cvt_nz(libc::pthread_mutexattr_init(attr.as_mut_ptr())).unwrap(); - let attr = PthreadMutexAttr(&mut attr); - cvt_nz(libc::pthread_mutexattr_settype( - attr.0.as_mut_ptr(), - libc::PTHREAD_MUTEX_NORMAL, - )) - .unwrap(); - cvt_nz(libc::pthread_mutex_init(mutex.0.get(), attr.0.as_ptr())).unwrap(); - } - - mutex - } - - fn destroy(mutex: Box<Self>) { - // We're not allowed to pthread_mutex_destroy a locked mutex, - // so check first if it's unlocked. - if unsafe { libc::pthread_mutex_trylock(mutex.0.get()) == 0 } { - unsafe { libc::pthread_mutex_unlock(mutex.0.get()) }; - drop(mutex); - } else { - // The mutex is locked. This happens if a MutexGuard is leaked. - // In this case, we just leak the Mutex too. - forget(mutex); - } - } - - fn cancel_init(_: Box<Self>) { - // In this case, we can just drop it without any checks, - // since it cannot have been locked yet. - } -} - -impl Drop for AllocatedMutex { - #[inline] - fn drop(&mut self) { - let r = unsafe { libc::pthread_mutex_destroy(self.0.get()) }; - if cfg!(target_os = "dragonfly") { - // On DragonFly pthread_mutex_destroy() returns EINVAL if called on a - // mutex that was just initialized with libc::PTHREAD_MUTEX_INITIALIZER. - // Once it is used (locked/unlocked) or pthread_mutex_init() is called, - // this behaviour no longer occurs. - debug_assert!(r == 0 || r == libc::EINVAL); - } else { - debug_assert_eq!(r, 0); - } - } -} - -impl Mutex { - #[inline] - pub const fn new() -> Mutex { - Mutex { inner: LazyBox::new() } - } - - #[inline] - pub unsafe fn lock(&self) { - #[cold] - #[inline(never)] - fn fail(r: i32) -> ! { - let error = Error::from_raw_os_error(r); - panic!("failed to lock mutex: {error}"); - } - - let r = libc::pthread_mutex_lock(raw(self)); - // As we set the mutex type to `PTHREAD_MUTEX_NORMAL` above, we expect - // the lock call to never fail. Unfortunately however, some platforms - // (Solaris) do not conform to the standard, and instead always provide - // deadlock detection. How kind of them! Unfortunately that means that - // we need to check the error code here. To save us from UB on other - // less well-behaved platforms in the future, we do it even on "good" - // platforms like macOS. See #120147 for more context. - if r != 0 { - fail(r) - } - } - - #[inline] - pub unsafe fn unlock(&self) { - let r = libc::pthread_mutex_unlock(raw(self)); - debug_assert_eq!(r, 0); - } - - #[inline] - pub unsafe fn try_lock(&self) -> bool { - libc::pthread_mutex_trylock(raw(self)) == 0 - } -} - -pub(super) struct PthreadMutexAttr<'a>(pub &'a mut MaybeUninit<libc::pthread_mutexattr_t>); - -impl Drop for PthreadMutexAttr<'_> { - fn drop(&mut self) { - unsafe { - let result = libc::pthread_mutexattr_destroy(self.0.as_mut_ptr()); - debug_assert_eq!(result, 0); - } - } -} diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index 976a437c17f..04b8c5ca916 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -20,7 +20,6 @@ pub mod io; pub mod kernel_copy; #[cfg(target_os = "l4re")] mod l4re; -pub mod locks; pub mod memchr; #[cfg(not(target_os = "l4re"))] pub mod net; diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs index 116878ee996..5de2e0e7d63 100644 --- a/library/std/src/sys/pal/wasi/mod.rs +++ b/library/std/src/sys/pal/wasi/mod.rs @@ -44,16 +44,6 @@ pub mod time; cfg_if::cfg_if! { if #[cfg(target_feature = "atomics")] { - #[path = "../unix/locks"] - pub mod locks { - #![allow(unsafe_op_in_unsafe_fn)] - mod futex_condvar; - mod futex_mutex; - mod futex_rwlock; - pub(crate) use futex_condvar::Condvar; - pub(crate) use futex_mutex::Mutex; - pub(crate) use futex_rwlock::RwLock; - } } else { #[path = "../unsupported/locks/mod.rs"] pub mod locks; diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs index 567555118d7..910a54b2e01 100644 --- a/library/std/src/sys/pal/wasm/mod.rs +++ b/library/std/src/sys/pal/wasm/mod.rs @@ -43,16 +43,6 @@ pub mod time; cfg_if::cfg_if! { if #[cfg(target_feature = "atomics")] { - #[path = "../unix/locks"] - pub mod locks { - #![allow(unsafe_op_in_unsafe_fn)] - mod futex_condvar; - mod futex_mutex; - mod futex_rwlock; - pub(crate) use futex_condvar::Condvar; - pub(crate) use futex_mutex::Mutex; - pub(crate) use futex_rwlock::RwLock; - } #[path = "atomics/futex.rs"] pub mod futex; #[path = "atomics/thread.rs"] |
