Add more ABI functions and some scheme APIs.

This commit is contained in:
4lDO2
2023-10-12 20:08:07 +02:00
parent eaf682b6b4
commit 619de8a521
2 changed files with 143 additions and 8 deletions
+5
View File
@@ -7,6 +7,11 @@ license = "MIT"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = ["scheme", "call"]
scheme = ["call"]
call = []
[dependencies]
bitflags = "2"
libc = "0.2"
+138 -8
View File
@@ -9,6 +9,10 @@ pub mod flag {
pub use libc::{CLOCK_MONOTONIC, CLOCK_REALTIME};
pub use libc::{SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK};
pub use libc::{SIGUSR1, SIGUSR2};
#[cfg(target_os = "redox")]
pub use libc::{O_SHLOCK, O_EXLOCK};
@@ -21,6 +25,8 @@ pub mod errno {
}
pub mod data {
pub use libc::timespec as TimeSpec;
pub use libc::sigaction as SigAction;
pub use libc::sigset_t as SigSet;
}
type RawResult = usize;
@@ -40,18 +46,30 @@ extern "C" {
fn redox_fpath_v1(fd: usize, dst_base: *mut u8, dst_len: usize) -> RawResult;
fn redox_close_v1(fd: usize) -> RawResult;
// NOTE: While the Redox kernel currently doesn't distinguish between threads and processes,
// the return value of this function is expected to be treated as a process ID and not a thread
// ID.
fn redox_get_pid_v1() -> RawResult;
fn redox_get_euid_v1() -> RawResult;
fn redox_get_ruid_v1() -> RawResult;
fn redox_get_egid_v1() -> RawResult;
fn redox_get_rgid_v1() -> RawResult;
fn redox_setrens_v1(rns: usize, ens: usize) -> RawResult;
fn redox_kill_v1(pid: usize, signal: u32) -> RawResult;
fn redox_waitpid_v1(pid: usize, status: *mut i32, options: u32) -> RawResult;
fn redox_sigprocmask_v1(how: u32, new: *const u64, old: *mut u64) -> RawResult;
fn redox_sigaction_v1(signal: u32, new: *const data::SigAction, old: *mut data::SigAction) -> RawResult;
fn redox_clock_gettime_v1(clock: usize, ts: *mut data::TimeSpec) -> RawResult;
}
#[cfg(feature = "call")]
pub struct Fd(usize);
#[cfg(feature = "call")]
impl Fd {
#[inline]
pub fn open(path: &str, flags: i32, mode: u16) -> Result<Self> {
@@ -89,11 +107,11 @@ impl Fd {
call::fpath(self.raw(), path)
}
#[inline]
pub fn fsync(&self) -> Result<usize> {
pub fn fsync(&self) -> Result<()> {
call::fsync(self.raw())
}
#[inline]
pub fn fdatasync(&self) -> Result<usize> {
pub fn fdatasync(&self) -> Result<()> {
call::fdatasync(self.raw())
}
@@ -110,12 +128,14 @@ impl Fd {
call::close(self.into_raw())
}
}
#[cfg(feature = "call")]
impl Drop for Fd {
fn drop(&mut self) {
let _ = unsafe { redox_close_v1(self.0) };
}
}
#[cfg(feature = "call")]
pub mod call {
use super::*;
@@ -144,12 +164,12 @@ pub mod call {
Ok(Error::demux(unsafe { redox_write_v1(raw_fd, buf.as_ptr(), buf.len()) })?)
}
#[inline]
pub fn fsync(raw_fd: usize) -> Result<usize> {
Ok(Error::demux(unsafe { redox_fsync_v1(raw_fd) })?)
pub fn fsync(raw_fd: usize) -> Result<()> {
Error::demux(unsafe { redox_fsync_v1(raw_fd) }).map(|_| ())
}
#[inline]
pub fn fdatasync(raw_fd: usize) -> Result<usize> {
Ok(Error::demux(unsafe { redox_fdatasync_v1(raw_fd) })?)
pub fn fdatasync(raw_fd: usize) -> Result<()> {
Ok(Error::demux(unsafe { redox_fdatasync_v1(raw_fd) })?).map(|_| ())
}
#[inline]
pub fn fchmod(raw_fd: usize, new_mode: u16) -> Result<()> {
@@ -190,6 +210,10 @@ pub mod call {
Error::demux(unsafe { redox_get_rgid_v1() })
}
#[inline]
pub fn getpid() -> Result<usize> {
Error::demux(unsafe { redox_get_pid_v1() })
}
#[inline]
pub fn setrens(rns: usize, ens: usize) -> Result<usize> {
Error::demux(unsafe { redox_setrens_v1(rns, ens) })
}
@@ -198,7 +222,113 @@ pub mod call {
Error::demux(unsafe { redox_waitpid_v1(pid, status as *mut i32, options as u32) })
}
#[inline]
pub fn clock_gettime(clock: i32, ts: &mut data::TimeSpec) -> Result<usize> {
Error::demux(unsafe { redox_clock_gettime_v1(clock as usize, ts) })
pub fn kill(pid: usize, signal: u32) -> Result<()> {
Error::demux(unsafe { redox_kill_v1(pid, signal) }).map(|_| ())
}
#[inline]
pub fn clock_gettime(clock: i32, ts: &mut data::TimeSpec) -> Result<()> {
Error::demux(unsafe { redox_clock_gettime_v1(clock as usize, ts) }).map(|_| ())
}
#[inline]
pub fn sigprocmask(how: i32, newmask: Option<&data::SigSet>, oldmask: Option<&mut data::SigSet>) -> Result<()> {
Error::demux(unsafe { redox_sigprocmask_v1(how as u32, newmask.map_or(core::ptr::null(), |m| m), oldmask.map_or(core::ptr::null_mut(), |m| m)) }).map(|_| ())
}
#[inline]
pub fn sigaction(signal: i32, newact: Option<&data::SigAction>, oldact: Option<&mut data::SigAction>) -> Result<()> {
Error::demux(unsafe { redox_sigaction_v1(signal as u32, newact.map_or(core::ptr::null(), |m| m), oldact.map_or(core::ptr::null_mut(), |m| m)) }).map(|_| ())
}
}
#[cfg(feature = "scheme")]
pub mod scheme {
use super::*;
use core::mem::size_of;
pub use syscall::{Scheme, SchemeMut, SchemeBlock, SchemeBlockMut};
use syscall::Packet;
#[repr(transparent)]
#[derive(Clone, Copy, Default)]
pub struct Request(Packet);
impl Request {
pub fn handle_scheme(mut self, scheme: &impl Scheme) -> Response {
scheme.handle(&mut self.0);
Response(self.0)
}
pub fn handle_scheme_mut(mut self, scheme: &mut impl SchemeMut) -> Response {
scheme.handle(&mut self.0);
Response(self.0)
}
pub fn handle_scheme_block(mut self, scheme: &mut impl SchemeBlock) -> Result<Response, Request> {
match scheme.handle(&mut self.0) {
Some(code) => Ok(Response(Packet { a: code, ..self.0 })),
None => Err(self),
}
}
pub fn handle_scheme_block_mut(mut self, scheme: &mut impl SchemeBlockMut) -> Result<Response, Request> {
match scheme.handle(&mut self.0) {
Some(code) => Ok(Response(Packet { a: code, ..self.0 })),
None => Err(self),
}
}
}
#[repr(transparent)]
#[derive(Clone, Copy, Default)]
pub struct Response(Packet);
impl Response {
pub fn new(req: &Request, status: Result<usize>) -> Self {
Self(Packet {
a: Error::mux(status),
..req.0
})
}
}
pub enum SignalBehavior {
Interrupt,
Restart,
}
// TODO: Support uninitialized memory
#[inline]
pub fn read_requests(socket: usize, buf: &mut [Request], behavior: SignalBehavior) -> Result<usize> {
let len = buf.len().checked_mul(size_of::<Request>()).unwrap();
let bytes_read = loop {
match call::read(socket, unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr().cast(), len) }) {
Ok(n) => break n,
error @ Err(Error { errno: errno::EINTR }) => match behavior {
SignalBehavior::Restart => continue,
SignalBehavior::Interrupt => return error,
}
Err(err) => return Err(err),
}
};
debug_assert_eq!(bytes_read % size_of::<Request>(), 0);
Ok(bytes_read / size_of::<Request>())
}
#[inline]
pub fn write_responses(socket: usize, buf: &[Response], behavior: SignalBehavior) -> Result<usize> {
let bytes = unsafe { core::slice::from_raw_parts(buf.as_ptr().cast(), buf.len().checked_mul(size_of::<Response>()).unwrap()) };
let bytes_written = loop {
match call::write(socket, bytes) {
Ok(n) => break n,
error @ Err(Error { errno: errno::EINTR }) => match behavior {
SignalBehavior::Restart => continue,
SignalBehavior::Interrupt => return error,
}
Err(err) => return Err(err),
}
};
debug_assert_eq!(bytes_written % size_of::<Response>(), 0);
Ok(bytes_written / size_of::<Response>())
}
}