Add more from the std
This commit is contained in:
114
crates/std/src/sys/cmath.rs
Normal file
114
crates/std/src/sys/cmath.rs
Normal file
@@ -0,0 +1,114 @@
|
||||
#![cfg(not(test))]
|
||||
|
||||
// These symbols are all defined by `libm`,
|
||||
// or by `compiler-builtins` on unsupported platforms.
|
||||
unsafe extern "C" {
|
||||
pub safe fn acos(n: f64) -> f64;
|
||||
pub safe fn asin(n: f64) -> f64;
|
||||
pub safe fn atan(n: f64) -> f64;
|
||||
pub safe fn atan2(a: f64, b: f64) -> f64;
|
||||
pub safe fn cosh(n: f64) -> f64;
|
||||
pub safe fn expm1(n: f64) -> f64;
|
||||
pub safe fn expm1f(n: f32) -> f32;
|
||||
#[cfg_attr(target_env = "msvc", link_name = "_hypot")]
|
||||
pub safe fn hypot(x: f64, y: f64) -> f64;
|
||||
#[cfg_attr(target_env = "msvc", link_name = "_hypotf")]
|
||||
pub safe fn hypotf(x: f32, y: f32) -> f32;
|
||||
pub safe fn log1p(n: f64) -> f64;
|
||||
pub safe fn log1pf(n: f32) -> f32;
|
||||
pub safe fn sinh(n: f64) -> f64;
|
||||
pub safe fn tan(n: f64) -> f64;
|
||||
pub safe fn tanh(n: f64) -> f64;
|
||||
pub safe fn tgamma(n: f64) -> f64;
|
||||
pub safe fn tgammaf(n: f32) -> f32;
|
||||
pub safe fn lgamma_r(n: f64, s: &mut i32) -> f64;
|
||||
#[cfg(not(target_os = "aix"))]
|
||||
pub safe fn lgammaf_r(n: f32, s: &mut i32) -> f32;
|
||||
pub safe fn erf(n: f64) -> f64;
|
||||
pub safe fn erff(n: f32) -> f32;
|
||||
pub safe fn erfc(n: f64) -> f64;
|
||||
pub safe fn erfcf(n: f32) -> f32;
|
||||
|
||||
pub safe fn acosf128(n: f128) -> f128;
|
||||
pub safe fn asinf128(n: f128) -> f128;
|
||||
pub safe fn atanf128(n: f128) -> f128;
|
||||
pub safe fn atan2f128(a: f128, b: f128) -> f128;
|
||||
pub safe fn cbrtf128(n: f128) -> f128;
|
||||
pub safe fn coshf128(n: f128) -> f128;
|
||||
pub safe fn expm1f128(n: f128) -> f128;
|
||||
pub safe fn hypotf128(x: f128, y: f128) -> f128;
|
||||
pub safe fn log1pf128(n: f128) -> f128;
|
||||
pub safe fn sinhf128(n: f128) -> f128;
|
||||
pub safe fn tanf128(n: f128) -> f128;
|
||||
pub safe fn tanhf128(n: f128) -> f128;
|
||||
pub safe fn tgammaf128(n: f128) -> f128;
|
||||
pub safe fn lgammaf128_r(n: f128, s: &mut i32) -> f128;
|
||||
pub safe fn erff128(n: f128) -> f128;
|
||||
pub safe fn erfcf128(n: f128) -> f128;
|
||||
}
|
||||
|
||||
cfg_select! {
|
||||
all(target_os = "windows", target_env = "msvc", target_arch = "x86") => {
|
||||
// On 32-bit x86 MSVC these functions aren't defined, so we just define shims
|
||||
// which promote everything to f64, perform the calculation, and then demote
|
||||
// back to f32. While not precisely correct should be "correct enough" for now.
|
||||
#[inline]
|
||||
pub fn acosf(n: f32) -> f32 {
|
||||
f64::acos(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn asinf(n: f32) -> f32 {
|
||||
f64::asin(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn atan2f(n: f32, b: f32) -> f32 {
|
||||
f64::atan2(n as f64, b as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn atanf(n: f32) -> f32 {
|
||||
f64::atan(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn coshf(n: f32) -> f32 {
|
||||
f64::cosh(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sinhf(n: f32) -> f32 {
|
||||
f64::sinh(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn tanf(n: f32) -> f32 {
|
||||
f64::tan(n as f64) as f32
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn tanhf(n: f32) -> f32 {
|
||||
f64::tanh(n as f64) as f32
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
unsafe extern "C" {
|
||||
pub safe fn acosf(n: f32) -> f32;
|
||||
pub safe fn asinf(n: f32) -> f32;
|
||||
pub safe fn atan2f(a: f32, b: f32) -> f32;
|
||||
pub safe fn atanf(n: f32) -> f32;
|
||||
pub safe fn coshf(n: f32) -> f32;
|
||||
pub safe fn sinhf(n: f32) -> f32;
|
||||
pub safe fn tanf(n: f32) -> f32;
|
||||
pub safe fn tanhf(n: f32) -> f32;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// On AIX, we don't have lgammaf_r only the f64 version, so we can
|
||||
// use the f64 version lgamma_r
|
||||
#[cfg(target_os = "aix")]
|
||||
pub fn lgammaf_r(n: f32, s: &mut i32) -> f32 {
|
||||
lgamma_r(n.into(), s) as f32
|
||||
}
|
||||
62
crates/std/src/sys/configure_builtins.rs
Normal file
62
crates/std/src/sys/configure_builtins.rs
Normal file
@@ -0,0 +1,62 @@
|
||||
//! The configure builtins provides runtime support compiler-builtin features
|
||||
//! which require dynamic initialization to work as expected, e.g. aarch64
|
||||
//! outline-atomics.
|
||||
|
||||
/// Enable LSE atomic operations at startup, if supported.
|
||||
///
|
||||
/// Linker sections are based on what [`ctor`] does, with priorities to run slightly before user
|
||||
/// code:
|
||||
///
|
||||
/// - Apple uses the section `__mod_init_func`, `mod_init_funcs` is needed to set
|
||||
/// `S_MOD_INIT_FUNC_POINTERS`. There doesn't seem to be a way to indicate priorities.
|
||||
/// - Windows uses `.CRT$XCT`, which is run before user constructors (these should use `.CRT$XCU`).
|
||||
/// - ELF uses `.init_array` with a priority of 90, which runs before our `ARGV_INIT_ARRAY`
|
||||
/// initializer (priority 99). Both are within the 0-100 implementation-reserved range, per docs
|
||||
/// for the [`prio-ctor-dtor`] warning, and this matches compiler-rt's `CONSTRUCTOR_PRIORITY`.
|
||||
///
|
||||
/// To save startup time, the initializer is only run if outline atomic routines from
|
||||
/// compiler-builtins may be used. If LSE is known to be available then the calls are never
|
||||
/// emitted, and if we build the C intrinsics then it has its own initializer using the symbol
|
||||
/// `__aarch64_have_lse_atomics`.
|
||||
///
|
||||
/// Initialization is done in a global constructor to so we get the same behavior regardless of
|
||||
/// whether Rust's `init` is used, or if we are in a `dylib` or `no_main` situation (as opposed
|
||||
/// to doing it as part of pre-main startup). This also matches C implementations.
|
||||
///
|
||||
/// Ideally `core` would have something similar, but detecting the CPU features requires the
|
||||
/// auxiliary vector from the OS. We do the initialization in `std` rather than as part of
|
||||
/// `compiler-builtins` because a builtins->std dependency isn't possible, and inlining parts of
|
||||
/// `std-detect` would be much messier.
|
||||
///
|
||||
/// [`ctor`]: https://github.com/mmastrac/rust-ctor/blob/63382b833ddcbfb8b064f4e86bfa1ed4026ff356/shared/src/macros/mod.rs#L522-L534
|
||||
/// [`prio-ctor-dtor`]: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
|
||||
#[cfg(all(
|
||||
target_arch = "aarch64",
|
||||
target_feature = "outline-atomics",
|
||||
not(target_feature = "lse"),
|
||||
not(feature = "compiler-builtins-c"),
|
||||
))]
|
||||
#[used]
|
||||
#[cfg_attr(target_vendor = "apple", unsafe(link_section = "__DATA,__mod_init_func,mod_init_funcs"))]
|
||||
#[cfg_attr(target_os = "windows", unsafe(link_section = ".CRT$XCT"))]
|
||||
#[cfg_attr(
|
||||
not(any(target_vendor = "apple", target_os = "windows")),
|
||||
unsafe(link_section = ".init_array.90")
|
||||
)]
|
||||
static RUST_LSE_INIT: extern "C" fn() = {
|
||||
extern "C" fn init_lse() {
|
||||
use crate::arch;
|
||||
|
||||
// This is provided by compiler-builtins::aarch64_outline_atomics.
|
||||
unsafe extern "C" {
|
||||
fn __rust_enable_lse();
|
||||
}
|
||||
|
||||
if arch::is_aarch64_feature_detected!("lse") {
|
||||
unsafe {
|
||||
__rust_enable_lse();
|
||||
}
|
||||
}
|
||||
}
|
||||
init_lse
|
||||
};
|
||||
31
crates/std/src/sys/env/common.rs
vendored
Normal file
31
crates/std/src/sys/env/common.rs
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
use crate::ffi::OsString;
|
||||
use crate::{fmt, vec};
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
}
|
||||
|
||||
impl Env {
|
||||
pub(super) fn new(env: Vec<(OsString, OsString)>) -> Self {
|
||||
Env { iter: env.into_iter() }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Env {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_list().entries(self.iter.as_slice()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl !Send for Env {}
|
||||
impl !Sync for Env {}
|
||||
|
||||
impl Iterator for Env {
|
||||
type Item = (OsString, OsString);
|
||||
fn next(&mut self) -> Option<(OsString, OsString)> {
|
||||
self.iter.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
1
crates/std/src/sys/env/mod.rs
vendored
1
crates/std/src/sys/env/mod.rs
vendored
@@ -11,6 +11,7 @@
|
||||
target_os = "uefi",
|
||||
target_os = "wasi",
|
||||
target_os = "xous",
|
||||
target_os = "survos",
|
||||
))]
|
||||
mod common;
|
||||
|
||||
|
||||
426
crates/std/src/sys/env_consts.rs
Normal file
426
crates/std/src/sys/env_consts.rs
Normal file
@@ -0,0 +1,426 @@
|
||||
//! Constants associated with each target.
|
||||
|
||||
// Replaces the #[else] gate with #[cfg(not(any(…)))] of all the other gates.
|
||||
// This ensures that they must be mutually exclusive and do not have precedence
|
||||
// like cfg_select!.
|
||||
macro cfg_unordered(
|
||||
$(#[cfg($cfg:meta)] $os:item)*
|
||||
#[else] $fallback:item
|
||||
) {
|
||||
$(#[cfg($cfg)] $os)*
|
||||
#[cfg(not(any($($cfg),*)))] $fallback
|
||||
}
|
||||
|
||||
// Keep entries sorted alphabetically and mutually exclusive.
|
||||
|
||||
cfg_unordered! {
|
||||
|
||||
#[cfg(target_os = "aix")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "aix";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".a";
|
||||
pub const DLL_EXTENSION: &str = "a";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "android";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "cygwin")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "cygwin";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".dll";
|
||||
pub const DLL_EXTENSION: &str = "dll";
|
||||
pub const EXE_SUFFIX: &str = ".exe";
|
||||
pub const EXE_EXTENSION: &str = "exe";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "dragonfly";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "emscripten")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "emscripten";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = ".js";
|
||||
pub const EXE_EXTENSION: &str = "js";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "espidf")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "espidf";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "freebsd";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "fuchsia")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "fuchsia";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "haiku")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "haiku";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "hermit")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "hermit";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = "";
|
||||
pub const DLL_EXTENSION: &str = "";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "horizon")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "horizon";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = ".elf";
|
||||
pub const EXE_EXTENSION: &str = "elf";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "hurd")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "hurd";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "illumos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "illumos";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "ios")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "ios";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".dylib";
|
||||
pub const DLL_EXTENSION: &str = "dylib";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "l4re")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "l4re";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "linux";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "macos";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".dylib";
|
||||
pub const DLL_EXTENSION: &str = "dylib";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "netbsd")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "netbsd";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "nto")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "nto";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "nuttx")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "nuttx";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "openbsd")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "openbsd";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "redox";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "rtems")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "rtems";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".sgxs";
|
||||
pub const DLL_EXTENSION: &str = "sgxs";
|
||||
pub const EXE_SUFFIX: &str = ".sgxs";
|
||||
pub const EXE_EXTENSION: &str = "sgxs";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "solaris")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "solaris";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "solid_asp3")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "itron";
|
||||
pub const OS: &str = "solid";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "tvos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "tvos";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".dylib";
|
||||
pub const DLL_EXTENSION: &str = "dylib";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "uefi")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "uefi";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = "";
|
||||
pub const DLL_EXTENSION: &str = "";
|
||||
pub const EXE_SUFFIX: &str = ".efi";
|
||||
pub const EXE_EXTENSION: &str = "efi";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "vexos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "vexos";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = "";
|
||||
pub const DLL_EXTENSION: &str = "";
|
||||
pub const EXE_SUFFIX: &str = ".bin";
|
||||
pub const EXE_EXTENSION: &str = "bin";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "visionos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "visionos";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".dylib";
|
||||
pub const DLL_EXTENSION: &str = "dylib";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "vita")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "vita";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = ".elf";
|
||||
pub const EXE_EXTENSION: &str = "elf";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "vxworks")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "vxworks";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".so";
|
||||
pub const DLL_EXTENSION: &str = "so";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(all(target_family = "wasm", not(any(target_os = "emscripten", target_os = "linux"))))]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".wasm";
|
||||
pub const DLL_EXTENSION: &str = "wasm";
|
||||
pub const EXE_SUFFIX: &str = ".wasm";
|
||||
pub const EXE_EXTENSION: &str = "wasm";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "watchos")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "watchos";
|
||||
pub const DLL_PREFIX: &str = "lib";
|
||||
pub const DLL_SUFFIX: &str = ".dylib";
|
||||
pub const DLL_EXTENSION: &str = "dylib";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "windows";
|
||||
pub const OS: &str = "windows";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".dll";
|
||||
pub const DLL_EXTENSION: &str = "dll";
|
||||
pub const EXE_SUFFIX: &str = ".exe";
|
||||
pub const EXE_EXTENSION: &str = "exe";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "zkvm")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = ".elf";
|
||||
pub const DLL_EXTENSION: &str = "elf";
|
||||
pub const EXE_SUFFIX: &str = ".elf";
|
||||
pub const EXE_EXTENSION: &str = "elf";
|
||||
}
|
||||
|
||||
// The fallback when none of the other gates match.
|
||||
#[else]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "";
|
||||
pub const OS: &str = "";
|
||||
pub const DLL_PREFIX: &str = "";
|
||||
pub const DLL_SUFFIX: &str = "";
|
||||
pub const DLL_EXTENSION: &str = "";
|
||||
pub const EXE_SUFFIX: &str = "";
|
||||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
}
|
||||
143
crates/std/src/sys/exit.rs
Normal file
143
crates/std/src/sys/exit.rs
Normal file
@@ -0,0 +1,143 @@
|
||||
cfg_select! {
|
||||
target_os = "linux" => {
|
||||
/// Mitigation for <https://github.com/rust-lang/rust/issues/126600>
|
||||
///
|
||||
/// On glibc, `libc::exit` has been observed to not always be thread-safe.
|
||||
/// It is currently unclear whether that is a glibc bug or allowed by the standard.
|
||||
/// To mitigate this problem, we ensure that only one
|
||||
/// Rust thread calls `libc::exit` (or returns from `main`) by calling this function before
|
||||
/// calling `libc::exit` (or returning from `main`).
|
||||
///
|
||||
/// Technically, this is not enough to ensure soundness, since other code directly calling
|
||||
/// `libc::exit` will still race with this.
|
||||
///
|
||||
/// *This function does not itself call `libc::exit`.* This is so it can also be used
|
||||
/// to guard returning from `main`.
|
||||
///
|
||||
/// This function will return only the first time it is called in a process.
|
||||
///
|
||||
/// * If it is called again on the same thread as the first call, it will abort.
|
||||
/// * If it is called again on a different thread, it will wait in a loop
|
||||
/// (waiting for the process to exit).
|
||||
pub fn unique_thread_exit() {
|
||||
use crate::ffi::c_int;
|
||||
use crate::ptr;
|
||||
use crate::sync::atomic::AtomicPtr;
|
||||
use crate::sync::atomic::Ordering::{Acquire, Relaxed};
|
||||
|
||||
static EXITING_THREAD_ID: AtomicPtr<c_int> = AtomicPtr::new(ptr::null_mut());
|
||||
|
||||
// We use the address of `errno` as a cheap and safe way to identify
|
||||
// threads. As the C standard mandates that `errno` must have thread
|
||||
// storage duration, we can rely on its address not changing over the
|
||||
// lifetime of the thread. Additionally, accesses to `errno` are
|
||||
// async-signal-safe, so this function is available in all imaginable
|
||||
// circumstances.
|
||||
let this_thread_id = crate::sys::io::errno_location();
|
||||
match EXITING_THREAD_ID.compare_exchange(ptr::null_mut(), this_thread_id, Acquire, Relaxed) {
|
||||
Ok(_) => {
|
||||
// This is the first thread to call `unique_thread_exit`,
|
||||
// and this is the first time it is called. Continue exiting.
|
||||
}
|
||||
Err(exiting_thread_id) if exiting_thread_id == this_thread_id => {
|
||||
// This is the first thread to call `unique_thread_exit`,
|
||||
// but this is the second time it is called.
|
||||
// Abort the process.
|
||||
core::panicking::panic_nounwind("std::process::exit called re-entrantly")
|
||||
}
|
||||
Err(_) => {
|
||||
// This is not the first thread to call `unique_thread_exit`.
|
||||
// Pause until the process exits.
|
||||
loop {
|
||||
// Safety: libc::pause is safe to call.
|
||||
unsafe { libc::pause(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
/// Mitigation for <https://github.com/rust-lang/rust/issues/126600>
|
||||
///
|
||||
/// Mitigation is ***NOT*** implemented on this platform, either because this platform
|
||||
/// is not affected, or because mitigation is not yet implemented for this platform.
|
||||
#[cfg_attr(any(test, doctest), expect(dead_code))]
|
||||
pub fn unique_thread_exit() {
|
||||
// Mitigation not required on platforms where `exit` is thread-safe.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exit(code: i32) -> ! {
|
||||
cfg_select! {
|
||||
target_os = "hermit" => {
|
||||
unsafe { hermit_abi::exit(code) }
|
||||
}
|
||||
target_os = "linux" => {
|
||||
unsafe {
|
||||
unique_thread_exit();
|
||||
libc::exit(code)
|
||||
}
|
||||
}
|
||||
target_os = "motor" => {
|
||||
moto_rt::process::exit(code)
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
crate::sys::pal::abi::exit_with_code(code as _)
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
rtabort!("exit({}) called", code)
|
||||
}
|
||||
target_os = "teeos" => {
|
||||
let _ = code;
|
||||
panic!("TA should not call `exit`")
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
use r_efi::base::Status;
|
||||
|
||||
use crate::os::uefi::env;
|
||||
|
||||
if let (Some(boot_services), Some(handle)) =
|
||||
(env::boot_services(), env::try_image_handle())
|
||||
{
|
||||
let boot_services = boot_services.cast::<r_efi::efi::BootServices>();
|
||||
let _ = unsafe {
|
||||
((*boot_services.as_ptr()).exit)(
|
||||
handle.as_ptr(),
|
||||
Status::from_usize(code as usize),
|
||||
0,
|
||||
crate::ptr::null_mut(),
|
||||
)
|
||||
};
|
||||
}
|
||||
crate::intrinsics::abort()
|
||||
}
|
||||
any(
|
||||
target_family = "unix",
|
||||
target_os = "wasi",
|
||||
) => {
|
||||
unsafe { libc::exit(code as crate::ffi::c_int) }
|
||||
}
|
||||
target_os = "vexos" => {
|
||||
let _ = code;
|
||||
|
||||
unsafe {
|
||||
vex_sdk::vexSystemExitRequest();
|
||||
|
||||
loop {
|
||||
vex_sdk::vexTasksRun();
|
||||
}
|
||||
}
|
||||
}
|
||||
target_os = "windows" => {
|
||||
unsafe { crate::sys::pal::c::ExitProcess(code as u32) }
|
||||
}
|
||||
target_os = "xous" => {
|
||||
crate::os::xous::ffi::exit(code as u32)
|
||||
}
|
||||
_ => {
|
||||
let _ = code;
|
||||
crate::intrinsics::abort()
|
||||
}
|
||||
}
|
||||
}
|
||||
81
crates/std/src/sys/fs/common.rs
Normal file
81
crates/std/src/sys/fs/common.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
#![allow(dead_code)] // not used on all platforms
|
||||
|
||||
use crate::io::{self, Error, ErrorKind};
|
||||
use crate::path::{Path, PathBuf};
|
||||
use crate::sys::fs::{File, OpenOptions};
|
||||
use crate::sys::helpers::ignore_notfound;
|
||||
use crate::{fmt, fs};
|
||||
|
||||
pub(crate) const NOT_FILE_ERROR: Error = io::const_error!(
|
||||
ErrorKind::InvalidInput,
|
||||
"the source path is neither a regular file nor a symlink to a regular file",
|
||||
);
|
||||
|
||||
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
||||
let mut reader = fs::File::open(from)?;
|
||||
let metadata = reader.metadata()?;
|
||||
|
||||
if !metadata.is_file() {
|
||||
return Err(NOT_FILE_ERROR);
|
||||
}
|
||||
|
||||
let mut writer = fs::File::create(to)?;
|
||||
let perm = metadata.permissions();
|
||||
|
||||
let ret = io::copy(&mut reader, &mut writer)?;
|
||||
writer.set_permissions(perm)?;
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
|
||||
let filetype = fs::symlink_metadata(path)?.file_type();
|
||||
if filetype.is_symlink() { fs::remove_file(path) } else { remove_dir_all_recursive(path) }
|
||||
}
|
||||
|
||||
fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
|
||||
for child in fs::read_dir(path)? {
|
||||
let result: io::Result<()> = try {
|
||||
let child = child?;
|
||||
if child.file_type()?.is_dir() {
|
||||
remove_dir_all_recursive(&child.path())?;
|
||||
} else {
|
||||
fs::remove_file(&child.path())?;
|
||||
}
|
||||
};
|
||||
// ignore internal NotFound errors to prevent race conditions
|
||||
if let Err(err) = &result
|
||||
&& err.kind() != io::ErrorKind::NotFound
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
ignore_notfound(fs::remove_dir(path))
|
||||
}
|
||||
|
||||
pub fn exists(path: &Path) -> io::Result<bool> {
|
||||
match fs::metadata(path) {
|
||||
Ok(_) => Ok(true),
|
||||
Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Dir {
|
||||
path: PathBuf,
|
||||
}
|
||||
|
||||
impl Dir {
|
||||
pub fn open(path: &Path, _opts: &OpenOptions) -> io::Result<Self> {
|
||||
path.canonicalize().map(|path| Self { path })
|
||||
}
|
||||
|
||||
pub fn open_file(&self, path: &Path, opts: &OpenOptions) -> io::Result<File> {
|
||||
File::open(&self.path.join(path), &opts)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Dir {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Dir").field("path", &self.path).finish()
|
||||
}
|
||||
}
|
||||
173
crates/std/src/sys/fs/mod.rs
Normal file
173
crates/std/src/sys/fs/mod.rs
Normal file
@@ -0,0 +1,173 @@
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
use crate::io;
|
||||
use crate::path::{Path, PathBuf};
|
||||
|
||||
pub mod common;
|
||||
|
||||
cfg_select! {
|
||||
any(target_family = "unix", target_os = "wasi") => {
|
||||
mod unix;
|
||||
use unix as imp;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub use unix::{chown, fchown, lchown, mkfifo};
|
||||
#[cfg(not(any(target_os = "fuchsia", target_os = "wasi")))]
|
||||
pub use unix::chroot;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub(crate) use unix::debug_assert_fd_is_open;
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub(super) use unix::CachedFileMetadata;
|
||||
use crate::sys::helpers::run_path_with_cstr as with_native_path;
|
||||
}
|
||||
target_os = "windows" => {
|
||||
mod windows;
|
||||
use windows as imp;
|
||||
pub use windows::{symlink_inner, junction_point};
|
||||
use crate::sys::path::with_native_path;
|
||||
}
|
||||
target_os = "hermit" => {
|
||||
mod hermit;
|
||||
use hermit as imp;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
use motor as imp;
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod solid;
|
||||
use solid as imp;
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
mod uefi;
|
||||
use uefi as imp;
|
||||
}
|
||||
target_os = "vexos" => {
|
||||
mod vexos;
|
||||
use vexos as imp;
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
use unsupported as imp;
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Replace this with platform-specific path conversion functions.
|
||||
#[cfg(not(any(target_family = "unix", target_os = "windows", target_os = "wasi")))]
|
||||
#[inline]
|
||||
pub fn with_native_path<T>(path: &Path, f: &dyn Fn(&Path) -> io::Result<T>) -> io::Result<T> {
|
||||
f(path)
|
||||
}
|
||||
|
||||
pub use imp::{
|
||||
Dir, DirBuilder, DirEntry, File, FileAttr, FilePermissions, FileTimes, FileType, OpenOptions,
|
||||
ReadDir,
|
||||
};
|
||||
|
||||
pub fn read_dir(path: &Path) -> io::Result<ReadDir> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
imp::readdir(path)
|
||||
}
|
||||
|
||||
pub fn remove_file(path: &Path) -> io::Result<()> {
|
||||
with_native_path(path, &imp::unlink)
|
||||
}
|
||||
|
||||
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
|
||||
with_native_path(old, &|old| with_native_path(new, &|new| imp::rename(old, new)))
|
||||
}
|
||||
|
||||
pub fn remove_dir(path: &Path) -> io::Result<()> {
|
||||
with_native_path(path, &imp::rmdir)
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(not(windows))]
|
||||
return imp::remove_dir_all(path);
|
||||
#[cfg(windows)]
|
||||
with_native_path(path, &imp::remove_dir_all)
|
||||
}
|
||||
|
||||
pub fn read_link(path: &Path) -> io::Result<PathBuf> {
|
||||
with_native_path(path, &imp::readlink)
|
||||
}
|
||||
|
||||
pub fn symlink(original: &Path, link: &Path) -> io::Result<()> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(windows)]
|
||||
return imp::symlink(original, link);
|
||||
#[cfg(not(windows))]
|
||||
with_native_path(original, &|original| {
|
||||
with_native_path(link, &|link| imp::symlink(original, link))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn hard_link(original: &Path, link: &Path) -> io::Result<()> {
|
||||
with_native_path(original, &|original| {
|
||||
with_native_path(link, &|link| imp::link(original, link))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn metadata(path: &Path) -> io::Result<FileAttr> {
|
||||
with_native_path(path, &imp::stat)
|
||||
}
|
||||
|
||||
pub fn symlink_metadata(path: &Path) -> io::Result<FileAttr> {
|
||||
with_native_path(path, &imp::lstat)
|
||||
}
|
||||
|
||||
pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> {
|
||||
with_native_path(path, &|path| imp::set_perm(path, perm.clone()))
|
||||
}
|
||||
|
||||
#[cfg(all(unix, not(target_os = "vxworks")))]
|
||||
pub fn set_permissions_nofollow(path: &Path, perm: crate::fs::Permissions) -> io::Result<()> {
|
||||
use crate::fs::OpenOptions;
|
||||
|
||||
let mut options = OpenOptions::new();
|
||||
|
||||
// ESP-IDF and Horizon do not support O_NOFOLLOW, so we skip setting it.
|
||||
// Their filesystems do not have symbolic links, so no special handling is required.
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "horizon")))]
|
||||
{
|
||||
use crate::os::unix::fs::OpenOptionsExt;
|
||||
options.custom_flags(libc::O_NOFOLLOW);
|
||||
}
|
||||
|
||||
options.open(path)?.set_permissions(perm)
|
||||
}
|
||||
|
||||
#[cfg(any(not(unix), target_os = "vxworks"))]
|
||||
pub fn set_permissions_nofollow(_path: &Path, _perm: crate::fs::Permissions) -> io::Result<()> {
|
||||
crate::unimplemented!(
|
||||
"`set_permissions_nofollow` is currently only implemented on Unix platforms"
|
||||
)
|
||||
}
|
||||
|
||||
pub fn canonicalize(path: &Path) -> io::Result<PathBuf> {
|
||||
with_native_path(path, &imp::canonicalize)
|
||||
}
|
||||
|
||||
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(not(windows))]
|
||||
return imp::copy(from, to);
|
||||
#[cfg(windows)]
|
||||
with_native_path(from, &|from| with_native_path(to, &|to| imp::copy(from, to)))
|
||||
}
|
||||
|
||||
pub fn exists(path: &Path) -> io::Result<bool> {
|
||||
// FIXME: use with_native_path on all platforms
|
||||
#[cfg(not(windows))]
|
||||
return imp::exists(path);
|
||||
#[cfg(windows)]
|
||||
with_native_path(path, &imp::exists)
|
||||
}
|
||||
|
||||
pub fn set_times(path: &Path, times: FileTimes) -> io::Result<()> {
|
||||
with_native_path(path, &|path| imp::set_times(path, times.clone()))
|
||||
}
|
||||
|
||||
pub fn set_times_nofollow(path: &Path, times: FileTimes) -> io::Result<()> {
|
||||
with_native_path(path, &|path| imp::set_times_nofollow(path, times.clone()))
|
||||
}
|
||||
362
crates/std/src/sys/fs/unsupported.rs
Normal file
362
crates/std/src/sys/fs/unsupported.rs
Normal file
@@ -0,0 +1,362 @@
|
||||
use crate::ffi::OsString;
|
||||
use crate::fmt;
|
||||
use crate::fs::TryLockError;
|
||||
use crate::hash::{Hash, Hasher};
|
||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
|
||||
use crate::path::{Path, PathBuf};
|
||||
pub use crate::sys::fs::common::Dir;
|
||||
use crate::sys::time::SystemTime;
|
||||
use crate::sys::unsupported;
|
||||
|
||||
pub struct File(!);
|
||||
|
||||
pub struct FileAttr(!);
|
||||
|
||||
pub struct ReadDir(!);
|
||||
|
||||
pub struct DirEntry(!);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OpenOptions {}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
pub struct FileTimes {}
|
||||
|
||||
pub struct FilePermissions(!);
|
||||
|
||||
pub struct FileType(!);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DirBuilder {}
|
||||
|
||||
impl FileAttr {
|
||||
pub fn size(&self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn perm(&self) -> FilePermissions {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> FileType {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn modified(&self) -> io::Result<SystemTime> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn created(&self) -> io::Result<SystemTime> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FileAttr {
|
||||
fn clone(&self) -> FileAttr {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FilePermissions {
|
||||
pub fn readonly(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_readonly(&mut self, _readonly: bool) {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FilePermissions {
|
||||
fn clone(&self) -> FilePermissions {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for FilePermissions {
|
||||
fn eq(&self, _other: &FilePermissions) -> bool {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FilePermissions {}
|
||||
|
||||
impl fmt::Debug for FilePermissions {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FileTimes {
|
||||
pub fn set_accessed(&mut self, _t: SystemTime) {}
|
||||
pub fn set_modified(&mut self, _t: SystemTime) {}
|
||||
}
|
||||
|
||||
impl FileType {
|
||||
pub fn is_dir(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_file(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_symlink(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FileType {
|
||||
fn clone(&self) -> FileType {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Copy for FileType {}
|
||||
|
||||
impl PartialEq for FileType {
|
||||
fn eq(&self, _other: &FileType) -> bool {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FileType {}
|
||||
|
||||
impl Hash for FileType {
|
||||
fn hash<H: Hasher>(&self, _h: &mut H) {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for FileType {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ReadDir {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for ReadDir {
|
||||
type Item = io::Result<DirEntry>;
|
||||
|
||||
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DirEntry {
|
||||
pub fn path(&self) -> PathBuf {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn file_name(&self) -> OsString {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> io::Result<FileAttr> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> io::Result<FileType> {
|
||||
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> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn fsync(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn datasync(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn lock(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn lock_shared(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn try_lock(&self) -> Result<(), TryLockError> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn try_lock_shared(&self) -> Result<(), TryLockError> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn unlock(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn truncate(&self, _size: u64) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read_buf(&self, _cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Option<io::Result<u64>> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn tell(&self) -> io::Result<u64> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<File> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_times(&self, _times: FileTimes) -> io::Result<()> {
|
||||
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 {
|
||||
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 set_times(_p: &Path, _times: FileTimes) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn set_times_nofollow(_p: &Path, _times: FileTimes) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn rmdir(_p: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn exists(_path: &Path) -> io::Result<bool> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn symlink(_original: &Path, _link: &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()
|
||||
}
|
||||
@@ -1,5 +1,14 @@
|
||||
pub mod cmath;
|
||||
pub mod configure_builtins;
|
||||
pub mod env;
|
||||
pub mod env_consts;
|
||||
pub mod exit;
|
||||
pub mod os_str;
|
||||
pub mod path;
|
||||
pub mod sync;
|
||||
pub mod thread;
|
||||
pub mod time;
|
||||
// pub mod fs;
|
||||
|
||||
/// A trait for viewing representations from std types.
|
||||
#[cfg_attr(not(target_os = "linux"), allow(unused))]
|
||||
|
||||
28
crates/std/src/sys/path/mod.rs
Normal file
28
crates/std/src/sys/path/mod.rs
Normal file
@@ -0,0 +1,28 @@
|
||||
cfg_select! {
|
||||
target_os = "windows" => {
|
||||
mod windows;
|
||||
mod windows_prefix;
|
||||
pub use windows::*;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod sgx;
|
||||
pub use sgx::*;
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod unsupported_backslash;
|
||||
pub use unsupported_backslash::*;
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
mod uefi;
|
||||
pub use uefi::*;
|
||||
}
|
||||
target_os = "cygwin" => {
|
||||
mod cygwin;
|
||||
mod windows_prefix;
|
||||
pub use cygwin::*;
|
||||
}
|
||||
_ => {
|
||||
mod unix;
|
||||
pub use unix::*;
|
||||
}
|
||||
}
|
||||
72
crates/std/src/sys/path/unix.rs
Normal file
72
crates/std/src/sys/path/unix.rs
Normal file
@@ -0,0 +1,72 @@
|
||||
use crate::ffi::OsStr;
|
||||
use crate::path::{Path, PathBuf, Prefix};
|
||||
use crate::{env, io};
|
||||
|
||||
#[inline]
|
||||
pub fn is_sep_byte(b: u8) -> bool {
|
||||
b == b'/'
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_verbatim_sep(b: u8) -> bool {
|
||||
b == b'/'
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
|
||||
None
|
||||
}
|
||||
|
||||
pub const HAS_PREFIXES: bool = false;
|
||||
pub const MAIN_SEP_STR: &str = "/";
|
||||
pub const MAIN_SEP: char = '/';
|
||||
|
||||
/// Make a POSIX path absolute without changing its semantics.
|
||||
pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
|
||||
// This is mostly a wrapper around collecting `Path::components`, with
|
||||
// exceptions made where this conflicts with the POSIX specification.
|
||||
// See 4.13 Pathname Resolution, IEEE Std 1003.1-2017
|
||||
// https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_13
|
||||
|
||||
// Get the components, skipping the redundant leading "." component if it exists.
|
||||
let mut components = path.strip_prefix(".").unwrap_or(path).components();
|
||||
let path_os = path.as_os_str().as_encoded_bytes();
|
||||
|
||||
let mut normalized = if path.is_absolute() {
|
||||
// "If a pathname begins with two successive <slash> characters, the
|
||||
// first component following the leading <slash> characters may be
|
||||
// interpreted in an implementation-defined manner, although more than
|
||||
// two leading <slash> characters shall be treated as a single <slash>
|
||||
// character."
|
||||
if path_os.starts_with(b"//") && !path_os.starts_with(b"///") {
|
||||
components.next();
|
||||
PathBuf::from("//")
|
||||
} else {
|
||||
PathBuf::new()
|
||||
}
|
||||
} else {
|
||||
// env::current_dir()?
|
||||
todo!()
|
||||
};
|
||||
normalized.extend(components);
|
||||
|
||||
// "Interfaces using pathname resolution may specify additional constraints
|
||||
// when a pathname that does not name an existing directory contains at
|
||||
// least one non- <slash> character and contains one or more trailing
|
||||
// <slash> characters".
|
||||
// A trailing <slash> is also meaningful if "a symbolic link is
|
||||
// encountered during pathname resolution".
|
||||
if path_os.ends_with(b"/") {
|
||||
normalized.push("");
|
||||
}
|
||||
|
||||
Ok(normalized)
|
||||
}
|
||||
|
||||
pub(crate) fn is_absolute(path: &Path) -> bool {
|
||||
if cfg!(any(unix, target_os = "hermit", target_os = "wasi", target_os = "motor")) {
|
||||
path.has_root()
|
||||
} else {
|
||||
path.has_root() && path.prefix().is_some()
|
||||
}
|
||||
}
|
||||
44
crates/std/src/sys/sync/condvar/mod.rs
Normal file
44
crates/std/src/sys/sync/condvar/mod.rs
Normal file
@@ -0,0 +1,44 @@
|
||||
cfg_select! {
|
||||
any(
|
||||
all(target_os = "windows", not(target_vendor="win7")),
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "motor",
|
||||
target_os = "fuchsia",
|
||||
all(target_family = "wasm", target_feature = "atomics"),
|
||||
target_os = "hermit",
|
||||
) => {
|
||||
mod futex;
|
||||
pub use futex::Condvar;
|
||||
}
|
||||
any(
|
||||
target_family = "unix",
|
||||
target_os = "teeos",
|
||||
) => {
|
||||
mod pthread;
|
||||
pub use pthread::Condvar;
|
||||
}
|
||||
all(target_os = "windows", target_vendor = "win7") => {
|
||||
mod windows7;
|
||||
pub use windows7::Condvar;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod sgx;
|
||||
pub use sgx::Condvar;
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod itron;
|
||||
pub use itron::Condvar;
|
||||
}
|
||||
target_os = "xous" => {
|
||||
mod xous;
|
||||
pub use xous::Condvar;
|
||||
}
|
||||
_ => {
|
||||
mod no_threads;
|
||||
pub use no_threads::Condvar;
|
||||
}
|
||||
}
|
||||
27
crates/std/src/sys/sync/condvar/no_threads.rs
Normal file
27
crates/std/src/sys/sync/condvar/no_threads.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use crate::sys::sync::Mutex;
|
||||
use crate::thread::sleep;
|
||||
use crate::time::Duration;
|
||||
|
||||
pub struct Condvar {}
|
||||
|
||||
impl Condvar {
|
||||
#[inline]
|
||||
pub const fn new() -> Condvar {
|
||||
Condvar {}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn notify_one(&self) {}
|
||||
|
||||
#[inline]
|
||||
pub fn notify_all(&self) {}
|
||||
|
||||
pub unsafe fn wait(&self, _mutex: &Mutex) {
|
||||
panic!("condvar wait not supported")
|
||||
}
|
||||
|
||||
pub unsafe fn wait_timeout(&self, _mutex: &Mutex, dur: Duration) -> bool {
|
||||
sleep(dur);
|
||||
false
|
||||
}
|
||||
}
|
||||
5
crates/std/src/sys/sync/mod.rs
Normal file
5
crates/std/src/sys/sync/mod.rs
Normal file
@@ -0,0 +1,5 @@
|
||||
mod condvar;
|
||||
mod mutex;
|
||||
|
||||
pub use condvar::Condvar;
|
||||
pub use mutex::Mutex;
|
||||
47
crates/std/src/sys/sync/mutex/mod.rs
Normal file
47
crates/std/src/sys/sync/mutex/mod.rs
Normal file
@@ -0,0 +1,47 @@
|
||||
cfg_select! {
|
||||
any(
|
||||
all(target_os = "windows", not(target_vendor = "win7")),
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "motor",
|
||||
target_os = "dragonfly",
|
||||
all(target_family = "wasm", target_feature = "atomics"),
|
||||
target_os = "hermit",
|
||||
) => {
|
||||
mod futex;
|
||||
pub use futex::Mutex;
|
||||
}
|
||||
target_os = "fuchsia" => {
|
||||
mod fuchsia;
|
||||
pub use fuchsia::Mutex;
|
||||
}
|
||||
any(
|
||||
target_family = "unix",
|
||||
target_os = "teeos",
|
||||
) => {
|
||||
mod pthread;
|
||||
pub use pthread::Mutex;
|
||||
}
|
||||
all(target_os = "windows", target_vendor = "win7") => {
|
||||
mod windows7;
|
||||
pub use windows7::{Mutex, raw};
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod sgx;
|
||||
pub use sgx::Mutex;
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod itron;
|
||||
pub use itron::Mutex;
|
||||
}
|
||||
target_os = "xous" => {
|
||||
mod xous;
|
||||
pub use xous::Mutex;
|
||||
}
|
||||
_ => {
|
||||
mod no_threads;
|
||||
pub use no_threads::Mutex;
|
||||
}
|
||||
}
|
||||
31
crates/std/src/sys/sync/mutex/no_threads.rs
Normal file
31
crates/std/src/sys/sync/mutex/no_threads.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
use crate::cell::Cell;
|
||||
|
||||
pub struct Mutex {
|
||||
// This platform has no threads, so we can use a Cell here.
|
||||
locked: Cell<bool>,
|
||||
}
|
||||
|
||||
unsafe impl Send for Mutex {}
|
||||
unsafe impl Sync for Mutex {} // no threads on this platform
|
||||
|
||||
impl Mutex {
|
||||
#[inline]
|
||||
pub const fn new() -> Mutex {
|
||||
Mutex { locked: Cell::new(false) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn lock(&self) {
|
||||
assert_eq!(self.locked.replace(true), false, "cannot recursively acquire mutex");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn unlock(&self) {
|
||||
self.locked.set(false);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn try_lock(&self) -> bool {
|
||||
self.locked.replace(true) == false
|
||||
}
|
||||
}
|
||||
154
crates/std/src/sys/thread/mod.rs
Normal file
154
crates/std/src/sys/thread/mod.rs
Normal file
@@ -0,0 +1,154 @@
|
||||
cfg_select! {
|
||||
target_os = "hermit" => {
|
||||
mod hermit;
|
||||
pub use hermit::{Thread, available_parallelism, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{current_os_id, set_name};
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::*;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod sgx;
|
||||
pub use sgx::{Thread, current_os_id, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
|
||||
// SGX should protect in-enclave data from outside attackers, so there
|
||||
// must not be any data leakage to the OS, particularly no 1-1 mapping
|
||||
// between SGX thread names and OS thread names. Hence `set_name` is
|
||||
// intentionally a no-op.
|
||||
//
|
||||
// Note that the internally visible SGX thread name is already provided
|
||||
// by the platform-agnostic Rust thread code. This can be observed in
|
||||
// the [`std::thread::tests::test_named_thread`] test, which succeeds
|
||||
// as-is with the SGX target.
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{available_parallelism, set_name};
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod solid;
|
||||
pub use solid::{Thread, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{available_parallelism, current_os_id, set_name};
|
||||
}
|
||||
target_os = "teeos" => {
|
||||
mod teeos;
|
||||
pub use teeos::{Thread, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{available_parallelism, current_os_id, set_name};
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
mod uefi;
|
||||
pub use uefi::{available_parallelism, sleep};
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{Thread, current_os_id, set_name, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
}
|
||||
any(target_family = "unix", target_os = "wasi") => {
|
||||
mod unix;
|
||||
pub use unix::{Thread, available_parallelism, current_os_id, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
#[cfg(not(any(
|
||||
target_env = "newlib",
|
||||
target_os = "l4re",
|
||||
target_os = "emscripten",
|
||||
target_os = "redox",
|
||||
target_os = "hurd",
|
||||
target_os = "aix",
|
||||
target_os = "wasi",
|
||||
)))]
|
||||
pub use unix::set_name;
|
||||
#[cfg(any(
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "dragonfly",
|
||||
target_os = "hurd",
|
||||
target_os = "vxworks",
|
||||
target_os = "wasi",
|
||||
target_vendor = "apple",
|
||||
))]
|
||||
pub use unix::sleep_until;
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
#[cfg(any(
|
||||
target_env = "newlib",
|
||||
target_os = "l4re",
|
||||
target_os = "emscripten",
|
||||
target_os = "redox",
|
||||
target_os = "hurd",
|
||||
target_os = "aix",
|
||||
target_os = "wasi",
|
||||
))]
|
||||
pub use unsupported::set_name;
|
||||
}
|
||||
target_os = "vexos" => {
|
||||
mod vexos;
|
||||
pub use vexos::{sleep, sleep_until, yield_now};
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{Thread, available_parallelism, current_os_id, set_name, DEFAULT_MIN_STACK_SIZE};
|
||||
}
|
||||
all(target_family = "wasm", target_feature = "atomics") => {
|
||||
mod wasm;
|
||||
pub use wasm::sleep;
|
||||
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{Thread, available_parallelism, current_os_id, set_name, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
}
|
||||
target_os = "windows" => {
|
||||
mod windows;
|
||||
pub use windows::{Thread, available_parallelism, current_os_id, set_name, set_name_wide, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
}
|
||||
target_os = "xous" => {
|
||||
mod xous;
|
||||
pub use xous::{Thread, available_parallelism, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
|
||||
#[expect(dead_code)]
|
||||
mod unsupported;
|
||||
pub use unsupported::{current_os_id, set_name};
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
pub use unsupported::{Thread, available_parallelism, current_os_id, set_name, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "freebsd",
|
||||
target_os = "netbsd",
|
||||
target_os = "linux",
|
||||
target_os = "android",
|
||||
target_os = "solaris",
|
||||
target_os = "illumos",
|
||||
target_os = "dragonfly",
|
||||
target_os = "hurd",
|
||||
target_os = "vxworks",
|
||||
target_os = "wasi",
|
||||
target_vendor = "apple",
|
||||
target_os = "motor",
|
||||
target_os = "vexos"
|
||||
)))]
|
||||
pub fn sleep_until(deadline: crate::time::Instant) {
|
||||
use crate::time::Instant;
|
||||
|
||||
// The clock source used for `sleep` might not be the same used for `Instant`.
|
||||
// Since this function *must not* return before the deadline, we recheck the
|
||||
// time after every call to `sleep`. See #149935 for an example of this
|
||||
// occurring on older Windows systems.
|
||||
while let Some(delay) = deadline.checked_duration_since(Instant::now()) {
|
||||
// Sleep for the estimated time remaining until the deadline.
|
||||
//
|
||||
// If your system has a better way of estimating the delay time or
|
||||
// provides a way to sleep until an absolute time, specialize this
|
||||
// function for your system.
|
||||
sleep(delay);
|
||||
}
|
||||
}
|
||||
46
crates/std/src/sys/thread/unsupported.rs
Normal file
46
crates/std/src/sys/thread/unsupported.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
use crate::ffi::CStr;
|
||||
use crate::io;
|
||||
use crate::num::NonZero;
|
||||
use crate::thread::ThreadInit;
|
||||
use crate::time::Duration;
|
||||
|
||||
// Silence dead code warnings for the otherwise unused ThreadInit::init() call.
|
||||
#[expect(dead_code)]
|
||||
fn dummy_init_call(init: Box<ThreadInit>) {
|
||||
drop(init.init());
|
||||
}
|
||||
|
||||
pub struct Thread(!);
|
||||
|
||||
pub const DEFAULT_MIN_STACK_SIZE: usize = 64 * 1024;
|
||||
|
||||
impl Thread {
|
||||
// unsafe: see thread::Builder::spawn_unchecked for safety requirements
|
||||
pub unsafe fn new(_stack: usize, _init: Box<ThreadInit>) -> io::Result<Thread> {
|
||||
Err(io::Error::UNSUPPORTED_PLATFORM)
|
||||
}
|
||||
|
||||
pub fn join(self) {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn available_parallelism() -> io::Result<NonZero<usize>> {
|
||||
Err(io::Error::UNKNOWN_THREAD_COUNT)
|
||||
}
|
||||
|
||||
pub fn current_os_id() -> Option<u64> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn yield_now() {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
pub fn set_name(_name: &CStr) {
|
||||
// nope
|
||||
}
|
||||
|
||||
pub fn sleep(_dur: Duration) {
|
||||
panic!("can't sleep");
|
||||
}
|
||||
53
crates/std/src/sys/time/mod.rs
Normal file
53
crates/std/src/sys/time/mod.rs
Normal file
@@ -0,0 +1,53 @@
|
||||
cfg_select! {
|
||||
target_os = "hermit" => {
|
||||
mod hermit;
|
||||
use hermit as imp;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
use moto_rt::time as imp;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod sgx;
|
||||
use sgx as imp;
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod solid;
|
||||
use solid as imp;
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
mod uefi;
|
||||
use uefi as imp;
|
||||
}
|
||||
any(
|
||||
target_os = "teeos",
|
||||
target_family = "unix",
|
||||
target_os = "wasi",
|
||||
) => {
|
||||
mod unix;
|
||||
use unix as imp;
|
||||
}
|
||||
target_os = "vexos" => {
|
||||
mod vexos;
|
||||
#[expect(unused)]
|
||||
mod unsupported;
|
||||
|
||||
mod imp {
|
||||
pub use super::vexos::Instant;
|
||||
pub use super::unsupported::{SystemTime, UNIX_EPOCH};
|
||||
}
|
||||
}
|
||||
target_os = "windows" => {
|
||||
mod windows;
|
||||
use windows as imp;
|
||||
}
|
||||
target_os = "xous" => {
|
||||
mod xous;
|
||||
use xous as imp;
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
use unsupported as imp;
|
||||
}
|
||||
}
|
||||
|
||||
pub use imp::{Instant, SystemTime, UNIX_EPOCH};
|
||||
49
crates/std/src/sys/time/unsupported.rs
Normal file
49
crates/std/src/sys/time/unsupported.rs
Normal file
@@ -0,0 +1,49 @@
|
||||
use crate::time::Duration;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
pub struct Instant(Duration);
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
pub struct SystemTime(Duration);
|
||||
|
||||
pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
|
||||
|
||||
impl Instant {
|
||||
pub fn now() -> Instant {
|
||||
panic!("time not implemented on this platform")
|
||||
}
|
||||
|
||||
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
|
||||
self.0.checked_sub(other.0)
|
||||
}
|
||||
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant(self.0.checked_add(*other)?))
|
||||
}
|
||||
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant(self.0.checked_sub(*other)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl SystemTime {
|
||||
pub const MAX: SystemTime = SystemTime(Duration::MAX);
|
||||
|
||||
pub const MIN: SystemTime = SystemTime(Duration::ZERO);
|
||||
|
||||
pub fn now() -> SystemTime {
|
||||
panic!("time not implemented on this platform")
|
||||
}
|
||||
|
||||
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
|
||||
}
|
||||
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_add(*other)?))
|
||||
}
|
||||
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_sub(*other)?))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user