alnyan/yggdrasil: shared memory + PTY
This commit is contained in:
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
Reference in New Issue
Block a user