diff --git a/.gitignore b/.gitignore index f203b85af15..644d273e6a6 100644 --- a/.gitignore +++ b/.gitignore @@ -81,5 +81,6 @@ tests/rustdoc-gui/src/**.lock ## Yggdrasil OS ABI link /yggdrasil-rt /yggdrasil-abi +/libyalloc # Before adding new lines, see the comment at the top. diff --git a/Cargo.lock b/Cargo.lock index ec2d62f7fc0..ff8342feb82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3013,6 +3013,16 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "libyalloc" +version = "0.1.0" +dependencies = [ + "compiler_builtins", + "libc", + "rustc-std-workspace-core", + "yggdrasil-rt", +] + [[package]] name = "libz-sys" version = "1.1.3" @@ -6011,6 +6021,7 @@ dependencies = [ "hashbrown 0.12.3", "hermit-abi 0.3.0", "libc", + "libyalloc", "miniz_oxide", "object 0.29.0", "panic_abort", diff --git a/Cargo.toml b/Cargo.toml index 1d1297dab50..ce45326c62c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -123,3 +123,5 @@ clippy_lints = { path = "src/tools/clippy/clippy_lints" } yggdrasil-rt = { path = "yggdrasil-rt" } [patch."https://git.alnyan.me/yggdrasil/yggdrasil-abi.git"] yggdrasil-abi = { path = "yggdrasil-abi" } +[patch."https://git.alnyan.me/yggdrasil/libyalloc.git"] +libyalloc = { path = "libyalloc" } diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index ceef55240b4..82e6c48b3b5 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -47,6 +47,7 @@ hermit-abi = { version = "0.3.0", features = ['rustc-dep-of-std'] } [target.'cfg(target_os = "yggdrasil")'.dependencies] yggdrasil-rt = { git = "https://git.alnyan.me/yggdrasil/yggdrasil-rt.git", features = ['rustc-dep-of-std'] } +libyalloc = { git = "https://git.alnyan.me/yggdrasil/libyalloc.git", features = ['rustc-dep-of-std'] } [target.wasm32-wasi.dependencies] wasi = { version = "0.11.0", features = ['rustc-dep-of-std'], default-features = false } diff --git a/library/std/src/os/yggdrasil/io/mod.rs b/library/std/src/os/yggdrasil/io/mod.rs index 8658f8faab9..6b41aaedb6d 100644 --- a/library/std/src/os/yggdrasil/io/mod.rs +++ b/library/std/src/os/yggdrasil/io/mod.rs @@ -88,6 +88,15 @@ pub unsafe fn mount_raw(options: &MountOptions<'_>) -> crate::io::Result<()> { cvt_io(syscall::mount(options)) } +#[unstable(feature = "yggdrasil_os", issue = "none")] +pub fn create_pipe_pair() -> crate::io::Result<(RawFd, RawFd)> { + let mut buffer = MaybeUninit::uninit_array(); + cvt_io(unsafe { syscall::create_pipe(&mut buffer) })?; + let read = unsafe { buffer[0].assume_init() }; + 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, diff --git a/library/std/src/os/yggdrasil/io/owned.rs b/library/std/src/os/yggdrasil/io/owned.rs index 4f82adf0088..f904660db1f 100644 --- a/library/std/src/os/yggdrasil/io/owned.rs +++ b/library/std/src/os/yggdrasil/io/owned.rs @@ -92,6 +92,7 @@ impl AsRawFd for OwnedFd { #[stable(feature = "io_safety", since = "1.63.0")] impl Drop for OwnedFd { fn drop(&mut self) { + yggdrasil_rt::debug_trace!("--- OwnedFd drop: {:?} ---", self.fd); unsafe { yggdrasil_rt::sys::close(self.fd).ok(); } diff --git a/library/std/src/sys/yggdrasil/alloc.rs b/library/std/src/sys/yggdrasil/alloc.rs index e2362d88b2c..09f31e84226 100644 --- a/library/std/src/sys/yggdrasil/alloc.rs +++ b/library/std/src/sys/yggdrasil/alloc.rs @@ -1,24 +1,23 @@ use crate::alloc::{GlobalAlloc, Layout, System}; +use crate::ptr::NonNull; +use crate::sync::Mutex; +use libyalloc::Allocator; #[stable(feature = "alloc_system_type", since = "1.28.0")] unsafe impl GlobalAlloc for System { #[inline] unsafe fn alloc(&self, layout: Layout) -> *mut u8 { - yggdrasil_rt::alloc::malloc(layout) - } + let ptr = ALLOC.lock().expect("Could not lock allocator mutex").alloc(layout); - #[inline] - unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 { - yggdrasil_rt::alloc::malloc_zeroed(layout) + if let Some(ptr) = ptr { ptr.as_ptr() } else { crate::ptr::null_mut() } } #[inline] unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { - yggdrasil_rt::alloc::dealloc(ptr, layout) - } + let ptr = NonNull::new(ptr).expect("Invalid pointer"); - #[inline] - unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { - yggdrasil_rt::alloc::realloc(ptr, layout, new_size) + ALLOC.lock().expect("Could not lock allocator mutex").free(ptr, layout); } } + +static ALLOC: Mutex = Mutex::new(Allocator::new()); diff --git a/library/std/src/sys/yggdrasil/pipe.rs b/library/std/src/sys/yggdrasil/pipe.rs index a43459b3b58..afa08c32dfb 100644 --- a/library/std/src/sys/yggdrasil/pipe.rs +++ b/library/std/src/sys/yggdrasil/pipe.rs @@ -1,38 +1,61 @@ use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; +use crate::os::yggdrasil::io::{AsRawFd, FromRawFd, RawFd}; +use crate::sys::cvt_io; +use crate::sys::io::FileDesc; -pub struct AnonPipe(!); +pub struct AnonPipe(FileDesc); impl AnonPipe { pub fn read(&self, _buf: &mut [u8]) -> io::Result { - self.0 + todo!() } pub fn read_buf(&self, _buf: BorrowedCursor<'_>) -> io::Result<()> { - self.0 + todo!() } pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result { - self.0 + todo!() } pub fn is_read_vectored(&self) -> bool { - self.0 + false } pub fn read_to_end(&self, _buf: &mut Vec) -> io::Result { - self.0 + todo!() } - pub fn write(&self, _buf: &[u8]) -> io::Result { - self.0 + pub fn write(&self, buf: &[u8]) -> io::Result { + unsafe { cvt_io(yggdrasil_rt::sys::write(self.as_raw_fd(), buf)) } } pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result { - self.0 + todo!() } pub fn is_write_vectored(&self) -> bool { - self.0 + todo!() + } +} + +impl FromRawFd for AnonPipe { + unsafe fn from_raw_fd(fd: RawFd) -> Self { + Self(FileDesc::from_raw_fd(fd)) + } +} + +impl AsRawFd for AnonPipe { + fn as_raw_fd(&self) -> RawFd { + self.0.as_raw_fd() + } +} + +impl Drop for AnonPipe { + fn drop(&mut self) { + unsafe { + // yggdrasil_rt::sys::close(self.as_raw_fd()).ok(); + } } } diff --git a/library/std/src/sys/yggdrasil/process.rs b/library/std/src/sys/yggdrasil/process.rs index ebff85e0694..808e4ec0efa 100644 --- a/library/std/src/sys/yggdrasil/process.rs +++ b/library/std/src/sys/yggdrasil/process.rs @@ -2,11 +2,14 @@ use crate::ffi::OsStr; use crate::fmt; use crate::io; use crate::num::NonZeroI32; +use crate::os::yggdrasil::io::{AsRawFd, FromRawFd, IntoRawFd}; use crate::path::Path; use crate::sys::cvt_io; +use crate::sys::fd::FileDesc; use crate::sys::fs::File; use crate::sys::pipe::AnonPipe; use crate::sys_common::process::{CommandEnv, CommandEnvs}; +use crate::sys_common::FromInner; pub use crate::ffi::OsString as EnvKey; @@ -36,6 +39,7 @@ pub struct ChildPipes { pub enum ChildStdio { Inherit, Null, + Fd(RawFd), } #[derive(Debug)] @@ -43,6 +47,7 @@ pub enum Stdio { Inherit, Null, MakePipe, + Fd(FileDesc), } pub struct Process { @@ -69,12 +74,44 @@ impl Process { } } +#[allow(ineffective_unstable_trait_impl)] +#[unstable(feature = "yggdrasil_os", issue = "none")] +impl FromRawFd for crate::process::Stdio { + #[inline] + unsafe fn from_raw_fd(fd: RawFd) -> crate::process::Stdio { + let fd = FileDesc::from_raw_fd(fd); + let io = Stdio::Fd(fd); + crate::process::Stdio::from_inner(io) + } +} + impl Stdio { - pub fn to_child_stdio(&self, _readable: bool) -> io::Result<(ChildStdio, Option)> { - match *self { + pub fn to_child_stdio(&self, readable: bool) -> io::Result<(ChildStdio, Option)> { + match self { Stdio::Inherit => Ok((ChildStdio::Inherit, None)), - Stdio::MakePipe => todo!(), Stdio::Null => Ok((ChildStdio::Null, None)), + Stdio::MakePipe => { + let (read, write) = crate::os::yggdrasil::io::create_pipe_pair()?; + + if readable { + yggdrasil_rt::debug_trace!( + "--- Make pipes for MakePipe: to_child={:?}, to_parent={:?} ---", + read, + write + ); + let write = unsafe { AnonPipe::from_raw_fd(write) }; + Ok((ChildStdio::Fd(read), Some(write))) + } else { + yggdrasil_rt::debug_trace!( + "--- Make pipes for MakePipe: to_child={:?}, to_parent={:?} ---", + write, + read + ); + let read = unsafe { AnonPipe::from_raw_fd(read) }; + Ok((ChildStdio::Fd(write), Some(read))) + } + } + Stdio::Fd(fd) => Ok((ChildStdio::Fd(fd.as_raw_fd()), None)), } } } @@ -203,6 +240,7 @@ impl Command { } pub fn stdin(&mut self, stdin: Stdio) { + yggdrasil_rt::debug_trace!("!!! Override stdin: {:?}", stdin); self.stdin = stdin; } @@ -235,12 +273,21 @@ impl Command { default: Stdio, needs_stdin: bool, ) -> io::Result<(Process, StdioPipes)> { + yggdrasil_rt::debug_trace!("Default: {:?}, needs_stdin = {:?}", default, needs_stdin); + let default_stdin = if needs_stdin { &default } else { &self.stdin }; - let stdin = default_stdin; + let stdin = &self.stdin; let stdout = &self.stdout; let stderr = &self.stderr; + yggdrasil_rt::debug_trace!( + "stdin = {:?}, stdout = {:?}, stderr = {:?}", + stdin, + stdout, + stderr + ); + let (their_stdin, our_stdin) = stdin.to_child_stdio(true)?; let (their_stdout, our_stdout) = stdout.to_child_stdio(false)?; let (their_stderr, our_stderr) = stderr.to_child_stdio(false)?; @@ -266,7 +313,8 @@ impl Command { optional.push(SpawnOption::InheritFile { source: match pipes.stdin { ChildStdio::Inherit => RawFd::STDIN, - ChildStdio::Null => unreachable!(), + ChildStdio::Fd(fd) => fd, + ChildStdio::Null => todo!(), }, child: RawFd::STDIN, }); @@ -275,7 +323,8 @@ impl Command { optional.push(SpawnOption::InheritFile { source: match pipes.stdout { ChildStdio::Inherit => RawFd::STDOUT, - ChildStdio::Null => unreachable!(), + ChildStdio::Fd(fd) => fd, + ChildStdio::Null => todo!(), }, child: RawFd::STDOUT, }); @@ -284,7 +333,8 @@ impl Command { optional.push(SpawnOption::InheritFile { source: match pipes.stderr { ChildStdio::Inherit => RawFd::STDERR, - ChildStdio::Null => unreachable!(), + ChildStdio::Fd(fd) => fd, + ChildStdio::Null => todo!(), }, child: RawFd::STDERR, }); @@ -317,7 +367,6 @@ impl Command { })); let environment = &Vec::from_iter(envs.iter().map(|x| x.as_str())); - yggdrasil_rt::debug_trace!("env = {:#?}", environment); let options = SpawnOptions { program, arguments, environment, optional: &optional };