diff options
Diffstat (limited to 'library/std/src')
| -rw-r--r-- | library/std/src/f128.rs | 24 | ||||
| -rw-r--r-- | library/std/src/f16.rs | 24 | ||||
| -rw-r--r-- | library/std/src/io/mod.rs | 9 | ||||
| -rw-r--r-- | library/std/src/io/stdio.rs | 34 | ||||
| -rw-r--r-- | library/std/src/os/hermit/mod.rs | 2 | ||||
| -rw-r--r-- | library/std/src/os/windows/process.rs | 49 | ||||
| -rw-r--r-- | library/std/src/process.rs | 48 | ||||
| -rw-r--r-- | library/std/src/sys/pal/hermit/alloc.rs | 10 | ||||
| -rw-r--r-- | library/std/src/sys/pal/hermit/fd.rs | 12 | ||||
| -rw-r--r-- | library/std/src/sys/pal/hermit/fs.rs | 51 | ||||
| -rw-r--r-- | library/std/src/sys/pal/hermit/futex.rs | 16 | ||||
| -rw-r--r-- | library/std/src/sys/pal/hermit/mod.rs | 40 | ||||
| -rw-r--r-- | library/std/src/sys/pal/hermit/os.rs | 10 | ||||
| -rw-r--r-- | library/std/src/sys/pal/hermit/stdio.rs | 10 | ||||
| -rw-r--r-- | library/std/src/sys/pal/hermit/thread.rs | 16 | ||||
| -rw-r--r-- | library/std/src/sys/pal/hermit/time.rs | 10 | ||||
| -rw-r--r-- | library/std/src/sys/pal/unix/alloc.rs | 40 | ||||
| -rw-r--r-- | library/std/src/sys/pal/unix/rand.rs | 13 |
18 files changed, 255 insertions, 163 deletions
diff --git a/library/std/src/f128.rs b/library/std/src/f128.rs index 4710d7c50b4..491235a872e 100644 --- a/library/std/src/f128.rs +++ b/library/std/src/f128.rs @@ -7,5 +7,29 @@ #[cfg(test)] mod tests; +#[cfg(not(test))] +use crate::intrinsics; + #[unstable(feature = "f128", issue = "116909")] pub use core::f128::consts; + +#[cfg(not(test))] +impl f128 { + /// Raises a number to an integer power. + /// + /// Using this function is generally faster than using `powf`. + /// It might have a different sequence of rounding operations than `powf`, + /// so the results are not guaranteed to agree. + /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. + #[inline] + #[rustc_allow_incoherent_impl] + #[unstable(feature = "f128", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub fn powi(self, n: i32) -> f128 { + unsafe { intrinsics::powif128(self, n) } + } +} diff --git a/library/std/src/f16.rs b/library/std/src/f16.rs index c36f9f5d4c6..1cb655ffabd 100644 --- a/library/std/src/f16.rs +++ b/library/std/src/f16.rs @@ -7,5 +7,29 @@ #[cfg(test)] mod tests; +#[cfg(not(test))] +use crate::intrinsics; + #[unstable(feature = "f16", issue = "116909")] pub use core::f16::consts; + +#[cfg(not(test))] +impl f16 { + /// Raises a number to an integer power. + /// + /// Using this function is generally faster than using `powf`. + /// It might have a different sequence of rounding operations than `powf`, + /// so the results are not guaranteed to agree. + /// + /// # Unspecified precision + /// + /// The precision of this function is non-deterministic. This means it varies by platform, Rust version, and + /// can even differ within the same execution from one invocation to the next. + #[inline] + #[rustc_allow_incoherent_impl] + #[unstable(feature = "f16", issue = "116909")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub fn powi(self, n: i32) -> f16 { + unsafe { intrinsics::powif16(self, n) } + } +} diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index af055152cbe..f55ec1588f9 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -1839,7 +1839,11 @@ pub trait Write { if output.error.is_err() { output.error } else { - Err(error::const_io_error!(ErrorKind::Uncategorized, "formatter error")) + // This shouldn't happen: the underlying stream did not error, but somehow + // the formatter still errored? + panic!( + "a formatting trait implementation returned an error when the underlying stream did not" + ); } } } @@ -2040,7 +2044,6 @@ pub trait Seek { /// # Example /// /// ```no_run - /// #![feature(seek_seek_relative)] /// use std::{ /// io::{self, Seek}, /// fs::File, @@ -2055,7 +2058,7 @@ pub trait Seek { /// ``` /// /// [`BufReader`]: crate::io::BufReader - #[unstable(feature = "seek_seek_relative", issue = "117374")] + #[stable(feature = "seek_seek_relative", since = "CURRENT_RUSTC_VERSION")] fn seek_relative(&mut self, offset: i64) -> Result<()> { self.seek(SeekFrom::Current(offset))?; Ok(()) diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 07fa9259e0b..c8968b74b12 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -1161,7 +1161,41 @@ pub trait IsTerminal: crate::sealed::Sealed { /// starting with `msys-` or `cygwin-` and ending in `-pty` will be considered terminals. /// Note that this [may change in the future][changes]. /// + /// # Examples + /// + /// An example of a type for which `IsTerminal` is implemented is [`Stdin`]: + /// + /// ```no_run + /// use std::io::{self, IsTerminal, Write}; + /// + /// fn main() -> io::Result<()> { + /// let stdin = io::stdin(); + /// + /// // Indicate that the user is prompted for input, if this is a terminal. + /// if stdin.is_terminal() { + /// print!("> "); + /// io::stdout().flush()?; + /// } + /// + /// let mut name = String::new(); + /// let _ = stdin.read_line(&mut name)?; + /// + /// println!("Hello {}", name.trim_end()); + /// + /// Ok(()) + /// } + /// ``` + /// + /// The example can be run in two ways: + /// + /// - If you run this example by piping some text to it, e.g. `echo "foo" | path/to/executable` + /// it will print: `Hello foo`. + /// - If you instead run the example interactively by running the executable directly, it will + /// panic with the message "Expected input to be piped to the process". + /// + /// /// [changes]: io#platform-specific-behavior + /// [`Stdin`]: crate::io::Stdin #[stable(feature = "is_terminal", since = "1.70.0")] fn is_terminal(&self) -> bool; } diff --git a/library/std/src/os/hermit/mod.rs b/library/std/src/os/hermit/mod.rs index 89b1b831912..02a4b2c3ab5 100644 --- a/library/std/src/os/hermit/mod.rs +++ b/library/std/src/os/hermit/mod.rs @@ -2,7 +2,7 @@ #[allow(unused_extern_crates)] #[stable(feature = "rust1", since = "1.0.0")] -pub extern crate hermit_abi as abi; +pub extern crate hermit_abi; pub mod ffi; pub mod io; diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index 15ab2250122..9cca27fa5dd 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -199,14 +199,14 @@ pub trait CommandExt: Sealed { /// Append literal text to the command line without any quoting or escaping. /// - /// This is useful for passing arguments to applications which doesn't follow + /// This is useful for passing arguments to applications that don't follow /// the standard C run-time escaping rules, such as `cmd.exe /c`. /// - /// # Bat files + /// # Batch files /// - /// Note the `cmd /c` command line has slightly different escaping rules then bat files + /// Note the `cmd /c` command line has slightly different escaping rules than batch files /// themselves. If possible, it may be better to write complex arguments to a temporary - /// .bat file, with appropriate escaping, and simply run that using: + /// `.bat` file, with appropriate escaping, and simply run that using: /// /// ```no_run /// # use std::process::Command; @@ -217,7 +217,7 @@ pub trait CommandExt: Sealed { /// /// # Example /// - /// Run a bat script using both trusted and untrusted arguments. + /// Run a batch script using both trusted and untrusted arguments. /// /// ```no_run /// #[cfg(windows)] @@ -241,9 +241,10 @@ pub trait CommandExt: Sealed { /// if !user_name.chars().all(|c| c.is_alphanumeric()) { /// return Err(Error::new(ErrorKind::InvalidInput, "invalid user name")); /// } - /// // now we've checked the user name, let's add that too. - /// cmd_args.push(' '); - /// cmd_args.push_str(&format!("--user {user_name}")); + /// + /// // now we have validated the user name, let's add that too. + /// cmd_args.push_str(" --user "); + /// cmd_args.push_str(user_name); /// /// // call cmd.exe and return the output /// Command::new("cmd.exe") @@ -287,25 +288,37 @@ pub trait CommandExt: Sealed { #[unstable(feature = "windows_process_extensions_async_pipes", issue = "98289")] fn async_pipes(&mut self, always_async: bool) -> &mut process::Command; - /// Sets a raw attribute on the command, providing extended configuration options for Windows processes. + /// Set a raw attribute on the command, providing extended configuration options for Windows + /// processes. + /// + /// This method allows you to specify custom attributes for a child process on Windows systems + /// using raw attribute values. Raw attributes provide extended configurability for process + /// creation, but their usage can be complex and potentially unsafe. /// - /// This method allows you to specify custom attributes for a child process on Windows systems using raw attribute values. - /// Raw attributes provide extended configurability for process creation, but their usage can be complex and potentially unsafe. + /// The `attribute` parameter specifies the raw attribute to be set, while the `value` + /// parameter holds the value associated with that attribute. Please refer to the + /// [`windows-rs` documentation] or the [Win32 API documentation] for detailed information + /// about available attributes and their meanings. /// - /// The `attribute` parameter specifies the raw attribute to be set, while the `value` parameter holds the value associated with that attribute. - /// Please refer to the [`windows-rs`](https://microsoft.github.io/windows-docs-rs/doc/windows/) documentation or the [`Win32 API documentation`](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute) for detailed information about available attributes and their meanings. + /// [`windows-rs` documentation]: https://microsoft.github.io/windows-docs-rs/doc/windows/ + /// [Win32 API documentation]: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute /// /// # Note /// /// The maximum number of raw attributes is the value of [`u32::MAX`]. - /// If this limit is exceeded, the call to [`process::Command::spawn`] will return an `Error` indicating that the maximum number of attributes has been exceeded. + /// If this limit is exceeded, the call to [`process::Command::spawn`] will return an `Error` + /// indicating that the maximum number of attributes has been exceeded. + /// /// # Safety /// - /// The usage of raw attributes is potentially unsafe and should be done with caution. Incorrect attribute values or improper configuration can lead to unexpected behavior or errors. + /// The usage of raw attributes is potentially unsafe and should be done with caution. + /// Incorrect attribute values or improper configuration can lead to unexpected behavior or + /// errors. /// /// # Example /// - /// The following example demonstrates how to create a child process with a specific parent process ID using a raw attribute. + /// The following example demonstrates how to create a child process with a specific parent + /// process ID using a raw attribute. /// /// ```rust /// #![feature(windows_process_extensions_raw_attribute)] @@ -339,7 +352,9 @@ pub trait CommandExt: Sealed { /// /// # Safety Note /// - /// Remember that improper use of raw attributes can lead to undefined behavior or security vulnerabilities. Always consult the documentation and ensure proper attribute values are used. + /// Remember that improper use of raw attributes can lead to undefined behavior or security + /// vulnerabilities. Always consult the documentation and ensure proper attribute values are + /// used. #[unstable(feature = "windows_process_extensions_raw_attribute", issue = "114854")] unsafe fn raw_attribute<T: Copy + Send + Sync + 'static>( &mut self, diff --git a/library/std/src/process.rs b/library/std/src/process.rs index d1848224251..c926c89f7a9 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -90,8 +90,8 @@ //! //! # Windows argument splitting //! -//! On Unix systems arguments are passed to a new process as an array of strings -//! but on Windows arguments are passed as a single commandline string and it's +//! On Unix systems arguments are passed to a new process as an array of strings, +//! but on Windows arguments are passed as a single commandline string and it is //! up to the child process to parse it into an array. Therefore the parent and //! child processes must agree on how the commandline string is encoded. //! @@ -107,26 +107,26 @@ //! * Use [`raw_arg`] to build a custom commandline. This bypasses the escaping //! rules used by [`arg`] so should be used with due caution. //! -//! `cmd.exe` and `.bat` use non-standard argument parsing and are especially +//! `cmd.exe` and `.bat` files use non-standard argument parsing and are especially //! vulnerable to malicious input as they may be used to run arbitrary shell //! commands. Untrusted arguments should be restricted as much as possible. //! For examples on handling this see [`raw_arg`]. //! -//! ### Bat file special handling +//! ### Batch file special handling //! //! On Windows, `Command` uses the Windows API function [`CreateProcessW`] to -//! spawn new processes. An undocumented feature of this function is that, +//! spawn new processes. An undocumented feature of this function is that //! when given a `.bat` file as the application to run, it will automatically -//! convert that into running `cmd.exe /c` with the bat file as the next argument. +//! convert that into running `cmd.exe /c` with the batch file as the next argument. //! //! For historical reasons Rust currently preserves this behaviour when using //! [`Command::new`], and escapes the arguments according to `cmd.exe` rules. //! Due to the complexity of `cmd.exe` argument handling, it might not be -//! possible to safely escape some special chars, and using them will result +//! possible to safely escape some special characters, and using them will result //! in an error being returned at process spawn. The set of unescapeable -//! special chars might change between releases. +//! special characters might change between releases. //! -//! Also note that running `.bat` scripts in this way may be removed in the +//! Also note that running batch scripts in this way may be removed in the //! future and so should not be relied upon. //! //! [`spawn`]: Command::spawn @@ -659,16 +659,19 @@ impl Command { /// /// Note that the argument is not passed through a shell, but given /// literally to the program. This means that shell syntax like quotes, - /// escaped characters, word splitting, glob patterns, variable substitution, etc. - /// have no effect. + /// escaped characters, word splitting, glob patterns, variable substitution, + /// etc. have no effect. /// /// <div class="warning"> /// - /// On Windows use caution with untrusted inputs. Most applications use the - /// standard convention for decoding arguments passed to them. These are safe to use with `arg`. - /// However some applications, such as `cmd.exe` and `.bat` files, use a non-standard way of decoding arguments - /// and are therefore vulnerable to malicious input. - /// In the case of `cmd.exe` this is especially important because a malicious argument can potentially run arbitrary shell commands. + /// On Windows, use caution with untrusted inputs. Most applications use the + /// standard convention for decoding arguments passed to them. These are safe to + /// use with `arg`. However, some applications such as `cmd.exe` and `.bat` files + /// use a non-standard way of decoding arguments. They are therefore vulnerable + /// to malicious input. + /// + /// In the case of `cmd.exe` this is especially important because a malicious + /// argument can potentially run arbitrary shell commands. /// /// See [Windows argument splitting][windows-args] for more details /// or [`raw_arg`] for manually implementing non-standard argument encoding. @@ -710,11 +713,14 @@ impl Command { /// /// <div class="warning"> /// - /// On Windows use caution with untrusted inputs. Most applications use the - /// standard convention for decoding arguments passed to them. These are safe to use with `args`. - /// However some applications, such as `cmd.exe` and `.bat` files, use a non-standard way of decoding arguments - /// and are therefore vulnerable to malicious input. - /// In the case of `cmd.exe` this is especially important because a malicious argument can potentially run arbitrary shell commands. + /// On Windows, use caution with untrusted inputs. Most applications use the + /// standard convention for decoding arguments passed to them. These are safe to + /// use with `arg`. However, some applications such as `cmd.exe` and `.bat` files + /// use a non-standard way of decoding arguments. They are therefore vulnerable + /// to malicious input. + /// + /// In the case of `cmd.exe` this is especially important because a malicious + /// argument can potentially run arbitrary shell commands. /// /// See [Windows argument splitting][windows-args] for more details /// or [`raw_arg`] for manually implementing non-standard argument encoding. diff --git a/library/std/src/sys/pal/hermit/alloc.rs b/library/std/src/sys/pal/hermit/alloc.rs index de550987a43..2cd0db90940 100644 --- a/library/std/src/sys/pal/hermit/alloc.rs +++ b/library/std/src/sys/pal/hermit/alloc.rs @@ -1,4 +1,4 @@ -use super::abi; +use super::hermit_abi; use crate::alloc::{GlobalAlloc, Layout, System}; use crate::ptr; @@ -6,11 +6,11 @@ use crate::ptr; unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - abi::malloc(layout.size(), layout.align()) + hermit_abi::malloc(layout.size(), layout.align()) } unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - let addr = abi::malloc(layout.size(), layout.align()); + let addr = hermit_abi::malloc(layout.size(), layout.align()); if !addr.is_null() { ptr::write_bytes(addr, 0x00, layout.size()); @@ -21,11 +21,11 @@ unsafe impl GlobalAlloc for System { #[inline] unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - abi::free(ptr, layout.size(), layout.align()) + hermit_abi::free(ptr, layout.size(), layout.align()) } #[inline] unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - abi::realloc(ptr, layout.size(), layout.align(), new_size) + hermit_abi::realloc(ptr, layout.size(), layout.align(), new_size) } } diff --git a/library/std/src/sys/pal/hermit/fd.rs b/library/std/src/sys/pal/hermit/fd.rs index 962577bb1ed..d7dab08cfbd 100644 --- a/library/std/src/sys/pal/hermit/fd.rs +++ b/library/std/src/sys/pal/hermit/fd.rs @@ -1,6 +1,6 @@ #![unstable(reason = "not public", issue = "none", feature = "fd")] -use super::abi; +use super::hermit_abi; use crate::io::{self, Read}; use crate::os::hermit::io::{FromRawFd, OwnedFd, RawFd}; use crate::sys::cvt; @@ -16,7 +16,8 @@ pub struct FileDesc { impl FileDesc { pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { - let result = cvt(unsafe { abi::read(self.fd.as_raw_fd(), buf.as_mut_ptr(), buf.len()) })?; + let result = + cvt(unsafe { hermit_abi::read(self.fd.as_raw_fd(), buf.as_mut_ptr(), buf.len()) })?; Ok(result as usize) } @@ -26,7 +27,8 @@ impl FileDesc { } pub fn write(&self, buf: &[u8]) -> io::Result<usize> { - let result = cvt(unsafe { abi::write(self.fd.as_raw_fd(), buf.as_ptr(), buf.len()) })?; + let result = + cvt(unsafe { hermit_abi::write(self.fd.as_raw_fd(), buf.as_ptr(), buf.len()) })?; Ok(result as usize) } @@ -49,8 +51,8 @@ impl FileDesc { unsupported() } - pub fn fstat(&self, stat: *mut abi::stat) -> io::Result<()> { - cvt(unsafe { abi::fstat(self.fd.as_raw_fd(), stat) })?; + pub fn fstat(&self, stat: *mut hermit_abi::stat) -> io::Result<()> { + cvt(unsafe { hermit_abi::fstat(self.fd.as_raw_fd(), stat) })?; Ok(()) } } diff --git a/library/std/src/sys/pal/hermit/fs.rs b/library/std/src/sys/pal/hermit/fs.rs index 6519cc22f1f..a4a16e6e86b 100644 --- a/library/std/src/sys/pal/hermit/fs.rs +++ b/library/std/src/sys/pal/hermit/fs.rs @@ -1,8 +1,8 @@ -use super::abi::{ +use super::fd::FileDesc; +use super::hermit_abi::{ self, dirent64, stat as stat_struct, DT_DIR, DT_LNK, DT_REG, DT_UNKNOWN, O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG, }; -use super::fd::FileDesc; use crate::ffi::{CStr, OsStr, OsString}; use crate::fmt; use crate::io::{self, Error, ErrorKind}; @@ -47,7 +47,7 @@ impl InnerReadDir { pub struct ReadDir { inner: Arc<InnerReadDir>, - pos: i64, + pos: usize, } impl ReadDir { @@ -197,38 +197,31 @@ impl Iterator for ReadDir { fn next(&mut self) -> Option<io::Result<DirEntry>> { let mut counter: usize = 0; - let mut offset: i64 = 0; + let mut offset: usize = 0; // loop over all directory entries and search the entry for the current position loop { // leave function, if the loop reaches the of the buffer (with all entries) - if offset >= self.inner.dir.len().try_into().unwrap() { + if offset >= self.inner.dir.len() { return None; } - let dir = unsafe { - &*(self.inner.dir.as_ptr().offset(offset.try_into().unwrap()) as *const dirent64) - }; + let dir = unsafe { &*(self.inner.dir.as_ptr().add(offset) as *const dirent64) }; - if counter == self.pos.try_into().unwrap() { + if counter == self.pos { self.pos += 1; // After dirent64, the file name is stored. d_reclen represents the length of the dirent64 // plus the length of the file name. Consequently, file name has a size of d_reclen minus // the size of dirent64. The file name is always a C string and terminated by `\0`. // Consequently, we are able to ignore the last byte. - let name_bytes = unsafe { - core::slice::from_raw_parts( - &dir.d_name as *const _ as *const u8, - dir.d_reclen as usize - core::mem::size_of::<dirent64>() - 1, - ) - .to_vec() - }; + let name_bytes = + unsafe { CStr::from_ptr(&dir.d_name as *const _ as *const i8).to_bytes() }; let entry = DirEntry { root: self.inner.root.clone(), ino: dir.d_ino, type_: dir.d_type as u32, - name: OsString::from_vec(name_bytes), + name: OsString::from_vec(name_bytes.to_vec()), }; return Some(Ok(entry)); @@ -237,7 +230,7 @@ impl Iterator for ReadDir { counter += 1; // move to the next dirent64, which is directly stored after the previous one - offset = offset + dir.d_off; + offset = offset + usize::from(dir.d_reclen); } } } @@ -365,7 +358,7 @@ impl File { mode = 0; } - let fd = unsafe { cvt(abi::open(path.as_ptr(), flags, mode))? }; + let fd = unsafe { cvt(hermit_abi::open(path.as_ptr(), flags, mode))? }; Ok(File(unsafe { FileDesc::from_raw_fd(fd as i32) })) } @@ -446,7 +439,7 @@ impl DirBuilder { pub fn mkdir(&self, path: &Path) -> io::Result<()> { run_path_with_cstr(path, &|path| { - cvt(unsafe { abi::mkdir(path.as_ptr(), self.mode) }).map(|_| ()) + cvt(unsafe { hermit_abi::mkdir(path.as_ptr(), self.mode) }).map(|_| ()) }) } @@ -508,7 +501,8 @@ impl FromRawFd for File { } pub fn readdir(path: &Path) -> io::Result<ReadDir> { - let fd_raw = run_path_with_cstr(path, &|path| cvt(unsafe { abi::opendir(path.as_ptr()) }))?; + let fd_raw = + run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::opendir(path.as_ptr()) }))?; let fd = unsafe { FileDesc::from_raw_fd(fd_raw as i32) }; let root = path.to_path_buf(); @@ -519,8 +513,9 @@ pub fn readdir(path: &Path) -> io::Result<ReadDir> { // reserve memory to receive all directory entries vec.resize(sz, 0); - let readlen = - unsafe { abi::getdents64(fd.as_raw_fd(), vec.as_mut_ptr() as *mut dirent64, sz) }; + let readlen = unsafe { + hermit_abi::getdents64(fd.as_raw_fd(), vec.as_mut_ptr() as *mut dirent64, sz) + }; if readlen > 0 { // shrink down to the minimal size vec.resize(readlen.try_into().unwrap(), 0); @@ -529,7 +524,7 @@ pub fn readdir(path: &Path) -> io::Result<ReadDir> { // if the buffer is too small, getdents64 returns EINVAL // otherwise, getdents64 returns an error number - if readlen != (-abi::errno::EINVAL).into() { + if readlen != (-hermit_abi::errno::EINVAL).into() { return Err(Error::from_raw_os_error(readlen.try_into().unwrap())); } @@ -547,7 +542,7 @@ pub fn readdir(path: &Path) -> io::Result<ReadDir> { } pub fn unlink(path: &Path) -> io::Result<()> { - run_path_with_cstr(path, &|path| cvt(unsafe { abi::unlink(path.as_ptr()) }).map(|_| ())) + run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::unlink(path.as_ptr()) }).map(|_| ())) } pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { @@ -559,7 +554,7 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { } pub fn rmdir(path: &Path) -> io::Result<()> { - run_path_with_cstr(path, &|path| cvt(unsafe { abi::rmdir(path.as_ptr()) }).map(|_| ())) + run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::rmdir(path.as_ptr()) }).map(|_| ())) } pub fn remove_dir_all(_path: &Path) -> io::Result<()> { @@ -581,7 +576,7 @@ pub fn link(_original: &Path, _link: &Path) -> io::Result<()> { pub fn stat(path: &Path) -> io::Result<FileAttr> { run_path_with_cstr(path, &|path| { let mut stat_val: stat_struct = unsafe { mem::zeroed() }; - cvt(unsafe { abi::stat(path.as_ptr(), &mut stat_val) })?; + cvt(unsafe { hermit_abi::stat(path.as_ptr(), &mut stat_val) })?; Ok(FileAttr::from_stat(stat_val)) }) } @@ -589,7 +584,7 @@ pub fn stat(path: &Path) -> io::Result<FileAttr> { pub fn lstat(path: &Path) -> io::Result<FileAttr> { run_path_with_cstr(path, &|path| { let mut stat_val: stat_struct = unsafe { mem::zeroed() }; - cvt(unsafe { abi::lstat(path.as_ptr(), &mut stat_val) })?; + cvt(unsafe { hermit_abi::lstat(path.as_ptr(), &mut stat_val) })?; Ok(FileAttr::from_stat(stat_val)) }) } diff --git a/library/std/src/sys/pal/hermit/futex.rs b/library/std/src/sys/pal/hermit/futex.rs index 427d8ff6f2e..571b2885658 100644 --- a/library/std/src/sys/pal/hermit/futex.rs +++ b/library/std/src/sys/pal/hermit/futex.rs @@ -1,4 +1,4 @@ -use super::abi; +use super::hermit_abi; use crate::ptr::null; use crate::sync::atomic::AtomicU32; use crate::time::Duration; @@ -8,32 +8,32 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) - // // Overflows are rounded up to an infinite timeout (None). let timespec = timeout.and_then(|dur| { - Some(abi::timespec { + Some(hermit_abi::timespec { tv_sec: dur.as_secs().try_into().ok()?, tv_nsec: dur.subsec_nanos().into(), }) }); let r = unsafe { - abi::futex_wait( + hermit_abi::futex_wait( futex.as_ptr(), expected, - timespec.as_ref().map_or(null(), |t| t as *const abi::timespec), - abi::FUTEX_RELATIVE_TIMEOUT, + timespec.as_ref().map_or(null(), |t| t as *const hermit_abi::timespec), + hermit_abi::FUTEX_RELATIVE_TIMEOUT, ) }; - r != -abi::errno::ETIMEDOUT + r != -hermit_abi::errno::ETIMEDOUT } #[inline] pub fn futex_wake(futex: &AtomicU32) -> bool { - unsafe { abi::futex_wake(futex.as_ptr(), 1) > 0 } + unsafe { hermit_abi::futex_wake(futex.as_ptr(), 1) > 0 } } #[inline] pub fn futex_wake_all(futex: &AtomicU32) { unsafe { - abi::futex_wake(futex.as_ptr(), i32::MAX); + hermit_abi::futex_wake(futex.as_ptr(), i32::MAX); } } diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs index 910935541bd..a64323a3a29 100644 --- a/library/std/src/sys/pal/hermit/mod.rs +++ b/library/std/src/sys/pal/hermit/mod.rs @@ -39,7 +39,7 @@ pub mod thread_local_key; pub mod time; use crate::io::ErrorKind; -use crate::os::hermit::abi; +use crate::os::hermit::hermit_abi; pub fn unsupported<T>() -> crate::io::Result<T> { Err(unsupported_err()) @@ -54,7 +54,7 @@ pub fn unsupported_err() -> crate::io::Error { pub fn abort_internal() -> ! { unsafe { - abi::abort(); + hermit_abi::abort(); } } @@ -62,7 +62,7 @@ pub fn hashmap_random_keys() -> (u64, u64) { let mut buf = [0; 16]; let mut slice = &mut buf[..]; while !slice.is_empty() { - let res = cvt(unsafe { abi::read_entropy(slice.as_mut_ptr(), slice.len(), 0) }) + let res = cvt(unsafe { hermit_abi::read_entropy(slice.as_mut_ptr(), slice.len(), 0) }) .expect("failed to generate random hashmap keys"); slice = &mut slice[res as usize..]; } @@ -109,31 +109,31 @@ pub unsafe extern "C" fn runtime_entry( let result = main(argc as isize, argv); run_dtors(); - abi::exit(result); + hermit_abi::exit(result); } #[inline] pub(crate) fn is_interrupted(errno: i32) -> bool { - errno == abi::errno::EINTR + errno == hermit_abi::errno::EINTR } pub fn decode_error_kind(errno: i32) -> ErrorKind { match errno { - abi::errno::EACCES => ErrorKind::PermissionDenied, - abi::errno::EADDRINUSE => ErrorKind::AddrInUse, - abi::errno::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, - abi::errno::EAGAIN => ErrorKind::WouldBlock, - abi::errno::ECONNABORTED => ErrorKind::ConnectionAborted, - abi::errno::ECONNREFUSED => ErrorKind::ConnectionRefused, - abi::errno::ECONNRESET => ErrorKind::ConnectionReset, - abi::errno::EEXIST => ErrorKind::AlreadyExists, - abi::errno::EINTR => ErrorKind::Interrupted, - abi::errno::EINVAL => ErrorKind::InvalidInput, - abi::errno::ENOENT => ErrorKind::NotFound, - abi::errno::ENOTCONN => ErrorKind::NotConnected, - abi::errno::EPERM => ErrorKind::PermissionDenied, - abi::errno::EPIPE => ErrorKind::BrokenPipe, - abi::errno::ETIMEDOUT => ErrorKind::TimedOut, + hermit_abi::errno::EACCES => ErrorKind::PermissionDenied, + hermit_abi::errno::EADDRINUSE => ErrorKind::AddrInUse, + hermit_abi::errno::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, + hermit_abi::errno::EAGAIN => ErrorKind::WouldBlock, + hermit_abi::errno::ECONNABORTED => ErrorKind::ConnectionAborted, + hermit_abi::errno::ECONNREFUSED => ErrorKind::ConnectionRefused, + hermit_abi::errno::ECONNRESET => ErrorKind::ConnectionReset, + hermit_abi::errno::EEXIST => ErrorKind::AlreadyExists, + hermit_abi::errno::EINTR => ErrorKind::Interrupted, + hermit_abi::errno::EINVAL => ErrorKind::InvalidInput, + hermit_abi::errno::ENOENT => ErrorKind::NotFound, + hermit_abi::errno::ENOTCONN => ErrorKind::NotConnected, + hermit_abi::errno::EPERM => ErrorKind::PermissionDenied, + hermit_abi::errno::EPIPE => ErrorKind::BrokenPipe, + hermit_abi::errno::ETIMEDOUT => ErrorKind::TimedOut, _ => ErrorKind::Uncategorized, } } diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs index 1f9affbf773..cc678123831 100644 --- a/library/std/src/sys/pal/hermit/os.rs +++ b/library/std/src/sys/pal/hermit/os.rs @@ -1,4 +1,4 @@ -use super::abi; +use super::hermit_abi; use crate::collections::HashMap; use crate::error::Error as StdError; use crate::ffi::{CStr, OsStr, OsString}; @@ -14,11 +14,11 @@ use crate::vec; use core::slice::memchr; pub fn errno() -> i32 { - unsafe { abi::get_errno() } + unsafe { hermit_abi::get_errno() } } pub fn error_string(errno: i32) -> String { - abi::error_string(errno).to_string() + hermit_abi::error_string(errno).to_string() } pub fn getcwd() -> io::Result<PathBuf> { @@ -197,10 +197,10 @@ pub fn home_dir() -> Option<PathBuf> { pub fn exit(code: i32) -> ! { unsafe { - abi::exit(code); + hermit_abi::exit(code); } } pub fn getpid() -> u32 { - unsafe { abi::getpid() } + unsafe { hermit_abi::getpid() } } diff --git a/library/std/src/sys/pal/hermit/stdio.rs b/library/std/src/sys/pal/hermit/stdio.rs index ac54385e8ce..777c57b391c 100644 --- a/library/std/src/sys/pal/hermit/stdio.rs +++ b/library/std/src/sys/pal/hermit/stdio.rs @@ -1,4 +1,4 @@ -use super::abi; +use super::hermit_abi; use crate::io; use crate::io::{IoSlice, IoSliceMut}; @@ -37,7 +37,7 @@ impl io::Write for Stdout { fn write(&mut self, data: &[u8]) -> io::Result<usize> { let len; - unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) } + unsafe { len = hermit_abi::write(1, data.as_ptr() as *const u8, data.len()) } if len < 0 { Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stdout is not able to print")) @@ -49,7 +49,7 @@ impl io::Write for Stdout { fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> { let len; - unsafe { len = abi::write(1, data.as_ptr() as *const u8, data.len()) } + unsafe { len = hermit_abi::write(1, data.as_ptr() as *const u8, data.len()) } if len < 0 { Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stdout is not able to print")) @@ -78,7 +78,7 @@ impl io::Write for Stderr { fn write(&mut self, data: &[u8]) -> io::Result<usize> { let len; - unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) } + unsafe { len = hermit_abi::write(2, data.as_ptr() as *const u8, data.len()) } if len < 0 { Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stderr is not able to print")) @@ -90,7 +90,7 @@ impl io::Write for Stderr { fn write_vectored(&mut self, data: &[IoSlice<'_>]) -> io::Result<usize> { let len; - unsafe { len = abi::write(2, data.as_ptr() as *const u8, data.len()) } + unsafe { len = hermit_abi::write(2, data.as_ptr() as *const u8, data.len()) } if len < 0 { Err(io::const_io_error!(io::ErrorKind::Uncategorized, "Stderr is not able to print")) diff --git a/library/std/src/sys/pal/hermit/thread.rs b/library/std/src/sys/pal/hermit/thread.rs index 4fe6b12a95b..b336dcd6860 100644 --- a/library/std/src/sys/pal/hermit/thread.rs +++ b/library/std/src/sys/pal/hermit/thread.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] -use super::abi; +use super::hermit_abi; use super::thread_local_dtor::run_dtors; use crate::ffi::CStr; use crate::io; @@ -9,7 +9,7 @@ use crate::num::NonZero; use crate::ptr; use crate::time::Duration; -pub type Tid = abi::Tid; +pub type Tid = hermit_abi::Tid; pub struct Thread { tid: Tid, @@ -27,10 +27,10 @@ impl Thread { core_id: isize, ) -> io::Result<Thread> { let p = Box::into_raw(Box::new(p)); - let tid = abi::spawn2( + let tid = hermit_abi::spawn2( thread_start, p.expose_provenance(), - abi::Priority::into(abi::NORMAL_PRIO), + hermit_abi::Priority::into(hermit_abi::NORMAL_PRIO), stack, core_id, ); @@ -62,7 +62,7 @@ impl Thread { #[inline] pub fn yield_now() { unsafe { - abi::yield_now(); + hermit_abi::yield_now(); } } @@ -74,13 +74,13 @@ impl Thread { #[inline] pub fn sleep(dur: Duration) { unsafe { - abi::usleep(dur.as_micros() as u64); + hermit_abi::usleep(dur.as_micros() as u64); } } pub fn join(self) { unsafe { - let _ = abi::join(self.tid); + let _ = hermit_abi::join(self.tid); } } @@ -98,5 +98,5 @@ impl Thread { } pub fn available_parallelism() -> io::Result<NonZero<usize>> { - unsafe { Ok(NonZero::new_unchecked(abi::get_processor_count())) } + unsafe { Ok(NonZero::new_unchecked(hermit_abi::get_processor_count())) } } diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs index d6f9e4c1476..2bf24462fa8 100644 --- a/library/std/src/sys/pal/hermit/time.rs +++ b/library/std/src/sys/pal/hermit/time.rs @@ -1,8 +1,6 @@ #![allow(dead_code)] -use super::abi; -use super::abi::timespec; -use super::abi::{CLOCK_MONOTONIC, CLOCK_REALTIME, NSEC_PER_SEC}; +use super::hermit_abi::{self, timespec, CLOCK_MONOTONIC, CLOCK_REALTIME, NSEC_PER_SEC}; use crate::cmp::Ordering; use crate::ops::{Add, AddAssign, Sub, SubAssign}; use crate::time::Duration; @@ -106,7 +104,8 @@ pub struct Instant(Timespec); impl Instant { pub fn now() -> Instant { let mut time: Timespec = Timespec::zero(); - let _ = unsafe { abi::clock_gettime(CLOCK_MONOTONIC, core::ptr::addr_of_mut!(time.t)) }; + let _ = + unsafe { hermit_abi::clock_gettime(CLOCK_MONOTONIC, core::ptr::addr_of_mut!(time.t)) }; Instant(time) } @@ -207,7 +206,8 @@ impl SystemTime { pub fn now() -> SystemTime { let mut time: Timespec = Timespec::zero(); - let _ = unsafe { abi::clock_gettime(CLOCK_REALTIME, core::ptr::addr_of_mut!(time.t)) }; + let _ = + unsafe { hermit_abi::clock_gettime(CLOCK_REALTIME, core::ptr::addr_of_mut!(time.t)) }; SystemTime(time) } diff --git a/library/std/src/sys/pal/unix/alloc.rs b/library/std/src/sys/pal/unix/alloc.rs index 9938c0bac25..2f908e3d0e9 100644 --- a/library/std/src/sys/pal/unix/alloc.rs +++ b/library/std/src/sys/pal/unix/alloc.rs @@ -59,51 +59,29 @@ unsafe impl GlobalAlloc for System { } cfg_if::cfg_if! { + // We use posix_memalign wherever possible, but not all targets have that function. if #[cfg(any( - target_os = "android", - target_os = "illumos", target_os = "redox", - target_os = "solaris", target_os = "espidf", target_os = "horizon", target_os = "vita", ))] { #[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 { - // C11 aligned_alloc requires that the size be a multiple of the alignment. - // Layout already checks that the size rounded up doesn't overflow isize::MAX. - let align = layout.align(); - let size = layout.size().next_multiple_of(align); - libc::aligned_alloc(align, 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. + // We prefer posix_memalign over aligned_malloc since with aligned_malloc, + // implementations are making almost arbitrary choices for which alignments are + // "supported", making it hard to use. For instance, some implementations require the + // size to be a multiple of the alignment (wasi emmalloc), while others require the + // alignment to be at least the pointer size (Illumos, macOS) -- which may or may not be + // standards-compliant, but that does not help us. + // posix_memalign only has one, clear requirement: 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/pal/unix/rand.rs b/library/std/src/sys/pal/unix/rand.rs index d8f227b4ef4..e6df109a6b8 100644 --- a/library/std/src/sys/pal/unix/rand.rs +++ b/library/std/src/sys/pal/unix/rand.rs @@ -59,7 +59,14 @@ mod imp { unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_NONBLOCK) } } - #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "freebsd", netbsd10))] + #[cfg(any( + target_os = "espidf", + target_os = "horizon", + target_os = "freebsd", + netbsd10, + target_os = "illumos", + target_os = "solaris" + ))] fn getrandom(buf: &mut [u8]) -> libc::ssize_t { unsafe { libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) } } @@ -83,6 +90,8 @@ mod imp { target_os = "horizon", target_os = "freebsd", target_os = "dragonfly", + target_os = "solaris", + target_os = "illumos", netbsd10 )))] fn getrandom_fill_bytes(_buf: &mut [u8]) -> bool { @@ -96,6 +105,8 @@ mod imp { target_os = "horizon", target_os = "freebsd", target_os = "dragonfly", + target_os = "solaris", + target_os = "illumos", netbsd10 ))] fn getrandom_fill_bytes(v: &mut [u8]) -> bool { |
