Skip to content

Commit

Permalink
add HermitOS support of vectored read/write operations
Browse files Browse the repository at this point in the history
In general, the I/O interface of hermit-abi is more POSIX-like
interface. Consequently, platform abstraction layer for HermitOS
has slightly adjusted and some inaccuracies remove.
  • Loading branch information
stlankes committed Jun 7, 2024
1 parent e3c3ce6 commit d96ab6e
Show file tree
Hide file tree
Showing 12 changed files with 188 additions and 87 deletions.
10 changes: 8 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1694,6 +1694,12 @@ name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"

[[package]]
name = "hermit-abi"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
dependencies = [
"compiler_builtins",
"rustc-std-workspace-alloc",
Expand Down Expand Up @@ -2636,7 +2642,7 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"hermit-abi 0.3.9",
"libc",
]

Expand Down Expand Up @@ -5363,7 +5369,7 @@ dependencies = [
"dlmalloc",
"fortanix-sgx-abi",
"hashbrown",
"hermit-abi",
"hermit-abi 0.4.0",
"libc",
"miniz_oxide",
"object 0.36.0",
Expand Down
2 changes: 1 addition & 1 deletion library/std/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ dlmalloc = { version = "0.2.4", features = ['rustc-dep-of-std'] }
fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'], public = true }

[target.'cfg(target_os = "hermit")'.dependencies]
hermit-abi = { version = "0.3.9", features = ['rustc-dep-of-std'], public = true }
hermit-abi = { version = "0.4.0", features = ['rustc-dep-of-std'], public = true }

[target.'cfg(target_os = "wasi")'.dependencies]
wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false }
Expand Down
39 changes: 38 additions & 1 deletion library/std/src/sys/pal/hermit/fd.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
#![unstable(reason = "not public", issue = "none", feature = "fd")]

use super::hermit_abi;
use crate::io::{self, Read};
use crate::cmp;
use crate::io::{self, IoSlice, IoSliceMut, Read};
use crate::os::hermit::io::{FromRawFd, OwnedFd, RawFd};
use crate::sys::cvt;
use crate::sys::unsupported;
use crate::sys_common::{AsInner, FromInner, IntoInner};

use crate::os::hermit::io::*;

const fn max_iov() -> usize {
hermit_abi::IOV_MAX
}

#[derive(Debug)]
pub struct FileDesc {
fd: OwnedFd,
Expand All @@ -21,6 +26,22 @@ impl FileDesc {
Ok(result as usize)
}

pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
let ret = cvt(unsafe {
hermit_abi::readv(
self.as_raw_fd(),
bufs.as_mut_ptr() as *mut hermit_abi::iovec as *const hermit_abi::iovec,
cmp::min(bufs.len(), max_iov()),
)
})?;
Ok(ret as usize)
}

#[inline]
pub fn is_read_vectored(&self) -> bool {
true
}

pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
let mut me = self;
(&mut me).read_to_end(buf)
Expand All @@ -32,6 +53,22 @@ impl FileDesc {
Ok(result as usize)
}

pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
let ret = cvt(unsafe {
hermit_abi::writev(
self.as_raw_fd(),
bufs.as_ptr() as *const hermit_abi::iovec,
cmp::min(bufs.len(), max_iov()),
)
})?;
Ok(ret as usize)
}

#[inline]
pub fn is_write_vectored(&self) -> bool {
true
}

pub fn duplicate(&self) -> io::Result<FileDesc> {
self.duplicate_path(&[])
}
Expand Down
39 changes: 20 additions & 19 deletions library/std/src/sys/pal/hermit/fs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::fd::FileDesc;
use super::hermit_abi::{
self, dirent64, stat as stat_struct, DT_DIR, DT_LNK, DT_REG, DT_UNKNOWN, O_APPEND, O_CREAT,
O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG,
O_DIRECTORY, O_EXCL, O_RDONLY, O_RDWR, O_TRUNC, O_WRONLY, S_IFDIR, S_IFLNK, S_IFMT, S_IFREG,
};
use crate::ffi::{CStr, OsStr, OsString};
use crate::fmt;
Expand Down Expand Up @@ -62,7 +62,7 @@ pub struct DirEntry {
/// 64-bit inode number
ino: u64,
/// File type
type_: u32,
type_: u8,
/// name of the entry
name: OsString,
}
Expand Down Expand Up @@ -90,7 +90,7 @@ pub struct FilePermissions {

#[derive(Copy, Clone, Eq, Debug)]
pub struct FileType {
mode: u32,
mode: u8,
}

impl PartialEq for FileType {
Expand All @@ -113,30 +113,31 @@ pub struct DirBuilder {
impl FileAttr {
pub fn modified(&self) -> io::Result<SystemTime> {
Ok(SystemTime::new(
self.stat_val.st_mtime.try_into().unwrap(),
self.stat_val.st_mtime_nsec.try_into().unwrap(),
self.stat_val.st_mtim.tv_sec,
self.stat_val.st_mtim.tv_nsec,
))
}

pub fn accessed(&self) -> io::Result<SystemTime> {
Ok(SystemTime::new(
self.stat_val.st_atime.try_into().unwrap(),
self.stat_val.st_atime_nsec.try_into().unwrap(),
self.stat_val.st_atim.tv_sec,
self.stat_val.st_atim.tv_nsec,
))
}

pub fn created(&self) -> io::Result<SystemTime> {
Ok(SystemTime::new(
self.stat_val.st_ctime.try_into().unwrap(),
self.stat_val.st_ctime_nsec.try_into().unwrap(),
self.stat_val.st_ctim.tv_sec,
self.stat_val.st_ctim.tv_nsec,
))
}

pub fn size(&self) -> u64 {
self.stat_val.st_size as u64
}

pub fn perm(&self) -> FilePermissions {
FilePermissions { mode: (self.stat_val.st_mode) }
FilePermissions { mode: self.stat_val.st_mode }
}

pub fn file_type(&self) -> FileType {
Expand Down Expand Up @@ -220,7 +221,7 @@ impl Iterator for ReadDir {
let entry = DirEntry {
root: self.inner.root.clone(),
ino: dir.d_ino,
type_: dir.d_type as u32,
type_: dir.d_type,
name: OsString::from_vec(name_bytes.to_vec()),
};

Expand Down Expand Up @@ -251,7 +252,7 @@ impl DirEntry {
}

pub fn file_type(&self) -> io::Result<FileType> {
Ok(FileType { mode: self.type_ as u32 })
Ok(FileType { mode: self.type_ })
}

#[allow(dead_code)]
Expand Down Expand Up @@ -385,12 +386,12 @@ impl File {
}

pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
crate::io::default_read_vectored(|buf| self.read(buf), bufs)
self.0.read_vectored(bufs)
}

#[inline]
pub fn is_read_vectored(&self) -> bool {
false
self.0.is_read_vectored()
}

pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
Expand All @@ -402,12 +403,12 @@ impl File {
}

pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
crate::io::default_write_vectored(|buf| self.write(buf), bufs)
self.0.write_vectored(bufs)
}

#[inline]
pub fn is_write_vectored(&self) -> bool {
false
self.0.is_write_vectored()
}

#[inline]
Expand Down Expand Up @@ -439,13 +440,13 @@ impl DirBuilder {

pub fn mkdir(&self, path: &Path) -> io::Result<()> {
run_path_with_cstr(path, &|path| {
cvt(unsafe { hermit_abi::mkdir(path.as_ptr(), self.mode) }).map(|_| ())
cvt(unsafe { hermit_abi::mkdir(path.as_ptr(), self.mode.into()) }).map(|_| ())
})
}

#[allow(dead_code)]
pub fn set_mode(&mut self, mode: u32) {
self.mode = mode as u32;
self.mode = mode;
}
}

Expand Down Expand Up @@ -502,7 +503,7 @@ impl FromRawFd for File {

pub fn readdir(path: &Path) -> io::Result<ReadDir> {
let fd_raw =
run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::opendir(path.as_ptr()) }))?;
run_path_with_cstr(path, &|path| cvt(unsafe { hermit_abi::open(path.as_ptr(), O_RDONLY | O_DIRECTORY, 0) }))?;
let fd = unsafe { FileDesc::from_raw_fd(fd_raw as i32) };
let root = path.to_path_buf();

Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/pal/hermit/futex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ pub fn futex_wait(futex: &AtomicU32, expected: u32, timeout: Option<Duration>) -
let timespec = timeout.and_then(|dur| {
Some(hermit_abi::timespec {
tv_sec: dur.as_secs().try_into().ok()?,
tv_nsec: dur.subsec_nanos().into(),
tv_nsec: dur.subsec_nanos().try_into().ok()?,
})
});

Expand Down
82 changes: 82 additions & 0 deletions library/std/src/sys/pal/hermit/io.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
use crate::marker::PhantomData;
use crate::os::hermit::io::{AsFd, AsRawFd};
use crate::slice;

use hermit_abi::{c_void, iovec};

#[derive(Copy, Clone)]
#[repr(transparent)]
pub struct IoSlice<'a> {
vec: iovec,
_p: PhantomData<&'a [u8]>,
}

impl<'a> IoSlice<'a> {
#[inline]
pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
IoSlice {
vec: iovec { iov_base: buf.as_ptr() as *mut u8 as *mut c_void, iov_len: buf.len() },
_p: PhantomData,
}
}

#[inline]
pub fn advance(&mut self, n: usize) {
if self.vec.iov_len < n {
panic!("advancing IoSlice beyond its length");
}

unsafe {
self.vec.iov_len -= n;
self.vec.iov_base = self.vec.iov_base.add(n);
}
}

#[inline]
pub fn as_slice(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
}
}

#[repr(transparent)]
pub struct IoSliceMut<'a> {
vec: iovec,
_p: PhantomData<&'a mut [u8]>,
}

impl<'a> IoSliceMut<'a> {
#[inline]
pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
IoSliceMut {
vec: iovec { iov_base: buf.as_mut_ptr() as *mut c_void, iov_len: buf.len() },
_p: PhantomData,
}
}

#[inline]
pub fn advance(&mut self, n: usize) {
if self.vec.iov_len < n {
panic!("advancing IoSliceMut beyond its length");
}

unsafe {
self.vec.iov_len -= n;
self.vec.iov_base = self.vec.iov_base.add(n);
}
}

#[inline]
pub fn as_slice(&self) -> &[u8] {
unsafe { slice::from_raw_parts(self.vec.iov_base as *mut u8, self.vec.iov_len) }
}

#[inline]
pub fn as_mut_slice(&mut self) -> &mut [u8] {
unsafe { slice::from_raw_parts_mut(self.vec.iov_base as *mut u8, self.vec.iov_len) }
}
}

pub fn is_terminal(fd: &impl AsFd) -> bool {
let fd = fd.as_fd();
hermit_abi::isatty(fd.as_raw_fd())
}
1 change: 0 additions & 1 deletion library/std/src/sys/pal/hermit/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ pub mod env;
pub mod fd;
pub mod fs;
pub mod futex;
#[path = "../unsupported/io.rs"]
pub mod io;
pub mod net;
pub mod os;
Expand Down
13 changes: 6 additions & 7 deletions library/std/src/sys/pal/hermit/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,12 +175,12 @@ impl Socket {
}

pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
crate::io::default_read_vectored(|b| self.read(b), bufs)
self.0.read_vectored(bufs)
}

#[inline]
pub fn is_read_vectored(&self) -> bool {
false
self.0.is_read_vectored()
}

fn recv_from_with_flags(&self, buf: &mut [u8], flags: i32) -> io::Result<(usize, SocketAddr)> {
Expand Down Expand Up @@ -209,16 +209,15 @@ impl Socket {
}

pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
let sz = cvt(unsafe { netc::write(self.0.as_raw_fd(), buf.as_ptr(), buf.len()) })?;
Ok(sz.try_into().unwrap())
self.0.write(buf)
}

pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
crate::io::default_write_vectored(|b| self.write(b), bufs)
self.0.write_vectored(bufs)
}

pub fn is_write_vectored(&self) -> bool {
false
self.0.is_write_vectored()
}

pub fn set_timeout(&self, dur: Option<Duration>, kind: i32) -> io::Result<()> {
Expand Down Expand Up @@ -265,7 +264,7 @@ impl Socket {
Shutdown::Read => netc::SHUT_RD,
Shutdown::Both => netc::SHUT_RDWR,
};
cvt(unsafe { netc::shutdown_socket(self.as_raw_fd(), how) })?;
cvt(unsafe { netc::shutdown(self.as_raw_fd(), how) })?;
Ok(())
}

Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/pal/hermit/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,5 +198,5 @@ pub fn exit(code: i32) -> ! {
}

pub fn getpid() -> u32 {
unsafe { hermit_abi::getpid() }
unsafe { hermit_abi::getpid() as u32 }
}
Loading

0 comments on commit d96ab6e

Please sign in to comment.