redesign of the interface to the unikernel HermitCore
- the old interface between HermitCore and the Rust Standard Library based on a small C library (newlib) - remove this interface and call directly the unikernel - remove the dependency to the HermitCore linker - use rust-lld as linker
This commit is contained in:
parent
7870050796
commit
c1e440a90f
51 changed files with 2388 additions and 451 deletions
|
@ -160,7 +160,7 @@ mod job {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "haiku", not(any(unix, windows))))]
|
||||
#[cfg(any(target_os = "haiku", target_os = "hermit", not(any(unix, windows))))]
|
||||
mod job {
|
||||
pub unsafe fn setup(_build: &mut crate::Build) {
|
||||
}
|
||||
|
|
|
@ -54,7 +54,8 @@ pub unsafe extern fn __rust_start_panic(_payload: usize) -> u32 {
|
|||
core::intrinsics::abort();
|
||||
}
|
||||
|
||||
#[cfg(all(target_vendor="fortanix", target_env="sgx"))]
|
||||
#[cfg(any(target_os = "hermit",
|
||||
all(target_vendor="fortanix", target_env="sgx")))]
|
||||
unsafe fn abort() -> ! {
|
||||
// call std::sys::abort_internal
|
||||
extern "C" { pub fn __rust_abort() -> !; }
|
||||
|
|
21
src/libpanic_unwind/hermit.rs
Normal file
21
src/libpanic_unwind/hermit.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
//! Unwinding for *hermit* target.
|
||||
//!
|
||||
//! Right now we don't support this, so this is just stubs.
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use core::ptr;
|
||||
use core::any::Any;
|
||||
|
||||
pub fn payload() -> *mut u8 {
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
pub unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
|
||||
extern "C" { pub fn __rust_abort() -> !; }
|
||||
__rust_abort();
|
||||
}
|
||||
|
||||
pub unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 {
|
||||
extern "C" { pub fn __rust_abort() -> !; }
|
||||
__rust_abort();
|
||||
}
|
|
@ -43,6 +43,9 @@ cfg_if::cfg_if! {
|
|||
} else if #[cfg(target_arch = "wasm32")] {
|
||||
#[path = "dummy.rs"]
|
||||
mod imp;
|
||||
} else if #[cfg(target_os = "hermit")] {
|
||||
#[path = "hermit.rs"]
|
||||
mod imp;
|
||||
} else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] {
|
||||
#[path = "dummy.rs"]
|
||||
mod imp;
|
||||
|
|
|
@ -1,26 +1,26 @@
|
|||
use crate::spec::{LinkArgs, LinkerFlavor, PanicStrategy, TargetOptions};
|
||||
use crate::spec::{LldFlavor, LinkArgs, LinkerFlavor, PanicStrategy, TargetOptions};
|
||||
use std::default::Default;
|
||||
|
||||
pub fn opts() -> TargetOptions {
|
||||
let mut args = LinkArgs::new();
|
||||
args.insert(LinkerFlavor::Gcc, vec![
|
||||
"-Wl,-Bstatic".to_string(),
|
||||
"-Wl,--no-dynamic-linker".to_string(),
|
||||
"-Wl,--gc-sections".to_string(),
|
||||
"-Wl,--as-needed".to_string(),
|
||||
let mut pre_link_args = LinkArgs::new();
|
||||
pre_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), vec![
|
||||
"--build-id".to_string(),
|
||||
"--hash-style=gnu".to_string(),
|
||||
"--Bstatic".to_string(),
|
||||
]);
|
||||
|
||||
TargetOptions {
|
||||
linker: Some("rust-lld".to_owned()),
|
||||
executables: true,
|
||||
has_elf_tls: true,
|
||||
linker_is_gnu: true,
|
||||
no_default_libraries: false,
|
||||
pre_link_args,
|
||||
no_default_libraries: true,
|
||||
panic_strategy: PanicStrategy::Abort,
|
||||
position_independent_executables: false,
|
||||
pre_link_args: args,
|
||||
position_independent_executables: true,
|
||||
relocation_model: "static".to_string(),
|
||||
target_family: Some("unix".to_string()),
|
||||
tls_model: "local-exec".to_string(),
|
||||
target_family: None,
|
||||
tls_model: "initial-exec".to_string(),
|
||||
.. Default::default()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use crate::spec::{LinkerFlavor, Target, TargetResult};
|
||||
use crate::spec::{LldFlavor, LinkerFlavor, Target, TargetResult};
|
||||
|
||||
pub fn target() -> TargetResult {
|
||||
let mut base = super::hermit_base::opts();
|
||||
base.cpu = "x86-64".to_string();
|
||||
base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
|
||||
base.linker = Some("x86_64-hermit-gcc".to_string());
|
||||
base.max_atomic_width = Some(64);
|
||||
base.features = "+rdrnd,+rdseed".to_string();
|
||||
base.stack_probes = true;
|
||||
|
||||
Ok(Target {
|
||||
llvm_target: "x86_64-unknown-hermit".to_string(),
|
||||
|
@ -17,7 +17,7 @@ pub fn target() -> TargetResult {
|
|||
target_os: "hermit".to_string(),
|
||||
target_env: String::new(),
|
||||
target_vendor: "unknown".to_string(),
|
||||
linker_flavor: LinkerFlavor::Gcc,
|
||||
linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld),
|
||||
options: base,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -346,6 +346,7 @@ impl<'a> fmt::Display for Html<'a> {
|
|||
"freebsd" => "FreeBSD",
|
||||
"fuchsia" => "Fuchsia",
|
||||
"haiku" => "Haiku",
|
||||
"hermit" => "HermitCore",
|
||||
"ios" => "iOS",
|
||||
"l4re" => "L4Re",
|
||||
"linux" => "Linux",
|
||||
|
|
|
@ -54,5 +54,7 @@ fn main() {
|
|||
}
|
||||
println!("cargo:rustc-link-lib=c");
|
||||
println!("cargo:rustc-link-lib=compiler_rt");
|
||||
} else if target.contains("hermit") {
|
||||
println!("cargo:rustc-link-lib=hermit");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,377 +0,0 @@
|
|||
#![stable(feature = "metadata_ext", since = "1.1.0")]
|
||||
|
||||
use crate::fs::Metadata;
|
||||
use crate::sys_common::AsInner;
|
||||
|
||||
#[allow(deprecated)]
|
||||
use crate::os::hermit::raw;
|
||||
|
||||
/// OS-specific extensions to [`fs::Metadata`].
|
||||
///
|
||||
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
|
||||
#[stable(feature = "metadata_ext", since = "1.1.0")]
|
||||
pub trait MetadataExt {
|
||||
/// Gain a reference to the underlying `stat` structure which contains
|
||||
/// the raw information returned by the OS.
|
||||
///
|
||||
/// The contents of the returned [`stat`] are **not** consistent across
|
||||
/// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the
|
||||
/// cross-Unix abstractions contained within the raw stat.
|
||||
///
|
||||
/// [`stat`]: ../../../../std/os/linux/raw/struct.stat.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// let stat = meta.as_raw_stat();
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext", since = "1.1.0")]
|
||||
#[rustc_deprecated(since = "1.8.0",
|
||||
reason = "deprecated in favor of the accessor \
|
||||
methods of this trait")]
|
||||
#[allow(deprecated)]
|
||||
fn as_raw_stat(&self) -> &raw::stat;
|
||||
|
||||
/// Returns the device ID on which this file resides.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_dev());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_dev(&self) -> u64;
|
||||
/// Returns the inode number.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_ino());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_ino(&self) -> u64;
|
||||
/// Returns the file type and mode.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_mode());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_mode(&self) -> u32;
|
||||
/// Returns the number of hard links to file.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_nlink());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_nlink(&self) -> u64;
|
||||
/// Returns the user ID of the file owner.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_uid());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_uid(&self) -> u32;
|
||||
/// Returns the group ID of the file owner.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_gid());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_gid(&self) -> u32;
|
||||
/// Returns the device ID that this file represents. Only relevant for special file.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_rdev());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_rdev(&self) -> u64;
|
||||
/// Returns the size of the file (if it is a regular file or a symbolic link) in bytes.
|
||||
///
|
||||
/// The size of a symbolic link is the length of the pathname it contains,
|
||||
/// without a terminating null byte.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_size());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_size(&self) -> u64;
|
||||
/// Returns the last access time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_atime());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_atime(&self) -> i64;
|
||||
/// Returns the last access time, nano seconds part.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_atime_nsec());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_atime_nsec(&self) -> i64;
|
||||
/// Returns the last modification time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_mtime());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_mtime(&self) -> i64;
|
||||
/// Returns the last modification time, nano seconds part.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_mtime_nsec());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_mtime_nsec(&self) -> i64;
|
||||
/// Returns the last status change time.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_ctime());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_ctime(&self) -> i64;
|
||||
/// Returns the last status change time, nano seconds part.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_ctime_nsec());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_ctime_nsec(&self) -> i64;
|
||||
/// Returns the "preferred" blocksize for efficient filesystem I/O.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_blksize());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_blksize(&self) -> u64;
|
||||
/// Returns the number of blocks allocated to the file, 512-byte units.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::os::linux::fs::MetadataExt;
|
||||
///
|
||||
/// fn main() -> io::Result<()> {
|
||||
/// let meta = fs::metadata("some_file")?;
|
||||
/// println!("{}", meta.st_blocks());
|
||||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "metadata_ext2", since = "1.8.0")]
|
||||
fn st_blocks(&self) -> u64;
|
||||
}
|
||||
|
||||
#[stable(feature = "metadata_ext", since = "1.1.0")]
|
||||
impl MetadataExt for Metadata {
|
||||
#[allow(deprecated)]
|
||||
fn as_raw_stat(&self) -> &raw::stat {
|
||||
unsafe {
|
||||
&*(self.as_inner().as_inner() as *const libc::stat64
|
||||
as *const raw::stat)
|
||||
}
|
||||
}
|
||||
fn st_dev(&self) -> u64 {
|
||||
self.as_inner().as_inner().st_dev as u64
|
||||
}
|
||||
fn st_ino(&self) -> u64 {
|
||||
self.as_inner().as_inner().st_ino as u64
|
||||
}
|
||||
fn st_mode(&self) -> u32 {
|
||||
self.as_inner().as_inner().st_mode as u32
|
||||
}
|
||||
fn st_nlink(&self) -> u64 {
|
||||
self.as_inner().as_inner().st_nlink as u64
|
||||
}
|
||||
fn st_uid(&self) -> u32 {
|
||||
self.as_inner().as_inner().st_uid as u32
|
||||
}
|
||||
fn st_gid(&self) -> u32 {
|
||||
self.as_inner().as_inner().st_gid as u32
|
||||
}
|
||||
fn st_rdev(&self) -> u64 {
|
||||
self.as_inner().as_inner().st_rdev as u64
|
||||
}
|
||||
fn st_size(&self) -> u64 {
|
||||
self.as_inner().as_inner().st_size as u64
|
||||
}
|
||||
fn st_atime(&self) -> i64 {
|
||||
self.as_inner().as_inner().st_atime as i64
|
||||
}
|
||||
fn st_atime_nsec(&self) -> i64 {
|
||||
self.as_inner().as_inner().st_atime_nsec as i64
|
||||
}
|
||||
fn st_mtime(&self) -> i64 {
|
||||
self.as_inner().as_inner().st_mtime as i64
|
||||
}
|
||||
fn st_mtime_nsec(&self) -> i64 {
|
||||
self.as_inner().as_inner().st_mtime_nsec as i64
|
||||
}
|
||||
fn st_ctime(&self) -> i64 {
|
||||
self.as_inner().as_inner().st_ctime as i64
|
||||
}
|
||||
fn st_ctime_nsec(&self) -> i64 {
|
||||
self.as_inner().as_inner().st_ctime_nsec as i64
|
||||
}
|
||||
fn st_blksize(&self) -> u64 {
|
||||
self.as_inner().as_inner().st_blksize as u64
|
||||
}
|
||||
fn st_blocks(&self) -> u64 {
|
||||
self.as_inner().as_inner().st_blocks as u64
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
//! HermitCore-specific definitions
|
||||
|
||||
#![stable(feature = "raw_ext", since = "1.1.0")]
|
||||
|
||||
pub mod raw;
|
||||
pub mod fs;
|
|
@ -1,17 +0,0 @@
|
|||
//! HermitCore-specific raw type definitions
|
||||
|
||||
#![stable(feature = "raw_ext", since = "1.1.0")]
|
||||
#![rustc_deprecated(since = "1.8.0",
|
||||
reason = "these type aliases are no longer supported by \
|
||||
the standard library, the `libc` crate on \
|
||||
crates.io should be used instead for the correct \
|
||||
definitions")]
|
||||
#![allow(deprecated)]
|
||||
#![allow(missing_debug_implementations)]
|
||||
|
||||
#[stable(feature = "pthread_t", since = "1.8.0")]
|
||||
pub use libc::pthread_t;
|
||||
|
||||
#[doc(inline)]
|
||||
#[stable(feature = "raw_ext", since = "1.1.0")]
|
||||
pub use libc::{dev_t, mode_t, off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};
|
|
@ -49,7 +49,6 @@ cfg_if::cfg_if! {
|
|||
#[cfg(target_os = "solaris")] pub mod solaris;
|
||||
#[cfg(target_os = "emscripten")] pub mod emscripten;
|
||||
#[cfg(target_os = "fuchsia")] pub mod fuchsia;
|
||||
#[cfg(target_os = "hermit")] pub mod hermit;
|
||||
#[cfg(target_os = "redox")] pub mod redox;
|
||||
#[cfg(target_os = "wasi")] pub mod wasi;
|
||||
#[cfg(target_os = "vxworks")] pub mod vxworks;
|
||||
|
|
|
@ -59,7 +59,6 @@ fn lang_start_internal(main: &(dyn Fn() -> i32 + Sync + crate::panic::RefUnwindS
|
|||
#[cfg(not(test))]
|
||||
#[lang = "start"]
|
||||
fn lang_start<T: crate::process::Termination + 'static>
|
||||
(main: fn() -> T, argc: isize, argv: *const *const u8) -> isize
|
||||
{
|
||||
(main: fn() -> T, argc: isize, argv: *const *const u8) -> isize {
|
||||
lang_start_internal(&move || main().report(), argc, argv)
|
||||
}
|
||||
|
|
40
src/libstd/sys/hermit/alloc.rs
Normal file
40
src/libstd/sys/hermit/alloc.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
use crate::alloc::{GlobalAlloc, Layout, System};
|
||||
use crate::ptr;
|
||||
|
||||
extern "C" {
|
||||
fn sys_malloc(size: usize, align: usize) -> *mut u8;
|
||||
fn sys_realloc(ptr: *mut u8, size: usize, align: usize, new_size: usize) -> *mut u8;
|
||||
fn sys_free(ptr: *mut u8, size: usize, align: usize);
|
||||
}
|
||||
|
||||
#[stable(feature = "alloc_system_type", since = "1.28.0")]
|
||||
unsafe impl GlobalAlloc for System {
|
||||
#[inline]
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||
sys_malloc(layout.size(), layout.align())
|
||||
}
|
||||
|
||||
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
|
||||
let addr = sys_malloc(layout.size(), layout.align());
|
||||
|
||||
if !addr.is_null() {
|
||||
ptr::write_bytes(
|
||||
addr,
|
||||
0x00,
|
||||
layout.size()
|
||||
);
|
||||
}
|
||||
|
||||
addr
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||
sys_free(ptr, layout.size(), layout.align())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
||||
sys_realloc(ptr, layout.size(), layout.align(), new_size)
|
||||
}
|
||||
}
|
82
src/libstd/sys/hermit/args.rs
Normal file
82
src/libstd/sys/hermit/args.rs
Normal file
|
@ -0,0 +1,82 @@
|
|||
use crate::ffi::OsString;
|
||||
use crate::marker::PhantomData;
|
||||
use crate::vec;
|
||||
|
||||
/// One-time global initialization.
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8) { imp::init(argc, argv) }
|
||||
|
||||
/// One-time global cleanup.
|
||||
pub unsafe fn cleanup() { imp::cleanup() }
|
||||
|
||||
/// Returns the command line arguments
|
||||
pub fn args() -> Args {
|
||||
imp::args()
|
||||
}
|
||||
|
||||
pub struct Args {
|
||||
iter: vec::IntoIter<OsString>,
|
||||
_dont_send_or_sync_me: PhantomData<*mut ()>,
|
||||
}
|
||||
|
||||
impl Args {
|
||||
pub fn inner_debug(&self) -> &[OsString] {
|
||||
self.iter.as_slice()
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for Args {
|
||||
type Item = OsString;
|
||||
fn next(&mut self) -> Option<OsString> { self.iter.next() }
|
||||
fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
|
||||
}
|
||||
|
||||
impl ExactSizeIterator for Args {
|
||||
fn len(&self) -> usize { self.iter.len() }
|
||||
}
|
||||
|
||||
impl DoubleEndedIterator for Args {
|
||||
fn next_back(&mut self) -> Option<OsString> { self.iter.next_back() }
|
||||
}
|
||||
|
||||
mod imp {
|
||||
use crate::sys_common::os_str_bytes::*;
|
||||
use crate::ptr;
|
||||
use crate::ffi::{CStr, OsString};
|
||||
use crate::marker::PhantomData;
|
||||
use super::Args;
|
||||
|
||||
use crate::sys_common::mutex::Mutex;
|
||||
|
||||
static mut ARGC: isize = 0;
|
||||
static mut ARGV: *const *const u8 = ptr::null();
|
||||
static LOCK: Mutex = Mutex::new();
|
||||
|
||||
pub unsafe fn init(argc: isize, argv: *const *const u8) {
|
||||
let _guard = LOCK.lock();
|
||||
ARGC = argc;
|
||||
ARGV = argv;
|
||||
}
|
||||
|
||||
pub unsafe fn cleanup() {
|
||||
let _guard = LOCK.lock();
|
||||
ARGC = 0;
|
||||
ARGV = ptr::null();
|
||||
}
|
||||
|
||||
pub fn args() -> Args {
|
||||
Args {
|
||||
iter: clone().into_iter(),
|
||||
_dont_send_or_sync_me: PhantomData
|
||||
}
|
||||
}
|
||||
|
||||
fn clone() -> Vec<OsString> {
|
||||
unsafe {
|
||||
let _guard = LOCK.lock();
|
||||
(0..ARGC).map(|i| {
|
||||
let cstr = CStr::from_ptr(*ARGV.offset(i) as *const i8);
|
||||
OsStringExt::from_vec(cstr.to_bytes().to_vec())
|
||||
}).collect()
|
||||
}
|
||||
}
|
||||
}
|
29
src/libstd/sys/hermit/cmath.rs
Normal file
29
src/libstd/sys/hermit/cmath.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
// These symbols are all defined in `compiler-builtins`
|
||||
extern {
|
||||
pub fn acos(n: f64) -> f64;
|
||||
pub fn acosf(n: f32) -> f32;
|
||||
pub fn asin(n: f64) -> f64;
|
||||
pub fn asinf(n: f32) -> f32;
|
||||
pub fn atan(n: f64) -> f64;
|
||||
pub fn atan2(a: f64, b: f64) -> f64;
|
||||
pub fn atan2f(a: f32, b: f32) -> f32;
|
||||
pub fn atanf(n: f32) -> f32;
|
||||
pub fn cbrt(n: f64) -> f64;
|
||||
pub fn cbrtf(n: f32) -> f32;
|
||||
pub fn cosh(n: f64) -> f64;
|
||||
pub fn coshf(n: f32) -> f32;
|
||||
pub fn expm1(n: f64) -> f64;
|
||||
pub fn expm1f(n: f32) -> f32;
|
||||
pub fn fdim(a: f64, b: f64) -> f64;
|
||||
pub fn fdimf(a: f32, b: f32) -> f32;
|
||||
pub fn hypot(x: f64, y: f64) -> f64;
|
||||
pub fn hypotf(x: f32, y: f32) -> f32;
|
||||
pub fn log1p(n: f64) -> f64;
|
||||
pub fn log1pf(n: f32) -> f32;
|
||||
pub fn sinh(n: f64) -> f64;
|
||||
pub fn sinhf(n: f32) -> f32;
|
||||
pub fn tan(n: f64) -> f64;
|
||||
pub fn tanf(n: f32) -> f32;
|
||||
pub fn tanh(n: f64) -> f64;
|
||||
pub fn tanhf(n: f32) -> f32;
|
||||
}
|
68
src/libstd/sys/hermit/condvar.rs
Normal file
68
src/libstd/sys/hermit/condvar.rs
Normal file
|
@ -0,0 +1,68 @@
|
|||
use crate::cmp;
|
||||
use crate::sys::mutex::Mutex;
|
||||
use crate::time::Duration;
|
||||
|
||||
pub struct Condvar {
|
||||
identifier: usize,
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn sys_notify(id: usize, count: i32) -> i32;
|
||||
fn sys_add_queue(id: usize, timeout_ns: i64) -> i32;
|
||||
fn sys_wait(id: usize) -> i32;
|
||||
fn sys_destroy_queue(id: usize) -> i32;
|
||||
}
|
||||
|
||||
impl Condvar {
|
||||
pub const fn new() -> Condvar {
|
||||
Condvar { identifier: 0 }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn init(&mut self) {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
pub unsafe fn notify_one(&self) {
|
||||
let _ = sys_notify(self.id(), 1);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn notify_all(&self) {
|
||||
let _ = sys_notify(self.id(), -1 /* =all */);
|
||||
}
|
||||
|
||||
pub unsafe fn wait(&self, mutex: &Mutex) {
|
||||
// add current task to the wait queue
|
||||
let _ = sys_add_queue(self.id(), -1 /* no timeout */);
|
||||
mutex.unlock();
|
||||
let _ = sys_wait(self.id());
|
||||
mutex.lock();
|
||||
}
|
||||
|
||||
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
|
||||
let nanos = dur.as_nanos();
|
||||
let nanos = cmp::min(i64::max_value() as u128, nanos);
|
||||
|
||||
// add current task to the wait queue
|
||||
let _ = sys_add_queue(self.id(), nanos as i64);
|
||||
|
||||
mutex.unlock();
|
||||
// If the return value is !0 then a timeout happened, so we return
|
||||
// `false` as we weren't actually notified.
|
||||
let ret = sys_wait(self.id()) == 0;
|
||||
mutex.lock();
|
||||
|
||||
ret
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {
|
||||
let _ = sys_destroy_queue(self.id());
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn id(&self) -> usize {
|
||||
&self.identifier as *const usize as usize
|
||||
}
|
||||
}
|
9
src/libstd/sys/hermit/env.rs
Normal file
9
src/libstd/sys/hermit/env.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
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 = "";
|
||||
}
|
4
src/libstd/sys/hermit/fast_thread_local.rs
Normal file
4
src/libstd/sys/hermit/fast_thread_local.rs
Normal file
|
@ -0,0 +1,4 @@
|
|||
#![cfg(target_thread_local)]
|
||||
#![unstable(feature = "thread_local_internals", issue = "0")]
|
||||
|
||||
pub use crate::sys_common::thread_local::register_dtor_fallback as register_dtor;
|
87
src/libstd/sys/hermit/fd.rs
Normal file
87
src/libstd/sys/hermit/fd.rs
Normal file
|
@ -0,0 +1,87 @@
|
|||
#![unstable(reason = "not public", issue = "0", feature = "fd")]
|
||||
|
||||
use crate::io::{self, Read, ErrorKind};
|
||||
use crate::mem;
|
||||
use crate::sys::cvt;
|
||||
use crate::sys_common::AsInner;
|
||||
|
||||
extern {
|
||||
fn sys_read(fd: i32, buf: *mut u8, len: usize) -> isize;
|
||||
fn sys_write(fd: i32, buf: *const u8, len: usize) -> isize;
|
||||
fn sys_close(fd: i32) -> i32;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FileDesc {
|
||||
fd: i32,
|
||||
}
|
||||
|
||||
impl FileDesc {
|
||||
pub fn new(fd: i32) -> FileDesc {
|
||||
FileDesc { fd }
|
||||
}
|
||||
|
||||
pub fn raw(&self) -> i32 { self.fd }
|
||||
|
||||
/// Extracts the actual file descriptor without closing it.
|
||||
pub fn into_raw(self) -> i32 {
|
||||
let fd = self.fd;
|
||||
mem::forget(self);
|
||||
fd
|
||||
}
|
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
let result = unsafe { sys_read(self.fd, buf.as_mut_ptr(), buf.len()) };
|
||||
cvt(result as i32)
|
||||
}
|
||||
|
||||
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
let mut me = self;
|
||||
(&mut me).read_to_end(buf)
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
let result = unsafe { sys_write(self.fd, buf.as_ptr(), buf.len()) };
|
||||
cvt(result as i32)
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<FileDesc> {
|
||||
self.duplicate_path(&[])
|
||||
}
|
||||
pub fn duplicate_path(&self, _path: &[u8]) -> io::Result<FileDesc> {
|
||||
Err(io::Error::new(ErrorKind::Other, "duplicate isn't supported"))
|
||||
}
|
||||
|
||||
pub fn nonblocking(&self) -> io::Result<bool> {
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
pub fn set_cloexec(&self) -> io::Result<()> {
|
||||
Err(io::Error::new(ErrorKind::Other, "cloexec isn't supported"))
|
||||
}
|
||||
|
||||
pub fn set_nonblocking(&self, _nonblocking: bool) -> io::Result<()> {
|
||||
Err(io::Error::new(ErrorKind::Other, "nonblocking isn't supported"))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Read for &'a FileDesc {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
(**self).read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsInner<i32> for FileDesc {
|
||||
fn as_inner(&self) -> &i32 { &self.fd }
|
||||
}
|
||||
|
||||
impl Drop for FileDesc {
|
||||
fn drop(&mut self) {
|
||||
// Note that errors are ignored when closing a file descriptor. The
|
||||
// reason for this is that if an error occurs we don't actually know if
|
||||
// the file descriptor was closed or not, and if we retried (for
|
||||
// something like EINTR), we might close another valid file descriptor
|
||||
// (opened after we closed ours.
|
||||
let _ = unsafe { sys_close(self.fd) };
|
||||
}
|
||||
}
|
389
src/libstd/sys/hermit/fs.rs
Normal file
389
src/libstd/sys/hermit/fs.rs
Normal file
|
@ -0,0 +1,389 @@
|
|||
use crate::ffi::{OsString, CString, CStr};
|
||||
use crate::fmt;
|
||||
use crate::io::{self, Error, ErrorKind};
|
||||
use crate::hash::{Hash, Hasher};
|
||||
use crate::io::{SeekFrom, IoSlice, IoSliceMut};
|
||||
use crate::path::{Path, PathBuf};
|
||||
use crate::sys::time::SystemTime;
|
||||
use crate::sys::{unsupported, Void};
|
||||
use crate::sys::hermit::fd::FileDesc;
|
||||
use crate::sys::cvt;
|
||||
use crate::sys_common::os_str_bytes::OsStrExt;
|
||||
|
||||
pub use crate::sys_common::fs::copy;
|
||||
//pub use crate::sys_common::fs::remove_dir_all;
|
||||
|
||||
extern {
|
||||
fn sys_open(name: *const i8, flags: i32, mode: i32) -> i32;
|
||||
fn sys_unlink(name: *const i8) -> i32;
|
||||
}
|
||||
|
||||
fn cstr(path: &Path) -> io::Result<CString> {
|
||||
Ok(CString::new(path.as_os_str().as_bytes())?)
|
||||
}
|
||||
//const O_ACCMODE: i32 = 00000003;
|
||||
const O_RDONLY: i32 = 00000000;
|
||||
const O_WRONLY: i32 = 00000001;
|
||||
const O_RDWR: i32 = 00000002;
|
||||
const O_CREAT: i32 = 00000100;
|
||||
const O_EXCL: i32 = 00000200;
|
||||
const O_TRUNC: i32 = 00001000;
|
||||
const O_APPEND: i32 = 00002000;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct File(FileDesc);
|
||||
|
||||
pub struct FileAttr(Void);
|
||||
|
||||
pub struct ReadDir(Void);
|
||||
|
||||
pub struct DirEntry(Void);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OpenOptions {
|
||||
// generic
|
||||
read: bool,
|
||||
write: bool,
|
||||
append: bool,
|
||||
truncate: bool,
|
||||
create: bool,
|
||||
create_new: bool,
|
||||
// system-specific
|
||||
mode: i32
|
||||
}
|
||||
|
||||
pub struct FilePermissions(Void);
|
||||
|
||||
pub struct FileType(Void);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DirBuilder { }
|
||||
|
||||
impl FileAttr {
|
||||
pub fn size(&self) -> u64 {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn perm(&self) -> FilePermissions {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> FileType {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn modified(&self) -> io::Result<SystemTime> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn created(&self) -> io::Result<SystemTime> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FileAttr {
|
||||
fn clone(&self) -> FileAttr {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl FilePermissions {
|
||||
pub fn readonly(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_readonly(&mut self, _readonly: bool) {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FilePermissions {
|
||||
fn clone(&self) -> FilePermissions {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for FilePermissions {
|
||||
fn eq(&self, _other: &FilePermissions) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FilePermissions {
|
||||
}
|
||||
|
||||
impl fmt::Debug for FilePermissions {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl FileType {
|
||||
pub fn is_dir(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn is_file(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn is_symlink(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FileType {
|
||||
fn clone(&self) -> FileType {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Copy for FileType {}
|
||||
|
||||
impl PartialEq for FileType {
|
||||
fn eq(&self, _other: &FileType) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FileType {
|
||||
}
|
||||
|
||||
impl Hash for FileType {
|
||||
fn hash<H: Hasher>(&self, _h: &mut H) {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for FileType {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ReadDir {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for ReadDir {
|
||||
type Item = io::Result<DirEntry>;
|
||||
|
||||
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl DirEntry {
|
||||
pub fn path(&self) -> PathBuf {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn file_name(&self) -> OsString {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> io::Result<FileAttr> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> io::Result<FileType> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl OpenOptions {
|
||||
pub fn new() -> OpenOptions {
|
||||
OpenOptions {
|
||||
// generic
|
||||
read: false,
|
||||
write: false,
|
||||
append: false,
|
||||
truncate: false,
|
||||
create: false,
|
||||
create_new: false,
|
||||
// system-specific
|
||||
mode: 0x777
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read(&mut self, read: bool) { self.read = read; }
|
||||
pub fn write(&mut self, write: bool) { self.write = write; }
|
||||
pub fn append(&mut self, append: bool) { self.append = append; }
|
||||
pub fn truncate(&mut self, truncate: bool) { self.truncate = truncate; }
|
||||
pub fn create(&mut self, create: bool) { self.create = create; }
|
||||
pub fn create_new(&mut self, create_new: bool) { self.create_new = create_new; }
|
||||
|
||||
fn get_access_mode(&self) -> io::Result<i32> {
|
||||
match (self.read, self.write, self.append) {
|
||||
(true, false, false) => Ok(O_RDONLY),
|
||||
(false, true, false) => Ok(O_WRONLY),
|
||||
(true, true, false) => Ok(O_RDWR),
|
||||
(false, _, true) => Ok(O_WRONLY | O_APPEND),
|
||||
(true, _, true) => Ok(O_RDWR | O_APPEND),
|
||||
(false, false, false) => Err(io::Error::new(ErrorKind::InvalidInput, "invalid access mode")),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_creation_mode(&self) -> io::Result<i32> {
|
||||
match (self.write, self.append) {
|
||||
(true, false) => {}
|
||||
(false, false) =>
|
||||
if self.truncate || self.create || self.create_new {
|
||||
return Err(io::Error::new(ErrorKind::InvalidInput, "invalid creation mode"));
|
||||
},
|
||||
(_, true) =>
|
||||
if self.truncate && !self.create_new {
|
||||
return Err(io::Error::new(ErrorKind::InvalidInput, "invalid creation mode"));
|
||||
},
|
||||
}
|
||||
|
||||
Ok(match (self.create, self.truncate, self.create_new) {
|
||||
(false, false, false) => 0,
|
||||
(true, false, false) => O_CREAT,
|
||||
(false, true, false) => O_TRUNC,
|
||||
(true, true, false) => O_CREAT | O_TRUNC,
|
||||
(_, _, true) => O_CREAT | O_EXCL,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl File {
|
||||
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
|
||||
let path = cstr(path)?;
|
||||
File::open_c(&path, opts)
|
||||
}
|
||||
|
||||
pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> {
|
||||
let mut flags = opts.get_access_mode()?;
|
||||
flags = flags | opts.get_creation_mode()?;
|
||||
|
||||
let mode;
|
||||
if flags & O_CREAT == O_CREAT {
|
||||
mode = opts.mode;
|
||||
} else {
|
||||
mode = 0;
|
||||
}
|
||||
|
||||
let fd = unsafe { cvt(sys_open(path.as_ptr(), flags, mode))? };
|
||||
Ok(File(FileDesc::new(fd as i32)))
|
||||
}
|
||||
|
||||
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
||||
Err(Error::from_raw_os_error(22))
|
||||
}
|
||||
|
||||
pub fn fsync(&self) -> io::Result<()> {
|
||||
Err(Error::from_raw_os_error(22))
|
||||
}
|
||||
|
||||
pub fn datasync(&self) -> io::Result<()> {
|
||||
self.fsync()
|
||||
}
|
||||
|
||||
pub fn truncate(&self, _size: u64) -> io::Result<()> {
|
||||
Err(Error::from_raw_os_error(22))
|
||||
}
|
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0.read(buf)
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
crate::io::default_read_vectored(|buf| self.read(buf), bufs)
|
||||
}
|
||||
|
||||
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||
self.0.write(buf)
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
crate::io::default_write_vectored(|buf| self.write(buf), bufs)
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
|
||||
Err(Error::from_raw_os_error(22))
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<File> {
|
||||
Err(Error::from_raw_os_error(22))
|
||||
}
|
||||
|
||||
pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
|
||||
Err(Error::from_raw_os_error(22))
|
||||
}
|
||||
|
||||
pub fn diverge(&self) -> ! {
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
impl DirBuilder {
|
||||
pub fn new() -> DirBuilder {
|
||||
DirBuilder { }
|
||||
}
|
||||
|
||||
pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn unlink(path: &Path) -> io::Result<()> {
|
||||
let name = cstr(path)?;
|
||||
let _ = unsafe { cvt(sys_unlink(name.as_ptr()))? };
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
|
||||
match perm.0 {}
|
||||
}
|
||||
|
||||
pub fn rmdir(_p: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
|
||||
//unsupported()
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn symlink(_src: &Path, _dst: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn stat(_p: &Path) -> io::Result<FileAttr> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
|
||||
unsupported()
|
||||
}
|
46
src/libstd/sys/hermit/io.rs
Normal file
46
src/libstd/sys/hermit/io.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use crate::mem;
|
||||
|
||||
pub struct IoSlice<'a>(&'a [u8]);
|
||||
|
||||
impl<'a> IoSlice<'a> {
|
||||
#[inline]
|
||||
pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
|
||||
IoSlice(buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn advance(&mut self, n: usize) {
|
||||
self.0 = &self.0[n..]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IoSliceMut<'a>(&'a mut [u8]);
|
||||
|
||||
impl<'a> IoSliceMut<'a> {
|
||||
#[inline]
|
||||
pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
|
||||
IoSliceMut(buf)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn advance(&mut self, n: usize) {
|
||||
let slice = mem::replace(&mut self.0, &mut []);
|
||||
let (_, remaining) = slice.split_at_mut(n);
|
||||
self.0 = remaining;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
self.0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_mut_slice(&mut self) -> &mut [u8] {
|
||||
self.0
|
||||
}
|
||||
}
|
1
src/libstd/sys/hermit/memchr.rs
Normal file
1
src/libstd/sys/hermit/memchr.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub use core::slice::memchr::{memchr, memrchr};
|
148
src/libstd/sys/hermit/mod.rs
Normal file
148
src/libstd/sys/hermit/mod.rs
Normal file
|
@ -0,0 +1,148 @@
|
|||
//! System bindings for HermitCore
|
||||
//!
|
||||
//! This module contains the facade (aka platform-specific) implementations of
|
||||
//! OS level functionality for HermitCore.
|
||||
//!
|
||||
//! This is all super highly experimental and not actually intended for
|
||||
//! wide/production use yet, it's still all in the experimental category. This
|
||||
//! will likely change over time.
|
||||
//!
|
||||
//! Currently all functions here are basically stubs that immediately return
|
||||
//! errors. The hope is that with a portability lint we can turn actually just
|
||||
//! remove all this and just omit parts of the standard library if we're
|
||||
//! compiling for wasm. That way it's a compile time error for something that's
|
||||
//! guaranteed to be a runtime error!
|
||||
|
||||
use crate::os::raw::c_char;
|
||||
use crate::intrinsics;
|
||||
|
||||
pub mod alloc;
|
||||
pub mod args;
|
||||
pub mod condvar;
|
||||
pub mod stdio;
|
||||
pub mod memchr;
|
||||
pub mod io;
|
||||
pub mod mutex;
|
||||
pub mod rwlock;
|
||||
pub mod os;
|
||||
pub mod cmath;
|
||||
pub mod thread;
|
||||
pub mod env;
|
||||
pub mod fs;
|
||||
pub mod fd;
|
||||
pub mod net;
|
||||
pub mod path;
|
||||
pub mod pipe;
|
||||
pub mod process;
|
||||
pub mod stack_overflow;
|
||||
pub mod time;
|
||||
pub mod thread_local;
|
||||
pub mod fast_thread_local;
|
||||
|
||||
pub use crate::sys_common::os_str_bytes as os_str;
|
||||
use crate::io::ErrorKind;
|
||||
|
||||
pub fn unsupported<T>() -> crate::io::Result<T> {
|
||||
Err(unsupported_err())
|
||||
}
|
||||
|
||||
pub fn unsupported_err() -> crate::io::Error {
|
||||
crate::io::Error::new(crate::io::ErrorKind::Other,
|
||||
"operation not supported on HermitCore yet")
|
||||
}
|
||||
|
||||
// This enum is used as the storage for a bunch of types which can't actually
|
||||
// exist.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
pub enum Void {}
|
||||
|
||||
pub unsafe fn strlen(start: *const c_char) -> usize {
|
||||
let mut str = start;
|
||||
|
||||
while *str != 0 {
|
||||
str = str.offset(1);
|
||||
}
|
||||
|
||||
(str as usize) - (start as usize)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn floor(x: f64) -> f64 {
|
||||
unsafe {
|
||||
intrinsics::floorf64(x)
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn abort_internal() -> ! {
|
||||
extern "C" {
|
||||
fn sys_abort() ->!;
|
||||
}
|
||||
|
||||
sys_abort();
|
||||
}
|
||||
|
||||
// TODO: just a workaround to test the system
|
||||
pub fn hashmap_random_keys() -> (u64, u64) {
|
||||
(1, 2)
|
||||
}
|
||||
|
||||
// This function is needed by the panic runtime. The symbol is named in
|
||||
// pre-link args for the target specification, so keep that in sync.
|
||||
#[cfg(not(test))]
|
||||
#[no_mangle]
|
||||
// NB. used by both libunwind and libpanic_abort
|
||||
pub unsafe extern "C" fn __rust_abort() {
|
||||
abort_internal();
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
pub fn init() {
|
||||
unsafe {
|
||||
let _ = net::init();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn runtime_entry(argc: i32, argv: *const *const c_char, env: *const *const c_char) -> ! {
|
||||
extern "C" {
|
||||
fn main(argc: isize, argv: *const *const c_char) -> i32;
|
||||
fn sys_exit(arg: i32) ->!;
|
||||
}
|
||||
|
||||
// initialize environment
|
||||
os::init_environment(env as *const *const i8);
|
||||
|
||||
let result = main(argc as isize, argv);
|
||||
|
||||
sys_exit(result);
|
||||
}
|
||||
|
||||
pub fn decode_error_kind(errno: i32) -> ErrorKind {
|
||||
match errno {
|
||||
x if x == 13 as i32 => ErrorKind::PermissionDenied,
|
||||
x if x == 98 as i32 => ErrorKind::AddrInUse,
|
||||
x if x == 99 as i32 => ErrorKind::AddrNotAvailable,
|
||||
x if x == 11 as i32 => ErrorKind::WouldBlock,
|
||||
x if x == 103 as i32 => ErrorKind::ConnectionAborted,
|
||||
x if x == 111 as i32 => ErrorKind::ConnectionRefused,
|
||||
x if x == 104 as i32 => ErrorKind::ConnectionReset,
|
||||
x if x == 17 as i32 => ErrorKind::AlreadyExists,
|
||||
x if x == 4 as i32 => ErrorKind::Interrupted,
|
||||
x if x == 22 as i32 => ErrorKind::InvalidInput,
|
||||
x if x == 2 as i32 => ErrorKind::NotFound,
|
||||
x if x == 107 as i32 => ErrorKind::NotConnected,
|
||||
x if x == 1 as i32 => ErrorKind::PermissionDenied,
|
||||
x if x == 32 as i32 => ErrorKind::BrokenPipe,
|
||||
x if x == 110 as i32 => ErrorKind::TimedOut,
|
||||
_ => ErrorKind::Other,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn cvt(result: i32) -> crate::io::Result<usize> {
|
||||
if result < 0 {
|
||||
Err(crate::io::Error::from_raw_os_error(-result))
|
||||
} else {
|
||||
Ok(result as usize)
|
||||
}
|
||||
}
|
88
src/libstd/sys/hermit/mutex.rs
Normal file
88
src/libstd/sys/hermit/mutex.rs
Normal file
|
@ -0,0 +1,88 @@
|
|||
use crate::ptr;
|
||||
use crate::ffi::c_void;
|
||||
|
||||
extern "C" {
|
||||
fn sys_sem_init(sem: *mut *const c_void, value: u32) -> i32;
|
||||
fn sys_sem_destroy(sem: *const c_void) -> i32;
|
||||
fn sys_sem_post(sem: *const c_void) -> i32;
|
||||
fn sys_sem_trywait(sem: *const c_void) -> i32;
|
||||
fn sys_sem_timedwait(sem: *const c_void, ms: u32) -> i32;
|
||||
fn sys_recmutex_init(recmutex: *mut *const c_void) -> i32;
|
||||
fn sys_recmutex_destroy(recmutex: *const c_void) -> i32;
|
||||
fn sys_recmutex_lock(recmutex: *const c_void) -> i32;
|
||||
fn sys_recmutex_unlock(recmutex: *const c_void) -> i32;
|
||||
}
|
||||
|
||||
pub struct Mutex {
|
||||
inner: *const c_void
|
||||
}
|
||||
|
||||
unsafe impl Send for Mutex {}
|
||||
unsafe impl Sync for Mutex {}
|
||||
|
||||
impl Mutex {
|
||||
pub const fn new() -> Mutex {
|
||||
Mutex { inner: ptr::null() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn init(&mut self) {
|
||||
let _ = sys_sem_init(&mut self.inner as *mut *const c_void, 1);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn lock(&self) {
|
||||
let _ = sys_sem_timedwait(self.inner, 0);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn unlock(&self) {
|
||||
let _ = sys_sem_post(self.inner);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn try_lock(&self) -> bool {
|
||||
let result = sys_sem_trywait(self.inner);
|
||||
result == 0
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {
|
||||
let _ = sys_sem_destroy(self.inner);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ReentrantMutex {
|
||||
inner: *const c_void
|
||||
}
|
||||
|
||||
impl ReentrantMutex {
|
||||
pub unsafe fn uninitialized() -> ReentrantMutex {
|
||||
ReentrantMutex { inner: ptr::null() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn init(&mut self) {
|
||||
let _ = sys_recmutex_init(&mut self.inner as *mut *const c_void);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn lock(&self) {
|
||||
let _ = sys_recmutex_lock(self.inner);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn try_lock(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn unlock(&self) {
|
||||
let _ = sys_recmutex_unlock(self.inner);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {
|
||||
let _ = sys_recmutex_destroy(self.inner);
|
||||
}
|
||||
}
|
364
src/libstd/sys/hermit/net.rs
Normal file
364
src/libstd/sys/hermit/net.rs
Normal file
|
@ -0,0 +1,364 @@
|
|||
use crate::fmt;
|
||||
use crate::convert::TryFrom;
|
||||
use crate::io::{self, IoSlice, IoSliceMut};
|
||||
use crate::net::{SocketAddr, Shutdown, Ipv4Addr, Ipv6Addr};
|
||||
use crate::str;
|
||||
use crate::sys::{unsupported, Void};
|
||||
use crate::time::Duration;
|
||||
|
||||
//// Iinitializes HermitCore's network stack
|
||||
pub unsafe fn init() -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub struct TcpStream(Void);
|
||||
|
||||
impl TcpStream {
|
||||
pub fn connect(_: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn connect_timeout(_: &SocketAddr, _: Duration) -> io::Result<TcpStream> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn read(&self, _: &mut [u8]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, _: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn write(&self, _: &[u8]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, _: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn shutdown(&self, _: Shutdown) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<TcpStream> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_nodelay(&self, _: bool) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn nodelay(&self) -> io::Result<bool> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn ttl(&self) -> io::Result<u32> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for TcpStream {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TcpListener(Void);
|
||||
|
||||
impl TcpListener {
|
||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<TcpListener> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn ttl(&self) -> io::Result<u32> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn only_v6(&self) -> io::Result<bool> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for TcpListener {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UdpSocket(Void);
|
||||
|
||||
impl UdpSocket {
|
||||
pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn recv_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn peek_from(&self, _: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn send_to(&self, _: &[u8], _: &SocketAddr) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<UdpSocket> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_read_timeout(&self, _: Option<Duration>) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_write_timeout(&self, _: Option<Duration>) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_broadcast(&self, _: bool) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn broadcast(&self) -> io::Result<bool> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr)
|
||||
-> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32)
|
||||
-> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr)
|
||||
-> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32)
|
||||
-> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_ttl(&self, _: u32) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn ttl(&self) -> io::Result<u32> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn set_nonblocking(&self, _: bool) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn recv(&self, _: &mut [u8]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn peek(&self, _: &mut [u8]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn send(&self, _: &[u8]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn connect(&self, _: io::Result<&SocketAddr>) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for UdpSocket {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LookupHost(Void);
|
||||
|
||||
impl LookupHost {
|
||||
pub fn port(&self) -> u16 {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for LookupHost {
|
||||
type Item = SocketAddr;
|
||||
fn next(&mut self) -> Option<SocketAddr> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for LookupHost {
|
||||
type Error = io::Error;
|
||||
|
||||
fn try_from(_v: &str) -> io::Result<LookupHost> {
|
||||
unsupported()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
|
||||
type Error = io::Error;
|
||||
|
||||
fn try_from(_v: (&'a str, u16)) -> io::Result<LookupHost> {
|
||||
unsupported()
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(nonstandard_style)]
|
||||
pub mod netc {
|
||||
pub const AF_INET: u8 = 0;
|
||||
pub const AF_INET6: u8 = 1;
|
||||
pub type sa_family_t = u8;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct in_addr {
|
||||
pub s_addr: u32,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct sockaddr_in {
|
||||
pub sin_family: sa_family_t,
|
||||
pub sin_port: u16,
|
||||
pub sin_addr: in_addr,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct in6_addr {
|
||||
pub s6_addr: [u8; 16],
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct sockaddr_in6 {
|
||||
pub sin6_family: sa_family_t,
|
||||
pub sin6_port: u16,
|
||||
pub sin6_addr: in6_addr,
|
||||
pub sin6_flowinfo: u32,
|
||||
pub sin6_scope_id: u32,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct sockaddr {
|
||||
}
|
||||
|
||||
pub type socklen_t = usize;
|
||||
}
|
178
src/libstd/sys/hermit/os.rs
Normal file
178
src/libstd/sys/hermit/os.rs
Normal file
|
@ -0,0 +1,178 @@
|
|||
use crate::error::Error as StdError;
|
||||
use crate::ffi::{CStr, OsString, OsStr};
|
||||
use crate::fmt;
|
||||
use crate::io;
|
||||
use crate::marker::PhantomData;
|
||||
use crate::memchr;
|
||||
use crate::path::{self, PathBuf};
|
||||
use crate::ptr;
|
||||
use crate::str;
|
||||
use crate::sys::{unsupported, Void};
|
||||
use crate::collections::HashMap;
|
||||
use crate::vec;
|
||||
use crate::sync::Mutex;
|
||||
use crate::sys_common::os_str_bytes::*;
|
||||
|
||||
extern "C" {
|
||||
fn sys_getpid() -> u32;
|
||||
fn sys_exit(arg: i32) ->!;
|
||||
}
|
||||
|
||||
pub fn errno() -> i32 {
|
||||
0
|
||||
}
|
||||
|
||||
pub fn error_string(_errno: i32) -> String {
|
||||
"operation successful".to_string()
|
||||
}
|
||||
|
||||
pub fn getcwd() -> io::Result<PathBuf> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn chdir(_: &path::Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub struct SplitPaths<'a>(&'a Void);
|
||||
|
||||
pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
|
||||
panic!("unsupported")
|
||||
}
|
||||
|
||||
impl<'a> Iterator for SplitPaths<'a> {
|
||||
type Item = PathBuf;
|
||||
fn next(&mut self) -> Option<PathBuf> {
|
||||
match *self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct JoinPathsError;
|
||||
|
||||
pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
|
||||
where I: Iterator<Item=T>, T: AsRef<OsStr>
|
||||
{
|
||||
Err(JoinPathsError)
|
||||
}
|
||||
|
||||
impl fmt::Display for JoinPathsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
"not supported on hermit yet".fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl StdError for JoinPathsError {
|
||||
fn description(&self) -> &str {
|
||||
"not supported on hermit yet"
|
||||
}
|
||||
}
|
||||
|
||||
pub fn current_exe() -> io::Result<PathBuf> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
static mut ENV: Option<Mutex<HashMap<OsString, OsString>>> = None;
|
||||
|
||||
pub fn init_environment(env: *const *const i8) {
|
||||
unsafe {
|
||||
ENV = Some(Mutex::new(HashMap::new()));
|
||||
|
||||
let mut guard = ENV.as_ref().unwrap().lock().unwrap();
|
||||
let mut environ = env;
|
||||
while environ != ptr::null() && *environ != ptr::null() {
|
||||
if let Some((key,value)) = parse(CStr::from_ptr(*environ).to_bytes()) {
|
||||
guard.insert(key, value);
|
||||
}
|
||||
environ = environ.offset(1);
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(input: &[u8]) -> Option<(OsString, OsString)> {
|
||||
// Strategy (copied from glibc): Variable name and value are separated
|
||||
// by an ASCII equals sign '='. Since a variable name must not be
|
||||
// empty, allow variable names starting with an equals sign. Skip all
|
||||
// malformed lines.
|
||||
if input.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let pos = memchr::memchr(b'=', &input[1..]).map(|p| p + 1);
|
||||
pos.map(|p| (
|
||||
OsStringExt::from_vec(input[..p].to_vec()),
|
||||
OsStringExt::from_vec(input[p+1..].to_vec()),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
_dont_send_or_sync_me: PhantomData<*mut ()>,
|
||||
}
|
||||
|
||||
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() }
|
||||
}
|
||||
|
||||
/// Returns a vector of (variable, value) byte-vector pairs for all the
|
||||
/// environment variables of the current process.
|
||||
pub fn env() -> Env {
|
||||
unsafe {
|
||||
let guard = ENV.as_ref().unwrap().lock().unwrap();
|
||||
let mut result = Vec::new();
|
||||
|
||||
for (key, value) in guard.iter() {
|
||||
result.push((key.clone(), value.clone()));
|
||||
}
|
||||
|
||||
return Env {
|
||||
iter: result.into_iter(),
|
||||
_dont_send_or_sync_me: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getenv(k: &OsStr) -> io::Result<Option<OsString>> {
|
||||
unsafe {
|
||||
match ENV.as_ref().unwrap().lock().unwrap().get_mut(k) {
|
||||
Some(value) => { Ok(Some(value.clone())) },
|
||||
None => { Ok(None) },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
|
||||
unsafe {
|
||||
let (k, v) = (k.to_owned(), v.to_owned());
|
||||
ENV.as_ref().unwrap().lock().unwrap().insert(k, v);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn unsetenv(k: &OsStr) -> io::Result<()> {
|
||||
unsafe {
|
||||
ENV.as_ref().unwrap().lock().unwrap().remove(k);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn temp_dir() -> PathBuf {
|
||||
panic!("no filesystem on hermit")
|
||||
}
|
||||
|
||||
pub fn home_dir() -> Option<PathBuf> {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn exit(code: i32) -> ! {
|
||||
unsafe {
|
||||
sys_exit(code);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn getpid() -> u32 {
|
||||
unsafe {
|
||||
sys_getpid()
|
||||
}
|
||||
}
|
19
src/libstd/sys/hermit/path.rs
Normal file
19
src/libstd/sys/hermit/path.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
use crate::path::Prefix;
|
||||
use crate::ffi::OsStr;
|
||||
|
||||
#[inline]
|
||||
pub fn is_sep_byte(b: u8) -> bool {
|
||||
b == b'/'
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn is_verbatim_sep(b: u8) -> bool {
|
||||
b == b'/'
|
||||
}
|
||||
|
||||
pub fn parse_prefix(_: &OsStr) -> Option<Prefix<'_>> {
|
||||
None
|
||||
}
|
||||
|
||||
pub const MAIN_SEP_STR: &str = "/";
|
||||
pub const MAIN_SEP: char = '/';
|
33
src/libstd/sys/hermit/pipe.rs
Normal file
33
src/libstd/sys/hermit/pipe.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
use crate::io::{self, IoSlice, IoSliceMut};
|
||||
use crate::sys::Void;
|
||||
|
||||
pub struct AnonPipe(Void);
|
||||
|
||||
impl AnonPipe {
|
||||
pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn diverge(&self) -> ! {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn read2(p1: AnonPipe,
|
||||
_v1: &mut Vec<u8>,
|
||||
_p2: AnonPipe,
|
||||
_v2: &mut Vec<u8>) -> io::Result<()> {
|
||||
match p1.0 {}
|
||||
}
|
154
src/libstd/sys/hermit/process.rs
Normal file
154
src/libstd/sys/hermit/process.rs
Normal file
|
@ -0,0 +1,154 @@
|
|||
use crate::ffi::OsStr;
|
||||
use crate::fmt;
|
||||
use crate::io;
|
||||
use crate::sys::fs::File;
|
||||
use crate::sys::pipe::AnonPipe;
|
||||
use crate::sys::{unsupported, Void};
|
||||
use crate::sys_common::process::CommandEnv;
|
||||
|
||||
pub use crate::ffi::OsString as EnvKey;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Command
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
pub struct Command {
|
||||
env: CommandEnv,
|
||||
}
|
||||
|
||||
// passed back to std::process with the pipes connected to the child, if any
|
||||
// were requested
|
||||
pub struct StdioPipes {
|
||||
pub stdin: Option<AnonPipe>,
|
||||
pub stdout: Option<AnonPipe>,
|
||||
pub stderr: Option<AnonPipe>,
|
||||
}
|
||||
|
||||
pub enum Stdio {
|
||||
Inherit,
|
||||
Null,
|
||||
MakePipe,
|
||||
}
|
||||
|
||||
impl Command {
|
||||
pub fn new(_program: &OsStr) -> Command {
|
||||
Command {
|
||||
env: Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn arg(&mut self, _arg: &OsStr) {
|
||||
}
|
||||
|
||||
pub fn env_mut(&mut self) -> &mut CommandEnv {
|
||||
&mut self.env
|
||||
}
|
||||
|
||||
pub fn cwd(&mut self, _dir: &OsStr) {
|
||||
}
|
||||
|
||||
pub fn stdin(&mut self, _stdin: Stdio) {
|
||||
}
|
||||
|
||||
pub fn stdout(&mut self, _stdout: Stdio) {
|
||||
}
|
||||
|
||||
pub fn stderr(&mut self, _stderr: Stdio) {
|
||||
}
|
||||
|
||||
pub fn spawn(&mut self, _default: Stdio, _needs_stdin: bool)
|
||||
-> io::Result<(Process, StdioPipes)> {
|
||||
unsupported()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AnonPipe> for Stdio {
|
||||
fn from(pipe: AnonPipe) -> Stdio {
|
||||
pipe.diverge()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<File> for Stdio {
|
||||
fn from(file: File) -> Stdio {
|
||||
file.diverge()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Command {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ExitStatus(Void);
|
||||
|
||||
impl ExitStatus {
|
||||
pub fn success(&self) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn code(&self) -> Option<i32> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for ExitStatus {
|
||||
fn clone(&self) -> ExitStatus {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Copy for ExitStatus {}
|
||||
|
||||
impl PartialEq for ExitStatus {
|
||||
fn eq(&self, _other: &ExitStatus) -> bool {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for ExitStatus {
|
||||
}
|
||||
|
||||
impl fmt::Debug for ExitStatus {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ExitStatus {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct ExitCode(bool);
|
||||
|
||||
impl ExitCode {
|
||||
pub const SUCCESS: ExitCode = ExitCode(false);
|
||||
pub const FAILURE: ExitCode = ExitCode(true);
|
||||
|
||||
pub fn as_i32(&self) -> i32 {
|
||||
self.0 as i32
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Process(Void);
|
||||
|
||||
impl Process {
|
||||
pub fn id(&self) -> u32 {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn kill(&mut self) -> io::Result<()> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn wait(&mut self) -> io::Result<ExitStatus> {
|
||||
match self.0 {}
|
||||
}
|
||||
|
||||
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
|
||||
match self.0 {}
|
||||
}
|
||||
}
|
51
src/libstd/sys/hermit/rwlock.rs
Normal file
51
src/libstd/sys/hermit/rwlock.rs
Normal file
|
@ -0,0 +1,51 @@
|
|||
use super::mutex::Mutex;
|
||||
|
||||
pub struct RWLock {
|
||||
mutex: Mutex
|
||||
}
|
||||
|
||||
unsafe impl Send for RWLock {}
|
||||
unsafe impl Sync for RWLock {}
|
||||
|
||||
impl RWLock {
|
||||
pub const fn new() -> RWLock {
|
||||
RWLock {
|
||||
mutex: Mutex::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn read(&self) {
|
||||
self.mutex.lock();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn try_read(&self) -> bool {
|
||||
self.mutex.try_lock()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn write(&self) {
|
||||
self.mutex.lock();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn try_write(&self) -> bool {
|
||||
self.mutex.try_lock()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn read_unlock(&self) {
|
||||
self.mutex.unlock();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn write_unlock(&self) {
|
||||
self.mutex.unlock();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(&self) {
|
||||
self.mutex.destroy();
|
||||
}
|
||||
}
|
15
src/libstd/sys/hermit/stack_overflow.rs
Normal file
15
src/libstd/sys/hermit/stack_overflow.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
pub struct Handler;
|
||||
|
||||
impl Handler {
|
||||
pub unsafe fn new() -> Handler {
|
||||
Handler
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn init() {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn cleanup() {
|
||||
}
|
122
src/libstd/sys/hermit/stdio.rs
Normal file
122
src/libstd/sys/hermit/stdio.rs
Normal file
|
@ -0,0 +1,122 @@
|
|||
use crate::io;
|
||||
use crate::io::{IoSlice, IoSliceMut};
|
||||
|
||||
extern "C" {
|
||||
fn sys_write(fd: i32, buf: *const u8, len: usize) -> isize;
|
||||
}
|
||||
|
||||
pub struct Stdin;
|
||||
pub struct Stdout;
|
||||
pub struct Stderr;
|
||||
|
||||
impl Stdin {
|
||||
pub fn new() -> io::Result<Stdin> {
|
||||
Ok(Stdin)
|
||||
}
|
||||
|
||||
pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
|
||||
self.read_vectored(&mut [IoSliceMut::new(data)])
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, _data: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
//ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDIN_FILENO as u32) })
|
||||
// .read(data)
|
||||
Ok(0)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
impl Stdout {
|
||||
pub fn new() -> io::Result<Stdout> {
|
||||
Ok(Stdout)
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
let len;
|
||||
|
||||
unsafe {
|
||||
len = sys_write(1, data.as_ptr() as *const u8, data.len())
|
||||
}
|
||||
|
||||
if len < 0 {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "Stdout is not able to print"))
|
||||
} else {
|
||||
Ok(len as usize)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
let len;
|
||||
|
||||
unsafe {
|
||||
len = sys_write(1, data.as_ptr() as *const u8, data.len())
|
||||
}
|
||||
|
||||
if len < 0 {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "Stdout is not able to print"))
|
||||
} else {
|
||||
Ok(len as usize)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Stderr {
|
||||
pub fn new() -> io::Result<Stderr> {
|
||||
Ok(Stderr)
|
||||
}
|
||||
|
||||
pub fn write(&self, data: &[u8]) -> io::Result<usize> {
|
||||
let len;
|
||||
|
||||
unsafe {
|
||||
len = sys_write(2, data.as_ptr() as *const u8, data.len())
|
||||
}
|
||||
|
||||
if len < 0 {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "Stderr is not able to print"))
|
||||
} else {
|
||||
Ok(len as usize)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
let len;
|
||||
|
||||
unsafe {
|
||||
len = sys_write(2, data.as_ptr() as *const u8, data.len())
|
||||
}
|
||||
|
||||
if len < 0 {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "Stderr is not able to print"))
|
||||
} else {
|
||||
Ok(len as usize)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl io::Write for Stderr {
|
||||
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
|
||||
(&*self).write(data)
|
||||
}
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
(&*self).flush()
|
||||
}
|
||||
}
|
||||
|
||||
pub const STDIN_BUF_SIZE: usize = 0;
|
||||
|
||||
pub fn is_ebadf(_err: &io::Error) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn panic_output() -> Option<impl io::Write> {
|
||||
Stderr::new().ok()
|
||||
}
|
121
src/libstd/sys/hermit/thread.rs
Normal file
121
src/libstd/sys/hermit/thread.rs
Normal file
|
@ -0,0 +1,121 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use crate::ffi::CStr;
|
||||
use crate::io;
|
||||
use crate::time::Duration;
|
||||
use crate::mem;
|
||||
use crate::fmt;
|
||||
use core::u32;
|
||||
|
||||
use crate::sys_common::thread::*;
|
||||
|
||||
pub type Tid = u32;
|
||||
|
||||
/// Priority of a task
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
|
||||
pub struct Priority(u8);
|
||||
|
||||
impl Priority {
|
||||
pub const fn into(self) -> u8 {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub const fn from(x: u8) -> Self {
|
||||
Priority(x)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Priority {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
pub const NORMAL_PRIO: Priority = Priority::from(2);
|
||||
|
||||
extern "C" {
|
||||
fn sys_usleep(usecs: u64);
|
||||
fn sys_spawn(id: *mut Tid, func: extern "C" fn(usize), arg: usize, prio: u8, core_id: isize) -> i32;
|
||||
fn sys_join(id: Tid) -> i32;
|
||||
fn sys_yield();
|
||||
}
|
||||
|
||||
pub struct Thread {
|
||||
tid: Tid
|
||||
}
|
||||
|
||||
unsafe impl Send for Thread {}
|
||||
unsafe impl Sync for Thread {}
|
||||
|
||||
pub const DEFAULT_MIN_STACK_SIZE: usize = 262144;
|
||||
|
||||
impl Thread {
|
||||
pub unsafe fn new_with_coreid(_stack: usize, p: Box<dyn FnOnce()>, core_id: isize)
|
||||
-> io::Result<Thread>
|
||||
{
|
||||
let p = box p;
|
||||
let mut tid: Tid = u32::MAX;
|
||||
let ret = sys_spawn(&mut tid as *mut Tid, thread_start, &*p as *const _ as *const u8 as usize,
|
||||
Priority::into(NORMAL_PRIO), core_id);
|
||||
|
||||
return if ret == 0 {
|
||||
mem::forget(p); // ownership passed to pthread_create
|
||||
Ok(Thread { tid: tid })
|
||||
} else {
|
||||
Err(io::Error::new(io::ErrorKind::Other, "Unable to create thread!"))
|
||||
};
|
||||
|
||||
extern fn thread_start(main: usize) {
|
||||
unsafe {
|
||||
start_thread(main as *mut u8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe fn new(stack: usize, p: Box<dyn FnOnce()>)
|
||||
-> io::Result<Thread>
|
||||
{
|
||||
Thread::new_with_coreid(stack, p, -1 /* = no specific core */)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn yield_now() {
|
||||
unsafe {
|
||||
sys_yield();
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_name(_name: &CStr) {
|
||||
// nope
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sleep(dur: Duration) {
|
||||
unsafe {
|
||||
sys_usleep(dur.as_micros() as u64);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn join(self) {
|
||||
unsafe {
|
||||
let _ = sys_join(self.tid);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn id(&self) -> Tid { self.tid }
|
||||
|
||||
#[inline]
|
||||
pub fn into_id(self) -> Tid {
|
||||
let id = self.tid;
|
||||
mem::forget(self);
|
||||
id
|
||||
}
|
||||
}
|
||||
|
||||
pub mod guard {
|
||||
pub type Guard = !;
|
||||
pub unsafe fn current() -> Option<Guard> { None }
|
||||
pub unsafe fn init() -> Option<Guard> { None }
|
||||
}
|
61
src/libstd/sys/hermit/thread_local.rs
Normal file
61
src/libstd/sys/hermit/thread_local.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
#![allow(dead_code)] // not used on all platforms
|
||||
|
||||
use crate::collections::BTreeMap;
|
||||
use crate::ptr;
|
||||
use crate::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
pub type Key = usize;
|
||||
|
||||
type Dtor = unsafe extern fn(*mut u8);
|
||||
|
||||
static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
static mut KEYS: *mut BTreeMap<Key, Option<Dtor>> = ptr::null_mut();
|
||||
|
||||
#[thread_local]
|
||||
static mut LOCALS: *mut BTreeMap<Key, *mut u8> = ptr::null_mut();
|
||||
|
||||
unsafe fn keys() -> &'static mut BTreeMap<Key, Option<Dtor>> {
|
||||
if KEYS == ptr::null_mut() {
|
||||
KEYS = Box::into_raw(Box::new(BTreeMap::new()));
|
||||
}
|
||||
&mut *KEYS
|
||||
}
|
||||
|
||||
unsafe fn locals() -> &'static mut BTreeMap<Key, *mut u8> {
|
||||
if LOCALS == ptr::null_mut() {
|
||||
LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
|
||||
}
|
||||
&mut *LOCALS
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn create(dtor: Option<Dtor>) -> Key {
|
||||
let key = NEXT_KEY.fetch_add(1, Ordering::SeqCst);
|
||||
keys().insert(key, dtor);
|
||||
key
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn get(key: Key) -> *mut u8 {
|
||||
if let Some(&entry) = locals().get(&key) {
|
||||
entry
|
||||
} else {
|
||||
ptr::null_mut()
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn set(key: Key, value: *mut u8) {
|
||||
locals().insert(key, value);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn destroy(key: Key) {
|
||||
keys().remove(&key);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn requires_synchronized_create() -> bool {
|
||||
false
|
||||
}
|
188
src/libstd/sys/hermit/time.rs
Normal file
188
src/libstd/sys/hermit/time.rs
Normal file
|
@ -0,0 +1,188 @@
|
|||
#![allow(dead_code)]
|
||||
|
||||
use crate::time::Duration;
|
||||
use crate::cmp::Ordering;
|
||||
use crate::convert::TryInto;
|
||||
use core::hash::{Hash, Hasher};
|
||||
|
||||
const NSEC_PER_SEC: u64 = 1_000_000_000;
|
||||
const CLOCK_REALTIME: u64 = 1;
|
||||
const CLOCK_MONOTONIC: u64 = 4;
|
||||
|
||||
extern "C" {
|
||||
fn sys_clock_gettime(clock_id: u64, tp: *mut timespec) -> i32;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[repr(C)]
|
||||
pub struct timespec {
|
||||
pub tv_sec: i64,
|
||||
pub tv_nsec: i64,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
struct Timespec {
|
||||
t: timespec
|
||||
}
|
||||
|
||||
impl Timespec {
|
||||
const fn zero() -> Timespec {
|
||||
Timespec {
|
||||
t: timespec { tv_sec: 0, tv_nsec: 0 },
|
||||
}
|
||||
}
|
||||
|
||||
fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
|
||||
if self >= other {
|
||||
Ok(if self.t.tv_nsec >= other.t.tv_nsec {
|
||||
Duration::new((self.t.tv_sec - other.t.tv_sec) as u64,
|
||||
(self.t.tv_nsec - other.t.tv_nsec) as u32)
|
||||
} else {
|
||||
Duration::new((self.t.tv_sec - 1 - other.t.tv_sec) as u64,
|
||||
self.t.tv_nsec as u32 + (NSEC_PER_SEC as u32) -
|
||||
other.t.tv_nsec as u32)
|
||||
})
|
||||
} else {
|
||||
match other.sub_timespec(self) {
|
||||
Ok(d) => Err(d),
|
||||
Err(d) => Ok(d),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
|
||||
let mut secs = other
|
||||
.as_secs()
|
||||
.try_into() // <- target type would be `libc::time_t`
|
||||
.ok()
|
||||
.and_then(|secs| self.t.tv_sec.checked_add(secs))?;
|
||||
|
||||
// Nano calculations can't overflow because nanos are <1B which fit
|
||||
// in a u32.
|
||||
let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
|
||||
if nsec >= NSEC_PER_SEC as u32 {
|
||||
nsec -= NSEC_PER_SEC as u32;
|
||||
secs = secs.checked_add(1)?;
|
||||
}
|
||||
Some(Timespec {
|
||||
t: timespec {
|
||||
tv_sec: secs,
|
||||
tv_nsec: nsec as _,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
|
||||
let mut secs = other
|
||||
.as_secs()
|
||||
.try_into() // <- target type would be `libc::time_t`
|
||||
.ok()
|
||||
.and_then(|secs| self.t.tv_sec.checked_sub(secs))?;
|
||||
|
||||
// Similar to above, nanos can't overflow.
|
||||
let mut nsec = self.t.tv_nsec as i32 - other.subsec_nanos() as i32;
|
||||
if nsec < 0 {
|
||||
nsec += NSEC_PER_SEC as i32;
|
||||
secs = secs.checked_sub(1)?;
|
||||
}
|
||||
Some(Timespec {
|
||||
t: timespec {
|
||||
tv_sec: secs,
|
||||
tv_nsec: nsec as _,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Timespec {
|
||||
fn eq(&self, other: &Timespec) -> bool {
|
||||
self.t.tv_sec == other.t.tv_sec && self.t.tv_nsec == other.t.tv_nsec
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Timespec {}
|
||||
|
||||
impl PartialOrd for Timespec {
|
||||
fn partial_cmp(&self, other: &Timespec) -> Option<Ordering> {
|
||||
Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Timespec {
|
||||
fn cmp(&self, other: &Timespec) -> Ordering {
|
||||
let me = (self.t.tv_sec, self.t.tv_nsec);
|
||||
let other = (other.t.tv_sec, other.t.tv_nsec);
|
||||
me.cmp(&other)
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Timespec {
|
||||
fn hash<H : Hasher>(&self, state: &mut H) {
|
||||
self.t.tv_sec.hash(state);
|
||||
self.t.tv_nsec.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
pub struct Instant {
|
||||
t: Timespec,
|
||||
}
|
||||
|
||||
impl Instant {
|
||||
pub fn now() -> Instant {
|
||||
let mut time: Timespec = Timespec::zero();
|
||||
let _ = unsafe { sys_clock_gettime(CLOCK_MONOTONIC, &mut time.t as *mut timespec) };
|
||||
|
||||
Instant { t: time }
|
||||
}
|
||||
|
||||
pub const fn zero() -> Instant {
|
||||
Instant { t: Timespec::zero() }
|
||||
}
|
||||
|
||||
pub fn actually_monotonic() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
|
||||
self.t.sub_timespec(&other.t).ok()
|
||||
}
|
||||
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant { t: self.t.checked_add_duration(other)? })
|
||||
}
|
||||
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
|
||||
Some(Instant { t: self.t.checked_sub_duration(other)? })
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub struct SystemTime {
|
||||
t: Timespec,
|
||||
}
|
||||
|
||||
pub const UNIX_EPOCH: SystemTime = SystemTime {
|
||||
t: Timespec::zero(),
|
||||
};
|
||||
|
||||
impl SystemTime {
|
||||
pub fn now() -> SystemTime {
|
||||
let mut time: Timespec = Timespec::zero();
|
||||
let _ = unsafe { sys_clock_gettime(CLOCK_REALTIME, &mut time.t as *mut timespec) };
|
||||
|
||||
SystemTime { t: time }
|
||||
}
|
||||
|
||||
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
self.t.sub_timespec(&other.t)
|
||||
}
|
||||
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime { t: self.t.checked_add_duration(other)? })
|
||||
}
|
||||
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime { t: self.t.checked_sub_duration(other)? })
|
||||
}
|
||||
}
|
|
@ -35,6 +35,9 @@ cfg_if::cfg_if! {
|
|||
} else if #[cfg(target_os = "cloudabi")] {
|
||||
mod cloudabi;
|
||||
pub use self::cloudabi::*;
|
||||
} else if #[cfg(target_os = "hermit")] {
|
||||
mod hermit;
|
||||
pub use self::hermit::*;
|
||||
} else if #[cfg(target_os = "wasi")] {
|
||||
mod wasi;
|
||||
pub use self::wasi::*;
|
||||
|
@ -60,6 +63,7 @@ cfg_if::cfg_if! {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::ext as unix_ext;
|
||||
} else if #[cfg(any(target_os = "cloudabi",
|
||||
target_os = "hermit",
|
||||
target_arch = "wasm32",
|
||||
all(target_vendor = "fortanix", target_env = "sgx")))] {
|
||||
// On CloudABI and wasm right now the module below doesn't compile
|
||||
|
|
|
@ -53,7 +53,6 @@ unsafe impl GlobalAlloc for System {
|
|||
}
|
||||
|
||||
#[cfg(any(target_os = "android",
|
||||
target_os = "hermit",
|
||||
target_os = "redox",
|
||||
target_os = "solaris"))]
|
||||
#[inline]
|
||||
|
@ -79,7 +78,6 @@ unsafe fn aligned_malloc(layout: &Layout) -> *mut u8 {
|
|||
}
|
||||
|
||||
#[cfg(not(any(target_os = "android",
|
||||
target_os = "hermit",
|
||||
target_os = "redox",
|
||||
target_os = "solaris")))]
|
||||
#[inline]
|
||||
|
|
|
@ -56,7 +56,6 @@ impl DoubleEndedIterator for Args {
|
|||
target_os = "haiku",
|
||||
target_os = "l4re",
|
||||
target_os = "fuchsia",
|
||||
target_os = "hermit",
|
||||
target_os = "redox"))]
|
||||
mod imp {
|
||||
use crate::os::unix::prelude::*;
|
||||
|
|
|
@ -31,7 +31,6 @@ impl Condvar {
|
|||
target_os = "ios",
|
||||
target_os = "l4re",
|
||||
target_os = "android",
|
||||
target_os = "hermit",
|
||||
target_os = "redox"))]
|
||||
pub unsafe fn init(&mut self) {}
|
||||
|
||||
|
@ -39,7 +38,6 @@ impl Condvar {
|
|||
target_os = "ios",
|
||||
target_os = "l4re",
|
||||
target_os = "android",
|
||||
target_os = "hermit",
|
||||
target_os = "redox")))]
|
||||
pub unsafe fn init(&mut self) {
|
||||
use crate::mem::MaybeUninit;
|
||||
|
@ -78,8 +76,7 @@ impl Condvar {
|
|||
// from changes made to the system time.
|
||||
#[cfg(not(any(target_os = "macos",
|
||||
target_os = "ios",
|
||||
target_os = "android",
|
||||
target_os = "hermit")))]
|
||||
target_os = "android")))]
|
||||
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
|
||||
use crate::mem;
|
||||
|
||||
|
@ -109,7 +106,7 @@ impl Condvar {
|
|||
// This implementation is modeled after libcxx's condition_variable
|
||||
// https://github.com/llvm-mirror/libcxx/blob/release_35/src/condition_variable.cpp#L46
|
||||
// https://github.com/llvm-mirror/libcxx/blob/release_35/include/__mutex_base#L367
|
||||
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "android", target_os = "hermit"))]
|
||||
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
|
||||
pub unsafe fn wait_timeout(&self, mutex: &Mutex, mut dur: Duration) -> bool {
|
||||
use crate::ptr;
|
||||
use crate::time::Instant;
|
||||
|
|
|
@ -152,17 +152,6 @@ pub mod os {
|
|||
pub const EXE_EXTENSION: &str = "";
|
||||
}
|
||||
|
||||
#[cfg(target_os = "hermit")]
|
||||
pub mod os {
|
||||
pub const FAMILY: &str = "unix";
|
||||
pub const OS: &str = "hermit";
|
||||
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";
|
||||
|
|
|
@ -319,12 +319,12 @@ impl DirEntry {
|
|||
lstat(&self.path())
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "solaris", target_os = "haiku", target_os = "hermit"))]
|
||||
#[cfg(any(target_os = "solaris", target_os = "haiku"))]
|
||||
pub fn file_type(&self) -> io::Result<FileType> {
|
||||
lstat(&self.path()).map(|m| m.file_type())
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "solaris", target_os = "haiku", target_os = "hermit")))]
|
||||
#[cfg(not(any(target_os = "solaris", target_os = "haiku")))]
|
||||
pub fn file_type(&self) -> io::Result<FileType> {
|
||||
match self.entry.d_type {
|
||||
libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }),
|
||||
|
@ -347,7 +347,6 @@ impl DirEntry {
|
|||
target_os = "haiku",
|
||||
target_os = "l4re",
|
||||
target_os = "fuchsia",
|
||||
target_os = "hermit",
|
||||
target_os = "redox"))]
|
||||
pub fn ino(&self) -> u64 {
|
||||
self.entry.d_ino as u64
|
||||
|
@ -378,8 +377,7 @@ impl DirEntry {
|
|||
target_os = "linux",
|
||||
target_os = "emscripten",
|
||||
target_os = "l4re",
|
||||
target_os = "haiku",
|
||||
target_os = "hermit"))]
|
||||
target_os = "haiku"))]
|
||||
fn name_bytes(&self) -> &[u8] {
|
||||
unsafe {
|
||||
CStr::from_ptr(self.entry.d_name.as_ptr()).to_bytes()
|
||||
|
|
|
@ -16,7 +16,6 @@ use crate::io::ErrorKind;
|
|||
#[cfg(all(not(rustdoc), target_os = "emscripten"))] pub use crate::os::emscripten as platform;
|
||||
#[cfg(all(not(rustdoc), target_os = "fuchsia"))] pub use crate::os::fuchsia as platform;
|
||||
#[cfg(all(not(rustdoc), target_os = "l4re"))] pub use crate::os::linux as platform;
|
||||
#[cfg(all(not(rustdoc), target_os = "hermit"))] pub use crate::os::hermit as platform;
|
||||
#[cfg(all(not(rustdoc), target_os = "redox"))] pub use crate::os::redox as platform;
|
||||
|
||||
pub use self::rand::hashmap_random_keys;
|
||||
|
|
|
@ -43,7 +43,6 @@ extern {
|
|||
#[cfg_attr(any(target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "android",
|
||||
target_os = "hermit",
|
||||
target_os = "redox",
|
||||
target_env = "newlib"),
|
||||
link_name = "__errno")]
|
||||
|
@ -394,7 +393,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
|
|||
crate::fs::read_to_string("sys:exe").map(PathBuf::from)
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "fuchsia", target_os = "l4re", target_os = "hermit"))]
|
||||
#[cfg(any(target_os = "fuchsia", target_os = "l4re"))]
|
||||
pub fn current_exe() -> io::Result<PathBuf> {
|
||||
use crate::io::ErrorKind;
|
||||
Err(io::Error::new(ErrorKind::Other, "Not yet implemented!"))
|
||||
|
|
|
@ -140,7 +140,6 @@ impl Thread {
|
|||
target_os = "haiku",
|
||||
target_os = "l4re",
|
||||
target_os = "emscripten",
|
||||
target_os = "hermit",
|
||||
target_os = "redox"))]
|
||||
pub fn set_name(_name: &CStr) {
|
||||
// Newlib, Illumos, Haiku, and Emscripten have no way to set a thread name.
|
||||
|
|
|
@ -371,9 +371,9 @@ mod inner {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "dragonfly", target_os = "hermit")))]
|
||||
#[cfg(not(target_os = "dragonfly"))]
|
||||
pub type clock_t = libc::c_int;
|
||||
#[cfg(any(target_os = "dragonfly", target_os = "hermit"))]
|
||||
#[cfg(target_os = "dragonfly")]
|
||||
pub type clock_t = libc::c_ulong;
|
||||
|
||||
fn now(clock: clock_t) -> Timespec {
|
||||
|
|
|
@ -49,6 +49,7 @@ pub mod mutex;
|
|||
unix,
|
||||
target_os = "redox",
|
||||
target_os = "cloudabi",
|
||||
target_os = "hermit",
|
||||
target_arch = "wasm32",
|
||||
all(target_vendor = "fortanix", target_env = "sgx")))]
|
||||
pub mod os_str_bytes;
|
||||
|
@ -67,6 +68,7 @@ pub mod fs;
|
|||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(target_os = "cloudabi",
|
||||
target_os = "l4re",
|
||||
target_os = "hermit",
|
||||
all(target_arch = "wasm32", not(target_os = "emscripten")),
|
||||
all(target_vendor = "fortanix", target_env = "sgx")))] {
|
||||
pub use crate::sys::net;
|
||||
|
|
|
@ -1052,6 +1052,7 @@ fn use_color(opts: &TestOpts) -> bool {
|
|||
|
||||
#[cfg(any(
|
||||
target_os = "cloudabi",
|
||||
target_os = "hermit",
|
||||
all(target_arch = "wasm32", not(target_os = "emscripten")),
|
||||
all(target_vendor = "fortanix", target_env = "sgx")
|
||||
))]
|
||||
|
@ -1308,6 +1309,12 @@ fn get_concurrency() -> usize {
|
|||
1
|
||||
}
|
||||
|
||||
#[cfg(target_os = "hermit")]
|
||||
fn num_cpus() -> usize {
|
||||
// FIXME: Implement num_cpus on HermitCore
|
||||
1
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
all(target_arch = "wasm32", not(target_os = "emscripten")),
|
||||
all(target_vendor = "fortanix", target_env = "sgx")
|
||||
|
|
|
@ -43,6 +43,8 @@ fn main() {
|
|||
println!("cargo:rustc-link-lib=gcc_s");
|
||||
} else if target.contains("redox") {
|
||||
// redox is handled in lib.rs
|
||||
} else if target.contains("hermit") {
|
||||
//println!("cargo:rustc-link-lib=unwind");
|
||||
} else if target.contains("cloudabi") {
|
||||
println!("cargo:rustc-link-lib=unwind");
|
||||
}
|
||||
|
|
|
@ -1,7 +1,26 @@
|
|||
#![allow(nonstandard_style)]
|
||||
|
||||
#[cfg(not(target_os = "hermit"))]
|
||||
use libc::{c_int, c_void, uintptr_t};
|
||||
|
||||
#[cfg(target_os = "hermit")]
|
||||
pub type c_int = i32;
|
||||
|
||||
#[cfg(target_os = "hermit")]
|
||||
pub type uintptr_t = usize;
|
||||
|
||||
#[cfg(target_os = "hermit")]
|
||||
#[repr(u8)]
|
||||
#[allow(missing_copy_implementations)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
pub enum c_void {
|
||||
// Two dummy variants so the #[repr] attribute can be used.
|
||||
#[doc(hidden)]
|
||||
__variant1,
|
||||
#[doc(hidden)]
|
||||
__variant2,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum _Unwind_Reason_Code {
|
||||
|
|
|
@ -52,6 +52,7 @@ static TARGETS: &[&str] = &[
|
|||
"aarch64-linux-android",
|
||||
"aarch64-pc-windows-msvc",
|
||||
"aarch64-unknown-cloudabi",
|
||||
"aarch64-unknown-hermit",
|
||||
"aarch64-unknown-linux-gnu",
|
||||
"aarch64-unknown-linux-musl",
|
||||
"aarch64-unknown-redox",
|
||||
|
@ -136,6 +137,7 @@ static TARGETS: &[&str] = &[
|
|||
"x86_64-unknown-linux-musl",
|
||||
"x86_64-unknown-netbsd",
|
||||
"x86_64-unknown-redox",
|
||||
"x86_64-unknown-hermit",
|
||||
];
|
||||
|
||||
static DOCS_TARGETS: &[&str] = &[
|
||||
|
|
Loading…
Add table
Reference in a new issue