diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/hermit-abi/src | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/hermit-abi/src')
-rw-r--r-- | third_party/rust/hermit-abi/src/lib.rs | 386 | ||||
-rw-r--r-- | third_party/rust/hermit-abi/src/tcpstream.rs | 110 |
2 files changed, 496 insertions, 0 deletions
diff --git a/third_party/rust/hermit-abi/src/lib.rs b/third_party/rust/hermit-abi/src/lib.rs new file mode 100644 index 0000000000..c9b3e4687a --- /dev/null +++ b/third_party/rust/hermit-abi/src/lib.rs @@ -0,0 +1,386 @@ +//! `hermit-abi` is small interface to call functions from the unikernel +//! [RustyHermit](https://github.com/hermitcore/libhermit-rs). + +#![cfg_attr(feature = "rustc-dep-of-std", no_std)] +#![feature(const_raw_ptr_to_usize_cast)] +extern crate libc; + +pub mod tcpstream; + +use libc::c_void; + +// sysmbols, which are part of the library operating system +extern "C" { + fn sys_get_processor_count() -> usize; + 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); + 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; + 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; + 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; + fn sys_getpid() -> u32; + fn sys_exit(arg: i32) -> !; + fn sys_abort() -> !; + 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_spawn2( + func: extern "C" fn(usize), + arg: usize, + prio: u8, + stack_size: usize, + core_id: isize, + ) -> Tid; + fn sys_join(id: Tid) -> i32; + fn sys_yield(); + fn sys_clock_gettime(clock_id: u64, tp: *mut timespec) -> i32; + fn sys_open(name: *const i8, flags: i32, mode: i32) -> i32; + fn sys_unlink(name: *const i8) -> i32; + fn sys_network_init() -> i32; +} + +/// A thread handle type +pub type Tid = u32; + +/// Priority of a thread +#[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) + } +} + +pub const HIGH_PRIO: Priority = Priority::from(3); +pub const NORMAL_PRIO: Priority = Priority::from(2); +pub const LOW_PRIO: Priority = Priority::from(1); + +/// A handle, identifying a socket +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)] +pub struct Handle(usize); + +pub const NSEC_PER_SEC: u64 = 1_000_000_000; +pub const CLOCK_REALTIME: u64 = 1; +pub const CLOCK_MONOTONIC: u64 = 4; +pub const STDIN_FILENO: libc::c_int = 0; +pub const STDOUT_FILENO: libc::c_int = 1; +pub const STDERR_FILENO: libc::c_int = 2; +pub const O_RDONLY: i32 = 0o0; +pub const O_WRONLY: i32 = 0o1; +pub const O_RDWR: i32 = 0o2; +pub const O_CREAT: i32 = 0o100; +pub const O_EXCL: i32 = 0o200; +pub const O_TRUNC: i32 = 0o1000; +pub const O_APPEND: i32 = 0o2000; + +/// returns true if file descriptor `fd` is a tty +pub fn isatty(_fd: libc::c_int) -> bool { + false +} + +/// intialize the network stack +pub fn network_init() -> i32 { + unsafe { sys_network_init() } +} + +/// `timespec` is used by `clock_gettime` to retrieve the +/// current time +#[derive(Copy, Clone, Debug)] +#[repr(C)] +pub struct timespec { + /// seconds + pub tv_sec: i64, + /// nanoseconds + pub tv_nsec: i64, +} + +/// determines the number of activated processors +#[inline(always)] +pub unsafe fn get_processor_count() -> usize { + sys_get_processor_count() +} + +#[doc(hidden)] +#[inline(always)] +pub unsafe fn malloc(size: usize, align: usize) -> *mut u8 { + sys_malloc(size, align) +} + +#[doc(hidden)] +#[inline(always)] +pub unsafe fn realloc(ptr: *mut u8, size: usize, align: usize, new_size: usize) -> *mut u8 { + sys_realloc(ptr, size, align, new_size) +} + +#[doc(hidden)] +#[inline(always)] +pub unsafe fn free(ptr: *mut u8, size: usize, align: usize) { + sys_free(ptr, size, align) +} + +#[inline(always)] +pub unsafe fn notify(id: usize, count: i32) -> i32 { + sys_notify(id, count) +} + +#[doc(hidden)] +#[inline(always)] +pub unsafe fn add_queue(id: usize, timeout_ns: i64) -> i32 { + sys_add_queue(id, timeout_ns) +} + +#[doc(hidden)] +#[inline(always)] +pub unsafe fn wait(id: usize) -> i32 { + sys_wait(id) +} + +#[doc(hidden)] +#[inline(always)] +pub unsafe fn destroy_queue(id: usize) -> i32 { + sys_destroy_queue(id) +} + +/// read from a file descriptor +/// +/// read() attempts to read `len` bytes of data from the object +/// referenced by the descriptor `fd` into the buffer pointed +/// to by `buf`. +#[inline(always)] +pub unsafe fn read(fd: i32, buf: *mut u8, len: usize) -> isize { + sys_read(fd, buf, len) +} + +/// write to a file descriptor +/// +/// write() attempts to write `len` of data to the object +/// referenced by the descriptor `fd` from the +/// buffer pointed to by `buf`. +#[inline(always)] +pub unsafe fn write(fd: i32, buf: *const u8, len: usize) -> isize { + sys_write(fd, buf, len) +} + +/// close a file descriptor +/// +/// The close() call deletes a file descriptor `fd` from the object +/// reference table. +#[inline(always)] +pub unsafe fn close(fd: i32) -> i32 { + sys_close(fd) +} + +/// sem_init() initializes the unnamed semaphore at the address +/// pointed to by `sem`. The `value` argument specifies the +/// initial value for the semaphore. +#[inline(always)] +pub unsafe fn sem_init(sem: *mut *const c_void, value: u32) -> i32 { + sys_sem_init(sem, value) +} + +/// sem_destroy() frees the unnamed semaphore at the address +/// pointed to by `sem`. +#[inline(always)] +pub unsafe fn sem_destroy(sem: *const c_void) -> i32 { + sys_sem_destroy(sem) +} + +/// sem_post() increments the semaphore pointed to by `sem`. +/// If the semaphore's value consequently becomes greater +/// than zero, then another thread blocked in a sem_wait call +/// will be woken up and proceed to lock the semaphore. +#[inline(always)] +pub unsafe fn sem_post(sem: *const c_void) -> i32 { + sys_sem_post(sem) +} + +/// try to decrement a semaphore +/// +/// sem_trywait() is the same as sem_timedwait(), except that +/// if the decrement cannot be immediately performed, then call +/// returns a negative value instead of blocking. +#[inline(always)] +pub unsafe fn sem_trywait(sem: *const c_void) -> i32 { + sys_sem_trywait(sem) +} + +/// decrement a semaphore +/// +/// sem_timedwait() decrements the semaphore pointed to by `sem`. +/// If the semaphore's value is greater than zero, then the +/// the function returns immediately. If the semaphore currently +/// has the value zero, then the call blocks until either +/// it becomes possible to perform the decrement of the time limit +/// to wait for the semaphore is expired. A time limit `ms` of +/// means infinity waiting time. +#[inline(always)] +pub unsafe fn sem_timedwait(sem: *const c_void, ms: u32) -> i32 { + sys_sem_timedwait(sem, ms) +} + +#[doc(hidden)] +#[inline(always)] +pub unsafe fn recmutex_init(recmutex: *mut *const c_void) -> i32 { + sys_recmutex_init(recmutex) +} + +#[doc(hidden)] +#[inline(always)] +pub unsafe fn recmutex_destroy(recmutex: *const c_void) -> i32 { + sys_recmutex_destroy(recmutex) +} + +#[doc(hidden)] +#[inline(always)] +pub unsafe fn recmutex_lock(recmutex: *const c_void) -> i32 { + sys_recmutex_lock(recmutex) +} + +#[doc(hidden)] +#[inline(always)] +pub unsafe fn recmutex_unlock(recmutex: *const c_void) -> i32 { + sys_recmutex_unlock(recmutex) +} + +/// Determines the id of the current thread +#[inline(always)] +pub unsafe fn getpid() -> u32 { + sys_getpid() +} + +/// cause normal termination and return `arg` +/// to the host system +#[inline(always)] +pub unsafe fn exit(arg: i32) -> ! { + sys_exit(arg) +} + +/// cause abnormal termination +#[inline(always)] +pub unsafe fn abort() -> ! { + sys_abort() +} + +/// suspend execution for microsecond intervals +/// +/// The usleep() function suspends execution of the calling +/// thread for (at least) `usecs` microseconds. +#[inline(always)] +pub unsafe fn usleep(usecs: u64) { + sys_usleep(usecs) +} + +/// spawn a new thread +/// +/// spawn() starts a new thread. The new thread starts execution +/// by invoking `func(usize)`; `arg` is passed as the argument +/// to `func`. `prio` defines the priority of the new thread, +/// which can be between `LOW_PRIO` and `HIGH_PRIO`. +/// `core_id` defines the core, where the thread is located. +/// A negative value give the operating system the possibility +/// to select the core by its own. +#[inline(always)] +pub unsafe fn spawn( + id: *mut Tid, + func: extern "C" fn(usize), + arg: usize, + prio: u8, + core_id: isize, +) -> i32 { + sys_spawn(id, func, arg, prio, core_id) +} + +/// spawn a new thread with user-specified stack size +/// +/// spawn2() starts a new thread. The new thread starts execution +/// by invoking `func(usize)`; `arg` is passed as the argument +/// to `func`. `prio` defines the priority of the new thread, +/// which can be between `LOW_PRIO` and `HIGH_PRIO`. +/// `core_id` defines the core, where the thread is located. +/// A negative value give the operating system the possibility +/// to select the core by its own. +/// In contrast to spawn(), spawn2() is able to define the +/// stack size. +#[inline(always)] +pub unsafe fn spawn2( + func: extern "C" fn(usize), + arg: usize, + prio: u8, + stack_size: usize, + core_id: isize, +) -> Tid { + sys_spawn2(func, arg, prio, stack_size, core_id) +} + +/// join with a terminated thread +/// +/// The join() function waits for the thread specified by `id` +/// to terminate. +#[inline(always)] +pub unsafe fn join(id: Tid) -> i32 { + sys_join(id) +} + +/// yield the processor +/// +/// causes the calling thread to relinquish the CPU. The thread +/// is moved to the end of the queue for its static priority. +#[inline(always)] +pub unsafe fn yield_now() { + sys_yield() +} + +/// get current time +/// +/// The clock_gettime() functions allow the calling thread +/// to retrieve the value used by a clock which is specified +/// by `clock_id`. +/// +/// `CLOCK_REALTIME`: the system's real time clock, +/// expressed as the amount of time since the Epoch. +/// +/// `CLOCK_MONOTONIC`: clock that increments monotonically, +/// tracking the time since an arbitrary point +#[inline(always)] +pub unsafe fn clock_gettime(clock_id: u64, tp: *mut timespec) -> i32 { + sys_clock_gettime(clock_id, tp) +} + +/// open and possibly create a file +/// +/// The open() system call opens the file specified by `name`. +/// If the specified file does not exist, it may optionally +/// be created by open(). +#[inline(always)] +pub unsafe fn open(name: *const i8, flags: i32, mode: i32) -> i32 { + sys_open(name, flags, mode) +} + +/// delete the file it refers to `name` +#[inline(always)] +pub unsafe fn unlink(name: *const i8) -> i32 { + sys_unlink(name) +} diff --git a/third_party/rust/hermit-abi/src/tcpstream.rs b/third_party/rust/hermit-abi/src/tcpstream.rs new file mode 100644 index 0000000000..d8f31b7d0d --- /dev/null +++ b/third_party/rust/hermit-abi/src/tcpstream.rs @@ -0,0 +1,110 @@ +//! `tcpstream` provide an interface to the network stack + +use crate::Handle; + +extern "Rust" { + fn sys_tcp_stream_connect(ip: &[u8], port: u16, timeout: Option<u64>) -> Result<Handle, ()>; + fn sys_tcp_stream_close(handle: Handle) -> Result<(), ()>; + fn sys_tcp_stream_read(handle: Handle, buffer: &mut [u8]) -> Result<usize, ()>; + fn sys_tcp_stream_write(handle: Handle, buffer: &[u8]) -> Result<usize, ()>; + fn sys_tcp_stream_set_read_timeout(handle: Handle, timeout: Option<u64>) -> Result<(), ()>; + fn sys_tcp_stream_get_read_timeout(handle: Handle) -> Result<Option<u64>, ()>; + fn sys_tcp_stream_set_write_timeout(handle: Handle, timeout: Option<u64>) -> Result<(), ()>; + fn sys_tcp_stream_get_write_timeout(handle: Handle) -> Result<Option<u64>, ()>; + fn sys_tcp_stream_duplicate(handle: Handle) -> Result<Handle, ()>; + fn sys_tcp_stream_peek(handle: Handle, buf: &mut [u8]) -> Result<usize, ()>; + fn sys_tcp_stream_set_nonblocking(handle: Handle, mode: bool) -> Result<(), ()>; + fn sys_tcp_stream_set_tll(handle: Handle, ttl: u32) -> Result<(), ()>; + fn sys_tcp_stream_get_tll(handle: Handle) -> Result<u32, ()>; + fn sys_tcp_stream_shutdown(handle: Handle, how: i32) -> Result<(), ()>; +} + +/// Opens a TCP connection to a remote host. +#[inline(always)] +pub fn connect(ip: &[u8], port: u16, timeout: Option<u64>) -> Result<Handle, ()> { + unsafe { sys_tcp_stream_connect(ip, port, timeout) } +} + +/// Close a TCP connection +#[inline(always)] +pub fn close(handle: Handle) -> Result<(), ()> { + unsafe { sys_tcp_stream_close(handle) } +} + +#[inline(always)] +pub fn duplicate(handle: Handle) -> Result<Handle, ()> { + unsafe { sys_tcp_stream_duplicate(handle) } +} + +#[inline(always)] +pub fn peek(handle: Handle, buf: &mut [u8]) -> Result<usize, ()> { + unsafe { sys_tcp_stream_peek(handle, buf) } +} + +#[inline(always)] +pub fn read(handle: Handle, buffer: &mut [u8]) -> Result<usize, ()> { + unsafe { sys_tcp_stream_read(handle, buffer) } +} + +#[inline(always)] +pub fn write(handle: Handle, buffer: &[u8]) -> Result<usize, ()> { + unsafe { sys_tcp_stream_write(handle, buffer) } +} + +#[inline(always)] +pub fn set_read_timeout(handle: Handle, timeout: Option<u64>) -> Result<(), ()> { + unsafe { sys_tcp_stream_set_read_timeout(handle, timeout) } +} + +#[inline(always)] +pub fn set_write_timeout(handle: Handle, timeout: Option<u64>) -> Result<(), ()> { + unsafe { sys_tcp_stream_set_write_timeout(handle, timeout) } +} + +#[inline(always)] +pub fn get_read_timeout(handle: Handle) -> Result<Option<u64>, ()> { + unsafe { sys_tcp_stream_get_read_timeout(handle) } +} + +#[inline(always)] +pub fn get_write_timeout(handle: Handle) -> Result<Option<u64>, ()> { + unsafe { sys_tcp_stream_get_write_timeout(handle) } +} + +#[inline(always)] +pub fn set_nodelay(_: Handle, mode: bool) -> Result<(), ()> { + // smoltcp does not support Nagle's algorithm + // => to enable Nagle's algorithm ins't possineö + if mode == true { + Ok(()) + } else { + Err(()) + } +} + +#[inline(always)] +pub fn nodelay(_: Handle) -> Result<bool, ()> { + // smoltcp does not support Nagle's algorithm + // => return always true + Ok(true) +} + +#[inline(always)] +pub fn set_nonblocking(handle: Handle, mode: bool) -> Result<(), ()> { + unsafe { sys_tcp_stream_set_nonblocking(handle, mode) } +} + +#[inline(always)] +pub fn set_tll(handle: Handle, ttl: u32) -> Result<(), ()> { + unsafe { sys_tcp_stream_set_tll(handle, ttl) } +} + +#[inline(always)] +pub fn get_tll(handle: Handle) -> Result<u32, ()> { + unsafe { sys_tcp_stream_get_tll(handle) } +} + +#[inline(always)] +pub fn shutdown(handle: Handle, how: i32) -> Result<(), ()> { + unsafe { sys_tcp_stream_shutdown(handle, how) } +} |