alnyan/yggdrasil: shared memory + PTY

This commit is contained in:
2024-01-04 21:32:42 +02:00
parent ab9d982a24
commit 4223772986
7 changed files with 224 additions and 127 deletions
+20
View File
@@ -0,0 +1,20 @@
use yggdrasil_rt::sys as syscall;
use super::DeviceRequest;
use crate::io;
use crate::os::fd::AsRawFd;
use crate::sys::cvt_io;
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub trait FdDeviceRequest {
#[unstable(feature = "yggdrasil_os", issue = "none")]
unsafe fn device_request(&self, req: &mut DeviceRequest) -> io::Result<()>;
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
impl<T: AsRawFd> FdDeviceRequest for T {
unsafe fn device_request(&self, req: &mut DeviceRequest) -> io::Result<()> {
cvt_io(syscall::device_request(self.as_raw_fd(), req))?;
Ok(())
}
}
@@ -0,0 +1,54 @@
use crate::os::fd::{AsRawFd, OwnedFd};
use crate::sys::cvt_io;
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub struct FileMapping<'a> {
data: &'a mut [u8],
_fd: OwnedFd,
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
impl<'a> FileMapping<'a> {
pub fn new<F: Into<OwnedFd>>(f: F, offset: u64, len: usize) -> crate::io::Result<Self> {
use yggdrasil_rt::mem::MappingSource;
let owned_fd = f.into();
let raw_fd = owned_fd.as_raw_fd();
let base = cvt_io(unsafe {
yggdrasil_rt::sys::map_memory(None, len, &MappingSource::File(raw_fd, offset))
})?;
#[allow(fuzzy_provenance_casts)]
let data = unsafe { crate::slice::from_raw_parts_mut(base as *mut u8, len) };
Ok(Self { data, _fd: owned_fd })
}
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
impl crate::ops::Deref for FileMapping<'_> {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.data
}
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
impl crate::ops::DerefMut for FileMapping<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.data
}
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
impl Drop for FileMapping<'_> {
fn drop(&mut self) {
// Unmap the memory
let base = self.data.as_ptr() as usize;
let len = self.data.len();
unsafe {
yggdrasil_rt::sys::unmap_memory(base, len).expect("Memory unmap failed");
}
}
}
+14 -126
View File
@@ -1,16 +1,17 @@
#![stable(feature = "os_fd", since = "1.66.0")]
#![allow(dead_code)]
mod device;
mod mapping;
mod message_channel;
mod net;
pub mod owned;
mod poll;
pub(crate) mod raw;
use crate::io::StdinLock;
mod shared_memory;
mod terminal;
use crate::mem::MaybeUninit;
use crate::path::Path;
use crate::sys::cvt_io;
use yggdrasil_rt::{
// io::{FileMode, OpenOptions},
@@ -22,7 +23,7 @@ use yggdrasil_rt::{
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub use yggdrasil_rt::io::{
DeviceRequest, MessageDestination, MountOptions, ReceivedMessageMetadata, TerminalInputOptions,
TerminalLineOptions, TerminalOptions, TerminalOutputOptions,
TerminalLineOptions, TerminalOptions, TerminalOutputOptions, TerminalSize,
};
#[stable(feature = "io_safety", since = "1.63.0")]
@@ -31,120 +32,22 @@ pub use owned::*;
pub use raw::*;
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub use poll::PollChannel;
pub use device::FdDeviceRequest;
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub use mapping::FileMapping;
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub use message_channel::{
MessageChannel, MessageChannelReceiver, MessageChannelSender, MessageReceiver, MessageSender,
};
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub struct FileMapping<'a> {
data: &'a mut [u8],
_fd: OwnedFd,
}
pub use poll::PollChannel;
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub trait FdDeviceRequest {
#[unstable(feature = "yggdrasil_os", issue = "none")]
unsafe fn device_request(&self, req: &mut DeviceRequest) -> crate::io::Result<()>;
}
pub use shared_memory::SharedMemory;
#[unstable(feature = "yggdrasil_os", issue = "none")]
impl<'a> FileMapping<'a> {
pub fn new<F: Into<OwnedFd>>(f: F, offset: u64, len: usize) -> crate::io::Result<Self> {
use yggdrasil_rt::mem::MappingSource;
let owned_fd = f.into();
let raw_fd = owned_fd.as_raw_fd();
let base = cvt_io(unsafe {
yggdrasil_rt::sys::map_memory(None, len, &MappingSource::File(raw_fd, offset))
})?;
#[allow(fuzzy_provenance_casts)]
let data = unsafe { crate::slice::from_raw_parts_mut(base as *mut u8, len) };
Ok(Self { data, _fd: owned_fd })
}
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
impl crate::ops::Deref for FileMapping<'_> {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.data
}
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
impl crate::ops::DerefMut for FileMapping<'_> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.data
}
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
impl Drop for FileMapping<'_> {
fn drop(&mut self) {
// Unmap the memory
let base = self.data.as_ptr() as usize;
let len = self.data.len();
unsafe {
yggdrasil_rt::sys::unmap_memory(base, len).expect("Memory unmap failed");
}
}
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
impl<T: AsRawFd> FdDeviceRequest for T {
unsafe fn device_request(&self, req: &mut DeviceRequest) -> crate::io::Result<()> {
cvt_io(syscall::device_request(self.as_raw_fd(), req))?;
Ok(())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> AsRawFd for StdinLock<'a> {
fn as_raw_fd(&self) -> RawFd {
todo!()
}
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub unsafe fn set_terminal_options<F: raw::AsRawFd>(
fd: F,
opt: TerminalOptions,
) -> crate::io::Result<()> {
let mut req = DeviceRequest::SetTerminalOptions(opt);
cvt_io(syscall::device_request(fd.as_raw_fd(), &mut req))
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub unsafe fn get_terminal_options<F: raw::AsRawFd>(fd: F) -> crate::io::Result<TerminalOptions> {
let mut req = DeviceRequest::GetTerminalOptions(MaybeUninit::uninit());
cvt_io(syscall::device_request(fd.as_raw_fd(), &mut req))?;
let DeviceRequest::GetTerminalOptions(opt) = req else {
unreachable!();
};
Ok(opt.assume_init())
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub unsafe fn start_terminal_session<P: AsRef<Path>>(_terminal: P) -> crate::io::Result<()> {
todo!()
// let terminal = terminal.as_ref().to_str().unwrap();
// cvt_io(syscall::start_session())?;
// // TODO implement open flags to explicitly set stdin/stdout/stderr
// cvt_io(syscall::open(None, terminal, OpenOptions::READ, FileMode::empty()))?;
// cvt_io(syscall::open(None, terminal, OpenOptions::WRITE, FileMode::empty()))?;
// cvt_io(syscall::open(None, terminal, OpenOptions::WRITE, FileMode::empty()))?;
// Ok(())
}
pub use terminal::{
create_pty, get_terminal_options, set_terminal_options, start_terminal_session,
update_terminal_options,
};
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub unsafe fn mount_raw(options: &MountOptions<'_>) -> crate::io::Result<()> {
@@ -159,18 +62,3 @@ pub fn create_pipe_pair() -> crate::io::Result<(RawFd, RawFd)> {
let write = unsafe { buffer[1].assume_init() };
Ok((read, write))
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub unsafe fn update_terminal_options<
F: raw::AsRawFd,
M: Fn(TerminalOptions) -> TerminalOptions,
>(
fd: F,
mutator: M,
) -> crate::io::Result<TerminalOptions> {
let fd = fd.as_raw_fd();
let old = get_terminal_options(fd)?;
let new = mutator(old);
set_terminal_options(fd, new)?;
Ok(old)
}
+7
View File
@@ -35,3 +35,10 @@ impl PollChannel {
Ok(output.map(|(l, r)| (l, cvt_io(r))))
}
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
impl AsRawFd for PollChannel {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}
+16 -1
View File
@@ -1,6 +1,6 @@
#![stable(feature = "os_fd", since = "1.66.0")]
use crate::sys_common::AsInner;
use crate::sys_common::{AsInner, FromInner};
#[stable(feature = "rust1", since = "1.0.0")]
pub type RawFd = yggdrasil_rt::io::RawFd;
@@ -76,3 +76,18 @@ impl AsRawFd for crate::fs::File {
self.as_inner().as_raw_fd()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl FromRawFd for crate::fs::File {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
let inner = crate::sys::fs::File::from_raw_fd(fd);
crate::fs::File::from_inner(inner)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> AsRawFd for crate::io::StdinLock<'a> {
fn as_raw_fd(&self) -> RawFd {
todo!()
}
}
@@ -0,0 +1,34 @@
use crate::io;
use crate::os::yggdrasil::io::{AsRawFd, FileMapping, FromRawFd, OwnedFd, RawFd};
use crate::sys::cvt_io;
use yggdrasil_rt::sys as syscall;
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub struct SharedMemory(OwnedFd, usize);
impl SharedMemory {
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub fn new(size: usize) -> io::Result<Self> {
let raw_fd = cvt_io(unsafe { syscall::create_shared_memory(size) })?;
let fd = unsafe { OwnedFd::from_raw_fd(raw_fd) };
Ok(Self(fd, size))
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub fn size(&self) -> usize {
self.1
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub fn into_mapping<'a>(self) -> io::Result<FileMapping<'a>> {
FileMapping::new(self.0, 0, self.1)
}
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
impl AsRawFd for SharedMemory {
fn as_raw_fd(&self) -> RawFd {
self.0.as_raw_fd()
}
}
@@ -0,0 +1,79 @@
use yggdrasil_rt::sys as syscall;
use super::{DeviceRequest, TerminalOptions, TerminalSize};
use crate::fs::File;
use crate::io;
use crate::mem::MaybeUninit;
use crate::os::fd::{AsRawFd, FromRawFd};
use crate::path::Path;
use crate::sys::cvt_io;
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub unsafe fn set_terminal_options<F: AsRawFd>(fd: F, opt: TerminalOptions) -> io::Result<()> {
let mut req = DeviceRequest::SetTerminalOptions(opt);
cvt_io(syscall::device_request(fd.as_raw_fd(), &mut req))
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub unsafe fn get_terminal_options<F: AsRawFd>(fd: F) -> io::Result<TerminalOptions> {
let mut req = DeviceRequest::GetTerminalOptions(MaybeUninit::uninit());
cvt_io(syscall::device_request(fd.as_raw_fd(), &mut req))?;
let DeviceRequest::GetTerminalOptions(opt) = req else {
unreachable!();
};
Ok(opt.assume_init())
}
pub fn get_terminal_size<F: AsRawFd>(fd: F) -> io::Result<TerminalSize> {
let mut req = DeviceRequest::GetTerminalSize(MaybeUninit::uninit());
cvt_io(unsafe { syscall::device_request(fd.as_raw_fd(), &mut req) })?;
let DeviceRequest::GetTerminalSize(opt) = req else {
unreachable!();
};
Ok(unsafe { opt.assume_init() })
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub unsafe fn update_terminal_options<F: AsRawFd, M: Fn(TerminalOptions) -> TerminalOptions>(
fd: F,
mutator: M,
) -> io::Result<TerminalOptions> {
let fd = fd.as_raw_fd();
let old = get_terminal_options(fd)?;
let new = mutator(old);
set_terminal_options(fd, new)?;
Ok(old)
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub unsafe fn start_terminal_session<P: AsRef<Path>>(_terminal: P) -> io::Result<()> {
todo!()
// let terminal = terminal.as_ref().to_str().unwrap();
// cvt_io(syscall::start_session())?;
// // TODO implement open flags to explicitly set stdin/stdout/stderr
// cvt_io(syscall::open(None, terminal, OpenOptions::READ, FileMode::empty()))?;
// cvt_io(syscall::open(None, terminal, OpenOptions::WRITE, FileMode::empty()))?;
// cvt_io(syscall::open(None, terminal, OpenOptions::WRITE, FileMode::empty()))?;
// Ok(())
}
#[unstable(feature = "yggdrasil_os", issue = "none")]
pub fn create_pty(
options: Option<TerminalOptions>,
size: TerminalSize,
) -> io::Result<(File, File)> {
let options = options.unwrap_or_default();
let mut fds = MaybeUninit::uninit();
cvt_io(unsafe { syscall::create_pty(&options, &size, &mut fds) })?;
let (master_raw_fd, slave_raw_fd) = unsafe { fds.assume_init() };
let master = unsafe { File::from_raw_fd(master_raw_fd) };
let slave = unsafe { File::from_raw_fd(slave_raw_fd) };
Ok((master, slave))
}