diff options
Diffstat (limited to 'library/std/src')
28 files changed, 312 insertions, 958 deletions
diff --git a/library/std/src/future.rs b/library/std/src/future.rs index 5ff74e55754..9d9c36e9afb 100644 --- a/library/std/src/future.rs +++ b/library/std/src/future.rs @@ -9,7 +9,7 @@ pub use core::future::Future; pub use core::future::{from_generator, get_context, ResumeTy}; #[doc(inline)] -#[stable(feature = "future_readiness_fns", since = "1.47.0")] +#[stable(feature = "future_readiness_fns", since = "1.48.0")] pub use core::future::{pending, ready, Pending, Ready}; #[doc(inline)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index b834361b750..5333d75ec1b 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -315,6 +315,7 @@ #![feature(try_reserve)] #![feature(unboxed_closures)] #![feature(unsafe_block_in_unsafe_fn)] +#![feature(unsafe_cell_raw_get)] #![feature(untagged_unions)] #![feature(unwind_attributes)] #![feature(vec_into_raw_parts)] diff --git a/library/std/src/path.rs b/library/std/src/path.rs index d71e89d0eee..b83c1e9628d 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -58,6 +58,7 @@ //! [`push`]: PathBuf::push #![stable(feature = "rust1", since = "1.0.0")] +#![deny(unsafe_op_in_unsafe_fn)] #[cfg(test)] mod tests; @@ -294,7 +295,8 @@ fn os_str_as_u8_slice(s: &OsStr) -> &[u8] { unsafe { &*(s as *const OsStr as *const [u8]) } } unsafe fn u8_slice_as_os_str(s: &[u8]) -> &OsStr { - &*(s as *const [u8] as *const OsStr) + // SAFETY: see the comment of `os_str_as_u8_slice` + unsafe { &*(s as *const [u8] as *const OsStr) } } // Detect scheme on Redox @@ -314,24 +316,21 @@ fn has_physical_root(s: &[u8], prefix: Option<Prefix<'_>>) -> bool { // basic workhorse for splitting stem and extension fn split_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) { - unsafe { - if os_str_as_u8_slice(file) == b".." { - return (Some(file), None); - } - - // The unsafety here stems from converting between &OsStr and &[u8] - // and back. This is safe to do because (1) we only look at ASCII - // contents of the encoding and (2) new &OsStr values are produced - // only from ASCII-bounded slices of existing &OsStr values. + if os_str_as_u8_slice(file) == b".." { + return (Some(file), None); + } - let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.'); - let after = iter.next(); - let before = iter.next(); - if before == Some(b"") { - (Some(file), None) - } else { - (before.map(|s| u8_slice_as_os_str(s)), after.map(|s| u8_slice_as_os_str(s))) - } + // The unsafety here stems from converting between &OsStr and &[u8] + // and back. This is safe to do because (1) we only look at ASCII + // contents of the encoding and (2) new &OsStr values are produced + // only from ASCII-bounded slices of existing &OsStr values. + let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.'); + let after = iter.next(); + let before = iter.next(); + if before == Some(b"") { + (Some(file), None) + } else { + unsafe { (before.map(|s| u8_slice_as_os_str(s)), after.map(|s| u8_slice_as_os_str(s))) } } } @@ -1702,7 +1701,7 @@ impl Path { // The following (private!) function allows construction of a path from a u8 // slice, which is only safe when it is known to follow the OsStr encoding. unsafe fn from_u8_slice(s: &[u8]) -> &Path { - Path::new(u8_slice_as_os_str(s)) + unsafe { Path::new(u8_slice_as_os_str(s)) } } // The following (private!) function reveals the byte encoding used for OsStr. fn as_u8_slice(&self) -> &[u8] { diff --git a/library/std/src/process.rs b/library/std/src/process.rs index d1960a049d9..00e2dbc9c1d 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -95,6 +95,7 @@ //! [`Read`]: io::Read #![stable(feature = "process", since = "1.0.0")] +#![deny(unsafe_op_in_unsafe_fn)] #[cfg(all(test, not(any(target_os = "cloudabi", target_os = "emscripten", target_env = "sgx"))))] mod tests; @@ -321,7 +322,8 @@ impl Read for ChildStdout { #[inline] unsafe fn initializer(&self) -> Initializer { - Initializer::nop() + // SAFETY: Read is guaranteed to work on uninitialized memory + unsafe { Initializer::nop() } } } @@ -381,7 +383,8 @@ impl Read for ChildStderr { #[inline] unsafe fn initializer(&self) -> Initializer { - Initializer::nop() + // SAFETY: Read is guaranteed to work on uninitialized memory + unsafe { Initializer::nop() } } } diff --git a/library/std/src/sys/sgx/fs.rs b/library/std/src/sys/sgx/fs.rs deleted file mode 100644 index ecb5b51cccd..00000000000 --- a/library/std/src/sys/sgx/fs.rs +++ /dev/null @@ -1,308 +0,0 @@ -use crate::ffi::OsString; -use crate::fmt; -use crate::hash::{Hash, Hasher}; -use crate::io::{self, IoSlice, IoSliceMut, SeekFrom}; -use crate::path::{Path, PathBuf}; -use crate::sys::time::SystemTime; -use crate::sys::{unsupported, Void}; - -pub struct File(Void); - -pub struct FileAttr(Void); - -pub struct ReadDir(Void); - -pub struct DirEntry(Void); - -#[derive(Clone, Debug)] -pub struct OpenOptions {} - -pub struct FilePermissions(Void); - -pub struct FileType(Void); - -#[derive(Debug)] -pub struct DirBuilder {} - -impl FileAttr { - pub fn size(&self) -> u64 { - match self.0 {} - } - - pub fn perm(&self) -> FilePermissions { - match self.0 {} - } - - pub fn file_type(&self) -> FileType { - match self.0 {} - } - - pub fn modified(&self) -> io::Result<SystemTime> { - match self.0 {} - } - - pub fn accessed(&self) -> io::Result<SystemTime> { - match self.0 {} - } - - pub fn created(&self) -> io::Result<SystemTime> { - match self.0 {} - } -} - -impl Clone for FileAttr { - fn clone(&self) -> FileAttr { - match self.0 {} - } -} - -impl FilePermissions { - pub fn readonly(&self) -> bool { - match self.0 {} - } - - pub fn set_readonly(&mut self, _readonly: bool) { - match self.0 {} - } -} - -impl Clone for FilePermissions { - fn clone(&self) -> FilePermissions { - match self.0 {} - } -} - -impl PartialEq for FilePermissions { - fn eq(&self, _other: &FilePermissions) -> bool { - match self.0 {} - } -} - -impl Eq for FilePermissions {} - -impl fmt::Debug for FilePermissions { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} - } -} - -impl FileType { - pub fn is_dir(&self) -> bool { - match self.0 {} - } - - pub fn is_file(&self) -> bool { - match self.0 {} - } - - pub fn is_symlink(&self) -> bool { - match self.0 {} - } -} - -impl Clone for FileType { - fn clone(&self) -> FileType { - match self.0 {} - } -} - -impl Copy for FileType {} - -impl PartialEq for FileType { - fn eq(&self, _other: &FileType) -> bool { - match self.0 {} - } -} - -impl Eq for FileType {} - -impl Hash for FileType { - fn hash<H: Hasher>(&self, _h: &mut H) { - match self.0 {} - } -} - -impl fmt::Debug for FileType { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} - } -} - -impl fmt::Debug for ReadDir { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} - } -} - -impl Iterator for ReadDir { - type Item = io::Result<DirEntry>; - - fn next(&mut self) -> Option<io::Result<DirEntry>> { - match self.0 {} - } -} - -impl DirEntry { - pub fn path(&self) -> PathBuf { - match self.0 {} - } - - pub fn file_name(&self) -> OsString { - match self.0 {} - } - - pub fn metadata(&self) -> io::Result<FileAttr> { - match self.0 {} - } - - pub fn file_type(&self) -> io::Result<FileType> { - match self.0 {} - } -} - -impl OpenOptions { - pub fn new() -> OpenOptions { - OpenOptions {} - } - - pub fn read(&mut self, _read: bool) {} - pub fn write(&mut self, _write: bool) {} - pub fn append(&mut self, _append: bool) {} - pub fn truncate(&mut self, _truncate: bool) {} - pub fn create(&mut self, _create: bool) {} - pub fn create_new(&mut self, _create_new: bool) {} -} - -impl File { - pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> { - unsupported() - } - - pub fn file_attr(&self) -> io::Result<FileAttr> { - match self.0 {} - } - - pub fn fsync(&self) -> io::Result<()> { - match self.0 {} - } - - pub fn datasync(&self) -> io::Result<()> { - match self.0 {} - } - - pub fn truncate(&self, _size: u64) -> io::Result<()> { - match self.0 {} - } - - pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> { - match self.0 {} - } - - pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - match self.0 {} - } - - pub fn is_read_vectored(&self) -> bool { - match self.0 {} - } - - pub fn write(&self, _buf: &[u8]) -> io::Result<usize> { - match self.0 {} - } - - pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> { - match self.0 {} - } - - pub fn is_write_vectored(&self) -> bool { - match self.0 {} - } - - pub fn flush(&self) -> io::Result<()> { - match self.0 {} - } - - pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> { - match self.0 {} - } - - pub fn duplicate(&self) -> io::Result<File> { - match self.0 {} - } - - pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> { - match self.0 {} - } - - pub fn diverge(&self) -> ! { - match self.0 {} - } -} - -impl DirBuilder { - pub fn new() -> DirBuilder { - DirBuilder {} - } - - pub fn mkdir(&self, _p: &Path) -> io::Result<()> { - unsupported() - } -} - -impl fmt::Debug for File { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} - } -} - -pub fn readdir(_p: &Path) -> io::Result<ReadDir> { - unsupported() -} - -pub fn unlink(_p: &Path) -> io::Result<()> { - unsupported() -} - -pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { - unsupported() -} - -pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> { - match perm.0 {} -} - -pub fn rmdir(_p: &Path) -> io::Result<()> { - unsupported() -} - -pub fn remove_dir_all(_path: &Path) -> io::Result<()> { - unsupported() -} - -pub fn readlink(_p: &Path) -> io::Result<PathBuf> { - unsupported() -} - -pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> { - unsupported() -} - -pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> { - unsupported() -} - -pub fn stat(_p: &Path) -> io::Result<FileAttr> { - unsupported() -} - -pub fn lstat(_p: &Path) -> io::Result<FileAttr> { - unsupported() -} - -pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> { - unsupported() -} - -pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> { - unsupported() -} diff --git a/library/std/src/sys/sgx/io.rs b/library/std/src/sys/sgx/io.rs deleted file mode 100644 index d5f475b4310..00000000000 --- a/library/std/src/sys/sgx/io.rs +++ /dev/null @@ -1,47 +0,0 @@ -use crate::mem; - -#[derive(Copy, Clone)] -pub struct IoSlice<'a>(&'a [u8]); - -impl<'a> IoSlice<'a> { - #[inline] - pub fn new(buf: &'a [u8]) -> IoSlice<'a> { - IoSlice(buf) - } - - #[inline] - pub fn advance(&mut self, n: usize) { - self.0 = &self.0[n..] - } - - #[inline] - pub fn as_slice(&self) -> &[u8] { - self.0 - } -} - -pub struct IoSliceMut<'a>(&'a mut [u8]); - -impl<'a> IoSliceMut<'a> { - #[inline] - pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { - IoSliceMut(buf) - } - - #[inline] - pub fn advance(&mut self, n: usize) { - let slice = mem::replace(&mut self.0, &mut []); - let (_, remaining) = slice.split_at_mut(n); - self.0 = remaining; - } - - #[inline] - pub fn as_slice(&self) -> &[u8] { - self.0 - } - - #[inline] - pub fn as_mut_slice(&mut self) -> &mut [u8] { - self.0 - } -} diff --git a/library/std/src/sys/sgx/mod.rs b/library/std/src/sys/sgx/mod.rs index 1d32eb25424..1abd91e75e8 100644 --- a/library/std/src/sys/sgx/mod.rs +++ b/library/std/src/sys/sgx/mod.rs @@ -17,14 +17,18 @@ pub mod condvar; pub mod env; pub mod ext; pub mod fd; +#[path = "../unsupported/fs.rs"] pub mod fs; +#[path = "../unsupported/io.rs"] pub mod io; pub mod memchr; pub mod mutex; pub mod net; pub mod os; pub mod path; +#[path = "../unsupported/pipe.rs"] pub mod pipe; +#[path = "../unsupported/process.rs"] pub mod process; pub mod rwlock; pub mod stack_overflow; diff --git a/library/std/src/sys/sgx/pipe.rs b/library/std/src/sys/sgx/pipe.rs deleted file mode 100644 index 10d0925823e..00000000000 --- a/library/std/src/sys/sgx/pipe.rs +++ /dev/null @@ -1,38 +0,0 @@ -use crate::io::{self, IoSlice, IoSliceMut}; -use crate::sys::Void; - -pub struct AnonPipe(Void); - -impl AnonPipe { - pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> { - match self.0 {} - } - - pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - match self.0 {} - } - - pub fn is_read_vectored(&self) -> bool { - match self.0 {} - } - - pub fn write(&self, _buf: &[u8]) -> io::Result<usize> { - match self.0 {} - } - - pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> { - match self.0 {} - } - - pub fn is_write_vectored(&self) -> bool { - match self.0 {} - } - - pub fn diverge(&self) -> ! { - match self.0 {} - } -} - -pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> { - match p1.0 {} -} diff --git a/library/std/src/sys/sgx/process.rs b/library/std/src/sys/sgx/process.rs deleted file mode 100644 index 4702e5c5492..00000000000 --- a/library/std/src/sys/sgx/process.rs +++ /dev/null @@ -1,149 +0,0 @@ -use crate::ffi::OsStr; -use crate::fmt; -use crate::io; -use crate::sys::fs::File; -use crate::sys::pipe::AnonPipe; -use crate::sys::{unsupported, Void}; -use crate::sys_common::process::CommandEnv; - -pub use crate::ffi::OsString as EnvKey; - -//////////////////////////////////////////////////////////////////////////////// -// Command -//////////////////////////////////////////////////////////////////////////////// - -pub struct Command { - env: CommandEnv, -} - -// passed back to std::process with the pipes connected to the child, if any -// were requested -pub struct StdioPipes { - pub stdin: Option<AnonPipe>, - pub stdout: Option<AnonPipe>, - pub stderr: Option<AnonPipe>, -} - -pub enum Stdio { - Inherit, - Null, - MakePipe, -} - -impl Command { - pub fn new(_program: &OsStr) -> Command { - Command { env: Default::default() } - } - - pub fn arg(&mut self, _arg: &OsStr) {} - - pub fn env_mut(&mut self) -> &mut CommandEnv { - &mut self.env - } - - pub fn cwd(&mut self, _dir: &OsStr) {} - - pub fn stdin(&mut self, _stdin: Stdio) {} - - pub fn stdout(&mut self, _stdout: Stdio) {} - - pub fn stderr(&mut self, _stderr: Stdio) {} - - pub fn spawn( - &mut self, - _default: Stdio, - _needs_stdin: bool, - ) -> io::Result<(Process, StdioPipes)> { - unsupported() - } -} - -impl From<AnonPipe> for Stdio { - fn from(pipe: AnonPipe) -> Stdio { - pipe.diverge() - } -} - -impl From<File> for Stdio { - fn from(file: File) -> Stdio { - file.diverge() - } -} - -impl fmt::Debug for Command { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - Ok(()) - } -} - -pub struct ExitStatus(Void); - -impl ExitStatus { - pub fn success(&self) -> bool { - match self.0 {} - } - - pub fn code(&self) -> Option<i32> { - match self.0 {} - } -} - -impl Clone for ExitStatus { - fn clone(&self) -> ExitStatus { - match self.0 {} - } -} - -impl Copy for ExitStatus {} - -impl PartialEq for ExitStatus { - fn eq(&self, _other: &ExitStatus) -> bool { - match self.0 {} - } -} - -impl Eq for ExitStatus {} - -impl fmt::Debug for ExitStatus { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} - } -} - -impl fmt::Display for ExitStatus { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} - } -} - -#[derive(PartialEq, Eq, Clone, Copy, Debug)] -pub struct ExitCode(bool); - -impl ExitCode { - pub const SUCCESS: ExitCode = ExitCode(false); - pub const FAILURE: ExitCode = ExitCode(true); - - pub fn as_i32(&self) -> i32 { - self.0 as i32 - } -} - -pub struct Process(Void); - -impl Process { - pub fn id(&self) -> u32 { - match self.0 {} - } - - pub fn kill(&mut self) -> io::Result<()> { - match self.0 {} - } - - pub fn wait(&mut self) -> io::Result<ExitStatus> { - match self.0 {} - } - - pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> { - match self.0 {} - } -} diff --git a/library/std/src/sys/unix/alloc.rs b/library/std/src/sys/unix/alloc.rs index 8e193935460..964abe8b8c9 100644 --- a/library/std/src/sys/unix/alloc.rs +++ b/library/std/src/sys/unix/alloc.rs @@ -52,46 +52,48 @@ unsafe impl GlobalAlloc for System { } } -#[cfg(any( - target_os = "android", - target_os = "illumos", - target_os = "redox", - target_os = "solaris" -))] -#[inline] -unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { - // On android we currently target API level 9 which unfortunately - // doesn't have the `posix_memalign` API used below. Instead we use - // `memalign`, but this unfortunately has the property on some systems - // where the memory returned cannot be deallocated by `free`! - // - // Upon closer inspection, however, this appears to work just fine with - // Android, so for this platform we should be fine to call `memalign` - // (which is present in API level 9). Some helpful references could - // possibly be chromium using memalign [1], attempts at documenting that - // memalign + free is ok [2] [3], or the current source of chromium - // which still uses memalign on android [4]. - // - // [1]: https://codereview.chromium.org/10796020/ - // [2]: https://code.google.com/p/android/issues/detail?id=35391 - // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579 - // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/ - // /memory/aligned_memory.cc - libc::memalign(layout.align(), layout.size()) as *mut u8 -} - -#[cfg(not(any( - target_os = "android", - target_os = "illumos", - target_os = "redox", - target_os = "solaris" -)))] -#[inline] -unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { - let mut out = ptr::null_mut(); - // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`. - // Since these are all powers of 2, we can just use max. - let align = layout.align().max(crate::mem::size_of::<usize>()); - let ret = libc::posix_memalign(&mut out, align, layout.size()); - if ret != 0 { ptr::null_mut() } else { out as *mut u8 } +cfg_if::cfg_if! { + if #[cfg(any( + target_os = "android", + target_os = "illumos", + target_os = "redox", + target_os = "solaris" + ))] { + #[inline] + unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { + // On android we currently target API level 9 which unfortunately + // doesn't have the `posix_memalign` API used below. Instead we use + // `memalign`, but this unfortunately has the property on some systems + // where the memory returned cannot be deallocated by `free`! + // + // Upon closer inspection, however, this appears to work just fine with + // Android, so for this platform we should be fine to call `memalign` + // (which is present in API level 9). Some helpful references could + // possibly be chromium using memalign [1], attempts at documenting that + // memalign + free is ok [2] [3], or the current source of chromium + // which still uses memalign on android [4]. + // + // [1]: https://codereview.chromium.org/10796020/ + // [2]: https://code.google.com/p/android/issues/detail?id=35391 + // [3]: https://bugs.chromium.org/p/chromium/issues/detail?id=138579 + // [4]: https://chromium.googlesource.com/chromium/src/base/+/master/ + // /memory/aligned_memory.cc + libc::memalign(layout.align(), layout.size()) as *mut u8 + } + } else if #[cfg(target_os = "wasi")] { + #[inline] + unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { + libc::aligned_alloc(layout.align(), layout.size()) as *mut u8 + } + } else { + #[inline] + unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 { + let mut out = ptr::null_mut(); + // posix_memalign requires that the alignment be a multiple of `sizeof(void*)`. + // Since these are all powers of 2, we can just use max. + let align = layout.align().max(crate::mem::size_of::<usize>()); + let ret = libc::posix_memalign(&mut out, align, layout.size()); + if ret != 0 { ptr::null_mut() } else { out as *mut u8 } + } + } } diff --git a/library/std/src/sys/unix/ext/mod.rs b/library/std/src/sys/unix/ext/mod.rs index cbdb1c10049..f4354688098 100644 --- a/library/std/src/sys/unix/ext/mod.rs +++ b/library/std/src/sys/unix/ext/mod.rs @@ -37,6 +37,18 @@ pub mod process; pub mod raw; pub mod thread; +#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")] +#[cfg(any( + target_os = "android", + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "openbsd" +))] +pub mod ucred; + /// A prelude for conveniently writing platform-specific code. /// /// Includes all extension traits, and some important type definitions. diff --git a/library/std/src/sys/unix/ext/net.rs b/library/std/src/sys/unix/ext/net.rs index 320378e30cc..f3da8f9f584 100644 --- a/library/std/src/sys/unix/ext/net.rs +++ b/library/std/src/sys/unix/ext/net.rs @@ -31,6 +31,29 @@ use crate::sys_common::{self, AsInner, FromInner, IntoInner}; use crate::time::Duration; #[cfg(any( + target_os = "android", + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "openbsd" +))] +use crate::os::unix::ucred; + +#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")] +#[cfg(any( + target_os = "android", + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "openbsd" +))] +pub use ucred::UCred; + +#[cfg(any( target_os = "linux", target_os = "android", target_os = "dragonfly", @@ -405,6 +428,34 @@ impl UnixStream { SocketAddr::new(|addr, len| unsafe { libc::getpeername(*self.0.as_inner(), addr, len) }) } + /// Gets the peer credentials for this Unix domain socket. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(peer_credentials_unix_socket)] + /// use std::os::unix::net::UnixStream; + /// + /// fn main() -> std::io::Result<()> { + /// let socket = UnixStream::connect("/tmp/sock")?; + /// let peer_cred = socket.peer_cred().expect("Couldn't get peer credentials"); + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")] + #[cfg(any( + target_os = "android", + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "openbsd" + ))] + pub fn peer_cred(&self) -> io::Result<UCred> { + ucred::peer_cred(self) + } + /// Sets the read timeout for the socket. /// /// If the provided value is [`None`], then [`read`] calls will block diff --git a/library/std/src/sys/unix/ext/ucred.rs b/library/std/src/sys/unix/ext/ucred.rs new file mode 100644 index 00000000000..ed7516c7f28 --- /dev/null +++ b/library/std/src/sys/unix/ext/ucred.rs @@ -0,0 +1,97 @@ +//! Unix peer credentials. + +// NOTE: Code in this file is heavily based on work done in PR 13 from the tokio-uds repository on +// GitHub. +// +// For reference, the link is here: https://github.com/tokio-rs/tokio-uds/pull/13 +// Credit to Martin Habovštiak (GitHub username Kixunil) and contributors for this work. + +use libc::{gid_t, pid_t, uid_t}; + +/// Credentials for a UNIX process for credentials passing. +#[unstable(feature = "peer_credentials_unix_socket", issue = "42839", reason = "unstable")] +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +pub struct UCred { + /// The UID part of the peer credential. This is the effective UID of the process at the domain + /// socket's endpoint. + pub uid: uid_t, + /// The GID part of the peer credential. This is the effective GID of the process at the domain + /// socket's endpoint. + pub gid: gid_t, + /// The PID part of the peer credential. This field is optional because the PID part of the + /// peer credentials is not supported on every platform. On platforms where the mechanism to + /// discover the PID exists, this field will be populated to the PID of the process at the + /// domain socket's endpoint. Otherwise, it will be set to None. + pub pid: Option<pid_t>, +} + +#[cfg(any(target_os = "android", target_os = "linux"))] +pub use self::impl_linux::peer_cred; + +#[cfg(any( + target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "openbsd" +))] +pub use self::impl_bsd::peer_cred; + +#[cfg(any(target_os = "linux", target_os = "android"))] +pub mod impl_linux { + use super::UCred; + use crate::os::unix::io::AsRawFd; + use crate::os::unix::net::UnixStream; + use crate::{io, mem}; + use libc::{c_void, getsockopt, socklen_t, ucred, SOL_SOCKET, SO_PEERCRED}; + + pub fn peer_cred(socket: &UnixStream) -> io::Result<UCred> { + let ucred_size = mem::size_of::<ucred>(); + + // Trivial sanity checks. + assert!(mem::size_of::<u32>() <= mem::size_of::<usize>()); + assert!(ucred_size <= u32::MAX as usize); + + let mut ucred_size = ucred_size as socklen_t; + let mut ucred: ucred = ucred { pid: 1, uid: 1, gid: 1 }; + + unsafe { + let ret = getsockopt( + socket.as_raw_fd(), + SOL_SOCKET, + SO_PEERCRED, + &mut ucred as *mut ucred as *mut c_void, + &mut ucred_size, + ); + + if ret == 0 && ucred_size as usize == mem::size_of::<ucred>() { + Ok(UCred { uid: ucred.uid, gid: ucred.gid, pid: Some(ucred.pid) }) + } else { + Err(io::Error::last_os_error()) + } + } + } +} + +#[cfg(any( + target_os = "dragonfly", + target_os = "macos", + target_os = "ios", + target_os = "freebsd", + target_os = "openbsd" +))] +pub mod impl_bsd { + use super::UCred; + use crate::io; + use crate::os::unix::io::AsRawFd; + use crate::os::unix::net::UnixStream; + + pub fn peer_cred(socket: &UnixStream) -> io::Result<UCred> { + let mut cred = UCred { uid: 1, gid: 1, pid: None }; + unsafe { + let ret = libc::getpeereid(socket.as_raw_fd(), &mut cred.uid, &mut cred.gid); + + if ret == 0 { Ok(cred) } else { Err(io::Error::last_os_error()) } + } + } +} diff --git a/library/std/src/sys/unix/ext/ucred/tests.rs b/library/std/src/sys/unix/ext/ucred/tests.rs new file mode 100644 index 00000000000..451b534b266 --- /dev/null +++ b/library/std/src/sys/unix/ext/ucred/tests.rs @@ -0,0 +1,25 @@ +use crate::os::unix::net::UnixStream; +use libc::{getegid, geteuid}; + +#[test] +#[cfg(any( + target_os = "android", + target_os = "linux", + target_os = "dragonfly", + target_os = "freebsd", + target_os = "ios", + target_os = "macos", + target_os = "openbsd" +))] +fn test_socket_pair() { + // Create two connected sockets and get their peer credentials. They should be equal. + let (sock_a, sock_b) = UnixStream::pair().unwrap(); + let (cred_a, cred_b) = (sock_a.peer_cred().unwrap(), sock_b.peer_cred().unwrap()); + assert_eq!(cred_a, cred_b); + + // Check that the UID and GIDs match up. + let uid = unsafe { geteuid() }; + let gid = unsafe { getegid() }; + assert_eq!(cred_a.uid, uid); + assert_eq!(cred_a.gid, gid); +} diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs index 6daf2885bae..fab27cd9f70 100644 --- a/library/std/src/sys/unix/process/process_fuchsia.rs +++ b/library/std/src/sys/unix/process/process_fuchsia.rs @@ -118,7 +118,8 @@ impl Command { FDIO_SPAWN_CLONE_JOB | FDIO_SPAWN_CLONE_LDSVC | FDIO_SPAWN_CLONE_NAMESPACE - | FDIO_SPAWN_CLONE_ENVIRON, // this is ignored when envp is non-null + | FDIO_SPAWN_CLONE_ENVIRON // this is ignored when envp is non-null + | FDIO_SPAWN_CLONE_UTC_CLOCK, self.get_program().as_ptr(), self.get_argv().as_ptr(), envp, diff --git a/library/std/src/sys/unix/process/zircon.rs b/library/std/src/sys/unix/process/zircon.rs index 750b8f0762a..69ec275c2b3 100644 --- a/library/std/src/sys/unix/process/zircon.rs +++ b/library/std/src/sys/unix/process/zircon.rs @@ -138,6 +138,7 @@ pub const FDIO_SPAWN_CLONE_LDSVC: u32 = 0x0002; pub const FDIO_SPAWN_CLONE_NAMESPACE: u32 = 0x0004; pub const FDIO_SPAWN_CLONE_STDIO: u32 = 0x0008; pub const FDIO_SPAWN_CLONE_ENVIRON: u32 = 0x0010; +pub const FDIO_SPAWN_CLONE_UTC_CLOCK: u32 = 0x0020; pub const FDIO_SPAWN_CLONE_ALL: u32 = 0xFFFF; // fdio_spawn_etc actions diff --git a/library/std/src/sys/unsupported/fs.rs b/library/std/src/sys/unsupported/fs.rs index ecb5b51cccd..faa53b6a744 100644 --- a/library/std/src/sys/unsupported/fs.rs +++ b/library/std/src/sys/unsupported/fs.rs @@ -233,10 +233,6 @@ impl File { pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> { match self.0 {} } - - pub fn diverge(&self) -> ! { - match self.0 {} - } } impl DirBuilder { diff --git a/library/std/src/sys/unsupported/mod.rs b/library/std/src/sys/unsupported/mod.rs index 87f655eecd5..8ba870c5dbc 100644 --- a/library/std/src/sys/unsupported/mod.rs +++ b/library/std/src/sys/unsupported/mod.rs @@ -8,6 +8,7 @@ pub mod io; pub mod mutex; pub mod net; pub mod os; +#[path = "../unix/path.rs"] pub mod path; pub mod pipe; pub mod process; diff --git a/library/std/src/sys/unsupported/path.rs b/library/std/src/sys/unsupported/path.rs deleted file mode 100644 index 840a7ae0426..00000000000 --- a/library/std/src/sys/unsupported/path.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::ffi::OsStr; -use crate::path::Prefix; - -#[inline] -pub fn is_sep_byte(b: u8) -> bool { - b == b'/' -} - -#[inline] -pub fn is_verbatim_sep(b: u8) -> bool { - b == b'/' -} - -pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> { - None -} - -pub const MAIN_SEP_STR: &str = "/"; -pub const MAIN_SEP: char = '/'; diff --git a/library/std/src/sys/unsupported/process.rs b/library/std/src/sys/unsupported/process.rs index 4702e5c5492..7156c9ab92f 100644 --- a/library/std/src/sys/unsupported/process.rs +++ b/library/std/src/sys/unsupported/process.rs @@ -65,8 +65,8 @@ impl From<AnonPipe> for Stdio { } impl From<File> for Stdio { - fn from(file: File) -> Stdio { - file.diverge() + fn from(_file: File) -> Stdio { + panic!("unsupported") } } diff --git a/library/std/src/sys/wasi/alloc.rs b/library/std/src/sys/wasi/alloc.rs deleted file mode 100644 index 4d0afe27bb8..00000000000 --- a/library/std/src/sys/wasi/alloc.rs +++ /dev/null @@ -1,69 +0,0 @@ -#![deny(unsafe_op_in_unsafe_fn)] - -use crate::alloc::{GlobalAlloc, Layout, System}; -use crate::ptr; -use crate::sys_common::alloc::{realloc_fallback, MIN_ALIGN}; - -// SAFETY: All methods implemented follow the contract rules defined -// in `GlobalAlloc`. -#[stable(feature = "alloc_system_type", since = "1.28.0")] -unsafe impl GlobalAlloc for System { - #[inline] - unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { - // SAFETY: `libc::malloc` is guaranteed to be safe, it will allocate - // `layout.size()` bytes of memory and return a pointer to it - unsafe { libc::malloc(layout.size()) as *mut u8 } - } else { - // SAFETY: `libc::aligned_alloc` is guaranteed to be safe if - // `layout.size()` is a multiple of `layout.align()`. This - // constraint can be satisfied if `pad_to_align` is called, - // which creates a layout by rounding the size of this layout up - // to a multiple of the layout's alignment - let aligned_layout = layout.pad_to_align(); - unsafe { libc::aligned_alloc(aligned_layout.align(), aligned_layout.size()) as *mut u8 } - } - } - - #[inline] - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() { - // SAFETY: `libc::calloc` is safe as long that `layout.size() * 1` - // would not result in integer overflow which cannot happen, - // multiplying by one never overflows - unsafe { libc::calloc(layout.size(), 1) as *mut u8 } - } else { - // SAFETY: The safety contract for `alloc` must be upheld by the caller - let ptr = unsafe { self.alloc(layout.clone()) }; - if !ptr.is_null() { - // SAFETY: in the case of the `ptr` being not null - // it will be properly aligned and a valid ptr - // which satisfies `ptr::write_bytes` safety constrains - unsafe { ptr::write_bytes(ptr, 0, layout.size()) }; - } - ptr - } - } - - #[inline] - unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) { - // SAFETY: `libc::free` is guaranteed to be safe if `ptr` is allocated - // by this allocator or if `ptr` is NULL - unsafe { libc::free(ptr as *mut libc::c_void) } - } - - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - if layout.align() <= MIN_ALIGN && layout.align() <= new_size { - // SAFETY: `libc::realloc` is safe if `ptr` is allocated by this - // allocator or NULL - // - If `new_size` is 0 and `ptr` is not NULL, it will act as `libc::free` - // - If `new_size` is not 0 and `ptr` is NULL, it will act as `libc::malloc` - // - Else, it will resize the block accordingly - unsafe { libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8 } - } else { - // SAFETY: The safety contract for `realloc_fallback` must be upheld by the caller - unsafe { realloc_fallback(self, ptr, layout, new_size) } - } - } -} diff --git a/library/std/src/sys/wasi/mod.rs b/library/std/src/sys/wasi/mod.rs index 2704ff484f9..a7a4407ac38 100644 --- a/library/std/src/sys/wasi/mod.rs +++ b/library/std/src/sys/wasi/mod.rs @@ -17,6 +17,7 @@ use crate::io as std_io; use crate::mem; +#[path = "../unix/alloc.rs"] pub mod alloc; pub mod args; #[path = "../unsupported/cmath.rs"] @@ -33,8 +34,11 @@ pub mod net; pub mod os; pub use crate::sys_common::os_str_bytes as os_str; pub mod ext; +#[path = "../unix/path.rs"] pub mod path; +#[path = "../unsupported/pipe.rs"] pub mod pipe; +#[path = "../unsupported/process.rs"] pub mod process; #[path = "../unsupported/rwlock.rs"] pub mod rwlock; diff --git a/library/std/src/sys/wasi/path.rs b/library/std/src/sys/wasi/path.rs deleted file mode 100644 index 840a7ae0426..00000000000 --- a/library/std/src/sys/wasi/path.rs +++ /dev/null @@ -1,19 +0,0 @@ -use crate::ffi::OsStr; -use crate::path::Prefix; - -#[inline] -pub fn is_sep_byte(b: u8) -> bool { - b == b'/' -} - -#[inline] -pub fn is_verbatim_sep(b: u8) -> bool { - b == b'/' -} - -pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> { - None -} - -pub const MAIN_SEP_STR: &str = "/"; -pub const MAIN_SEP: char = '/'; diff --git a/library/std/src/sys/wasi/pipe.rs b/library/std/src/sys/wasi/pipe.rs deleted file mode 100644 index 180fc114d86..00000000000 --- a/library/std/src/sys/wasi/pipe.rs +++ /dev/null @@ -1,40 +0,0 @@ -#![deny(unsafe_op_in_unsafe_fn)] - -use crate::io::{self, IoSlice, IoSliceMut}; -use crate::sys::Void; - -pub struct AnonPipe(Void); - -impl AnonPipe { - pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> { - match self.0 {} - } - - pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { - match self.0 {} - } - - pub fn is_read_vectored(&self) -> bool { - match self.0 {} - } - - pub fn write(&self, _buf: &[u8]) -> io::Result<usize> { - match self.0 {} - } - - pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> { - match self.0 {} - } - - pub fn is_write_vectored(&self) -> bool { - match self.0 {} - } - - pub fn diverge(&self) -> ! { - match self.0 {} - } -} - -pub fn read2(p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> { - match p1.0 {} -} diff --git a/library/std/src/sys/wasi/process.rs b/library/std/src/sys/wasi/process.rs deleted file mode 100644 index c69d6376b01..00000000000 --- a/library/std/src/sys/wasi/process.rs +++ /dev/null @@ -1,151 +0,0 @@ -#![deny(unsafe_op_in_unsafe_fn)] - -use crate::ffi::OsStr; -use crate::fmt; -use crate::io; -use crate::sys::fs::File; -use crate::sys::pipe::AnonPipe; -use crate::sys::{unsupported, Void}; -use crate::sys_common::process::CommandEnv; - -pub use crate::ffi::OsString as EnvKey; - -//////////////////////////////////////////////////////////////////////////////// -// Command -//////////////////////////////////////////////////////////////////////////////// - -pub struct Command { - env: CommandEnv, -} - -// passed back to std::process with the pipes connected to the child, if any -// were requested -pub struct StdioPipes { - pub stdin: Option<AnonPipe>, - pub stdout: Option<AnonPipe>, - pub stderr: Option<AnonPipe>, -} - -pub enum Stdio { - Inherit, - Null, - MakePipe, -} - -impl Command { - pub fn new(_program: &OsStr) -> Command { - Command { env: Default::default() } - } - - pub fn arg(&mut self, _arg: &OsStr) {} - - pub fn env_mut(&mut self) -> &mut CommandEnv { - &mut self.env - } - - pub fn cwd(&mut self, _dir: &OsStr) {} - - pub fn stdin(&mut self, _stdin: Stdio) {} - - pub fn stdout(&mut self, _stdout: Stdio) {} - - pub fn stderr(&mut self, _stderr: Stdio) {} - - pub fn spawn( - &mut self, - _default: Stdio, - _needs_stdin: bool, - ) -> io::Result<(Process, StdioPipes)> { - unsupported() - } -} - -impl From<AnonPipe> for Stdio { - fn from(pipe: AnonPipe) -> Stdio { - pipe.diverge() - } -} - -impl From<File> for Stdio { - fn from(_file: File) -> Stdio { - panic!("unsupported") - } -} - -impl fmt::Debug for Command { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - Ok(()) - } -} - -pub struct ExitStatus(Void); - -impl ExitStatus { - pub fn success(&self) -> bool { - match self.0 {} - } - - pub fn code(&self) -> Option<i32> { - match self.0 {} - } -} - -impl Clone for ExitStatus { - fn clone(&self) -> ExitStatus { - match self.0 {} - } -} - -impl Copy for ExitStatus {} - -impl PartialEq for ExitStatus { - fn eq(&self, _other: &ExitStatus) -> bool { - match self.0 {} - } -} - -impl Eq for ExitStatus {} - -impl fmt::Debug for ExitStatus { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} - } -} - -impl fmt::Display for ExitStatus { - fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.0 {} - } -} - -#[derive(PartialEq, Eq, Clone, Copy, Debug)] -pub struct ExitCode(bool); - -impl ExitCode { - pub const SUCCESS: ExitCode = ExitCode(false); - pub const FAILURE: ExitCode = ExitCode(true); - - pub fn as_i32(&self) -> i32 { - self.0 as i32 - } -} - -pub struct Process(Void); - -impl Process { - pub fn id(&self) -> u32 { - match self.0 {} - } - - pub fn kill(&mut self) -> io::Result<()> { - match self.0 {} - } - - pub fn wait(&mut self) -> io::Result<ExitStatus> { - match self.0 {} - } - - pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> { - match self.0 {} - } -} diff --git a/library/std/src/sys/wasm/mod.rs b/library/std/src/sys/wasm/mod.rs index 3de58904043..2934ea59ab5 100644 --- a/library/std/src/sys/wasm/mod.rs +++ b/library/std/src/sys/wasm/mod.rs @@ -27,7 +27,7 @@ pub mod io; pub mod net; #[path = "../unsupported/os.rs"] pub mod os; -#[path = "../unsupported/path.rs"] +#[path = "../unix/path.rs"] pub mod path; #[path = "../unsupported/pipe.rs"] pub mod pipe; diff --git a/library/std/src/sys/windows/mutex.rs b/library/std/src/sys/windows/mutex.rs index 63dfc640908..1e09b95c872 100644 --- a/library/std/src/sys/windows/mutex.rs +++ b/library/std/src/sys/windows/mutex.rs @@ -19,20 +19,25 @@ //! CriticalSection is used and we keep track of who's holding the mutex to //! detect recursive locks. -use crate::cell::UnsafeCell; +use crate::cell::{Cell, UnsafeCell}; use crate::mem::{self, MaybeUninit}; use crate::sync::atomic::{AtomicUsize, Ordering}; use crate::sys::c; use crate::sys::compat; pub struct Mutex { + // This is either directly an SRWLOCK (if supported), or a Box<Inner> otherwise. lock: AtomicUsize, - held: UnsafeCell<bool>, } unsafe impl Send for Mutex {} unsafe impl Sync for Mutex {} +struct Inner { + remutex: ReentrantMutex, + held: Cell<bool>, +} + #[derive(Clone, Copy)] enum Kind { SRWLock = 1, @@ -51,7 +56,6 @@ impl Mutex { // This works because SRWLOCK_INIT is 0 (wrapped in a struct), so we are also properly // initializing an SRWLOCK here. lock: AtomicUsize::new(0), - held: UnsafeCell::new(false), } } #[inline] @@ -60,10 +64,11 @@ impl Mutex { match kind() { Kind::SRWLock => c::AcquireSRWLockExclusive(raw(self)), Kind::CriticalSection => { - let re = self.remutex(); - (*re).lock(); - if !self.flag_locked() { - (*re).unlock(); + let inner = &*self.inner(); + inner.remutex.lock(); + if inner.held.replace(true) { + // It was already locked, so we got a recursive lock which we do not want. + inner.remutex.unlock(); panic!("cannot recursively lock a mutex"); } } @@ -73,23 +78,27 @@ impl Mutex { match kind() { Kind::SRWLock => c::TryAcquireSRWLockExclusive(raw(self)) != 0, Kind::CriticalSection => { - let re = self.remutex(); - if !(*re).try_lock() { + let inner = &*self.inner(); + if !inner.remutex.try_lock() { false - } else if self.flag_locked() { - true - } else { - (*re).unlock(); + } else if inner.held.replace(true) { + // It was already locked, so we got a recursive lock which we do not want. + inner.remutex.unlock(); false + } else { + true } } } } pub unsafe fn unlock(&self) { - *self.held.get() = false; match kind() { Kind::SRWLock => c::ReleaseSRWLockExclusive(raw(self)), - Kind::CriticalSection => (*self.remutex()).unlock(), + Kind::CriticalSection => { + let inner = &*(self.lock.load(Ordering::SeqCst) as *const Inner); + inner.held.set(false); + inner.remutex.unlock(); + } } } pub unsafe fn destroy(&self) { @@ -97,38 +106,27 @@ impl Mutex { Kind::SRWLock => {} Kind::CriticalSection => match self.lock.load(Ordering::SeqCst) { 0 => {} - n => { - Box::from_raw(n as *mut ReentrantMutex).destroy(); - } + n => Box::from_raw(n as *mut Inner).remutex.destroy(), }, } } - unsafe fn remutex(&self) -> *mut ReentrantMutex { + unsafe fn inner(&self) -> *const Inner { match self.lock.load(Ordering::SeqCst) { 0 => {} - n => return n as *mut _, + n => return n as *const _, } - let re = box ReentrantMutex::uninitialized(); - re.init(); - let re = Box::into_raw(re); - match self.lock.compare_and_swap(0, re as usize, Ordering::SeqCst) { - 0 => re, + let inner = box Inner { remutex: ReentrantMutex::uninitialized(), held: Cell::new(false) }; + inner.remutex.init(); + let inner = Box::into_raw(inner); + match self.lock.compare_and_swap(0, inner as usize, Ordering::SeqCst) { + 0 => inner, n => { - Box::from_raw(re).destroy(); - n as *mut _ + Box::from_raw(inner).remutex.destroy(); + n as *const _ } } } - - unsafe fn flag_locked(&self) -> bool { - if *self.held.get() { - false - } else { - *self.held.get() = true; - true - } - } } fn kind() -> Kind { @@ -150,7 +148,7 @@ fn kind() -> Kind { } pub struct ReentrantMutex { - inner: UnsafeCell<MaybeUninit<c::CRITICAL_SECTION>>, + inner: MaybeUninit<UnsafeCell<c::CRITICAL_SECTION>>, } unsafe impl Send for ReentrantMutex {} @@ -158,27 +156,27 @@ unsafe impl Sync for ReentrantMutex {} impl ReentrantMutex { pub const fn uninitialized() -> ReentrantMutex { - ReentrantMutex { inner: UnsafeCell::new(MaybeUninit::uninit()) } + ReentrantMutex { inner: MaybeUninit::uninit() } } pub unsafe fn init(&self) { - c::InitializeCriticalSection((&mut *self.inner.get()).as_mut_ptr()); + c::InitializeCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr())); } pub unsafe fn lock(&self) { - c::EnterCriticalSection((&mut *self.inner.get()).as_mut_ptr()); + c::EnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr())); } #[inline] pub unsafe fn try_lock(&self) -> bool { - c::TryEnterCriticalSection((&mut *self.inner.get()).as_mut_ptr()) != 0 + c::TryEnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr())) != 0 } pub unsafe fn unlock(&self) { - c::LeaveCriticalSection((&mut *self.inner.get()).as_mut_ptr()); + c::LeaveCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr())); } pub unsafe fn destroy(&self) { - c::DeleteCriticalSection((&mut *self.inner.get()).as_mut_ptr()); + c::DeleteCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr())); } } diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 9d8c6f1815e..60a05dc5d54 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -424,10 +424,9 @@ pub mod fast { // thread_local's, or it is being recursively initialized. // // Macos: Inlining this function can cause two `tlv_get_addr` calls to - // be performed for every call to `Key::get`. The #[cold] hint makes - // that less likely. + // be performed for every call to `Key::get`. // LLVM issue: https://bugs.llvm.org/show_bug.cgi?id=41722 - #[cold] + #[inline(never)] unsafe fn try_initialize<F: FnOnce() -> T>(&self, init: F) -> Option<&'static T> { if !mem::needs_drop::<T>() || self.try_register_dtor() { Some(self.inner.initialize(init)) |
