about summary refs log tree commit diff
path: root/library/std/src/sys/pal/hermit/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/sys/pal/hermit/mod.rs')
-rw-r--r--library/std/src/sys/pal/hermit/mod.rs207
1 files changed, 207 insertions, 0 deletions
diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs
new file mode 100644
index 00000000000..abd7eb353f8
--- /dev/null
+++ b/library/std/src/sys/pal/hermit/mod.rs
@@ -0,0 +1,207 @@
+//! 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!
+
+#![allow(missing_docs, nonstandard_style, unsafe_op_in_unsafe_fn)]
+
+use crate::os::raw::c_char;
+
+pub mod alloc;
+pub mod args;
+#[path = "../unix/cmath.rs"]
+pub mod cmath;
+pub mod env;
+pub mod fd;
+pub mod fs;
+pub mod futex;
+#[path = "../unsupported/io.rs"]
+pub mod io;
+pub mod memchr;
+pub mod net;
+pub mod os;
+#[path = "../unix/os_str.rs"]
+pub mod os_str;
+#[path = "../unix/path.rs"]
+pub mod path;
+#[path = "../unsupported/pipe.rs"]
+pub mod pipe;
+#[path = "../unsupported/process.rs"]
+pub mod process;
+pub mod stdio;
+pub mod thread;
+pub mod thread_local_dtor;
+#[path = "../unsupported/thread_local_key.rs"]
+pub mod thread_local_key;
+pub mod time;
+
+#[path = "../unix/locks"]
+pub mod locks {
+    mod futex_condvar;
+    mod futex_mutex;
+    mod futex_rwlock;
+    pub(crate) use futex_condvar::Condvar;
+    pub(crate) use futex_mutex::Mutex;
+    pub(crate) use futex_rwlock::RwLock;
+}
+
+use crate::io::ErrorKind;
+use crate::os::hermit::abi;
+
+pub fn unsupported<T>() -> crate::io::Result<T> {
+    Err(unsupported_err())
+}
+
+pub fn unsupported_err() -> crate::io::Error {
+    crate::io::const_io_error!(
+        crate::io::ErrorKind::Unsupported,
+        "operation not supported on HermitCore yet",
+    )
+}
+
+pub fn abort_internal() -> ! {
+    unsafe {
+        abi::abort();
+    }
+}
+
+pub fn hashmap_random_keys() -> (u64, u64) {
+    let mut buf = [0; 16];
+    let mut slice = &mut buf[..];
+    while !slice.is_empty() {
+        let res = cvt(unsafe { abi::read_entropy(slice.as_mut_ptr(), slice.len(), 0) })
+            .expect("failed to generate random hashmap keys");
+        slice = &mut slice[res as usize..];
+    }
+
+    let key1 = buf[..8].try_into().unwrap();
+    let key2 = buf[8..].try_into().unwrap();
+    (u64::from_ne_bytes(key1), u64::from_ne_bytes(key2))
+}
+
+// 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 extern "C" fn __rust_abort() {
+    abort_internal();
+}
+
+// SAFETY: must be called only once during runtime initialization.
+// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
+pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) {
+    args::init(argc, argv);
+}
+
+// SAFETY: must be called only once during runtime cleanup.
+// NOTE: this is not guaranteed to run, for example when the program aborts.
+pub unsafe fn cleanup() {}
+
+#[cfg(not(test))]
+#[no_mangle]
+pub unsafe extern "C" fn runtime_entry(
+    argc: i32,
+    argv: *const *const c_char,
+    env: *const *const c_char,
+) -> ! {
+    use crate::sys::hermit::thread_local_dtor::run_dtors;
+    extern "C" {
+        fn main(argc: isize, argv: *const *const c_char) -> i32;
+    }
+
+    // initialize environment
+    os::init_environment(env as *const *const i8);
+
+    let result = main(argc as isize, argv);
+
+    run_dtors();
+    abi::exit(result);
+}
+
+#[inline]
+pub(crate) fn is_interrupted(errno: i32) -> bool {
+    errno == abi::errno::EINTR
+}
+
+pub fn decode_error_kind(errno: i32) -> ErrorKind {
+    match errno {
+        abi::errno::EACCES => ErrorKind::PermissionDenied,
+        abi::errno::EADDRINUSE => ErrorKind::AddrInUse,
+        abi::errno::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
+        abi::errno::EAGAIN => ErrorKind::WouldBlock,
+        abi::errno::ECONNABORTED => ErrorKind::ConnectionAborted,
+        abi::errno::ECONNREFUSED => ErrorKind::ConnectionRefused,
+        abi::errno::ECONNRESET => ErrorKind::ConnectionReset,
+        abi::errno::EEXIST => ErrorKind::AlreadyExists,
+        abi::errno::EINTR => ErrorKind::Interrupted,
+        abi::errno::EINVAL => ErrorKind::InvalidInput,
+        abi::errno::ENOENT => ErrorKind::NotFound,
+        abi::errno::ENOTCONN => ErrorKind::NotConnected,
+        abi::errno::EPERM => ErrorKind::PermissionDenied,
+        abi::errno::EPIPE => ErrorKind::BrokenPipe,
+        abi::errno::ETIMEDOUT => ErrorKind::TimedOut,
+        _ => ErrorKind::Uncategorized,
+    }
+}
+
+#[doc(hidden)]
+pub trait IsNegative {
+    fn is_negative(&self) -> bool;
+    fn negate(&self) -> i32;
+}
+
+macro_rules! impl_is_negative {
+    ($($t:ident)*) => ($(impl IsNegative for $t {
+        fn is_negative(&self) -> bool {
+            *self < 0
+        }
+
+        fn negate(&self) -> i32 {
+            i32::try_from(-(*self)).unwrap()
+        }
+    })*)
+}
+
+impl IsNegative for i32 {
+    fn is_negative(&self) -> bool {
+        *self < 0
+    }
+
+    fn negate(&self) -> i32 {
+        -(*self)
+    }
+}
+impl_is_negative! { i8 i16 i64 isize }
+
+pub fn cvt<T: IsNegative>(t: T) -> crate::io::Result<T> {
+    if t.is_negative() {
+        let e = decode_error_kind(t.negate());
+        Err(crate::io::Error::from(e))
+    } else {
+        Ok(t)
+    }
+}
+
+pub fn cvt_r<T, F>(mut f: F) -> crate::io::Result<T>
+where
+    T: IsNegative,
+    F: FnMut() -> T,
+{
+    loop {
+        match cvt(f()) {
+            Err(ref e) if e.is_interrupted() => {}
+            other => return other,
+        }
+    }
+}