diff --git a/compiler/rustc_target/src/spec/aarch64_unknown_yggdrasil_linker_script.ld b/compiler/rustc_target/src/spec/aarch64_unknown_yggdrasil_linker_script.ld index 59cab5c5eb7..4907a55212d 100644 --- a/compiler/rustc_target/src/spec/aarch64_unknown_yggdrasil_linker_script.ld +++ b/compiler/rustc_target/src/spec/aarch64_unknown_yggdrasil_linker_script.ld @@ -16,6 +16,8 @@ SECTIONS { .rodata : { *(.rodata*) + /* TODO: this is unused currently */ + *(.eh_frame*) } . = ALIGN(4K); @@ -31,4 +33,10 @@ SECTIONS { *(COMMON) *(.bss*) } + + . = ALIGN(4K); + + .tbss : { + *(.tbss*) + } } diff --git a/compiler/rustc_target/src/spec/x86_64_unknown_yggdrasil_linker_script.ld b/compiler/rustc_target/src/spec/x86_64_unknown_yggdrasil_linker_script.ld index 89b9096ff2e..96eddaa718d 100644 --- a/compiler/rustc_target/src/spec/x86_64_unknown_yggdrasil_linker_script.ld +++ b/compiler/rustc_target/src/spec/x86_64_unknown_yggdrasil_linker_script.ld @@ -14,6 +14,8 @@ SECTIONS { .rodata : { *(.rodata*) + /* TODO: this is unused currently */ + *(.eh_frame*) } . = ALIGN(4K); @@ -29,4 +31,10 @@ SECTIONS { *(COMMON) *(.bss*) } + + . = ALIGN(4K); + + .tbss : { + *(.tbss*) + } } diff --git a/compiler/rustc_target/src/spec/yggdrasil_base.rs b/compiler/rustc_target/src/spec/yggdrasil_base.rs index 259ce92146c..d04ec79b613 100644 --- a/compiler/rustc_target/src/spec/yggdrasil_base.rs +++ b/compiler/rustc_target/src/spec/yggdrasil_base.rs @@ -10,6 +10,7 @@ pub fn opts() -> TargetOptions { linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), lld_flavor_json: LldFlavor::Ld, stack_probes: StackProbeType::Inline, + has_thread_local: true, max_atomic_width: Some(128), eh_frame_header: false, relocation_model: RelocModel::Static, diff --git a/library/std/src/os/yggdrasil/io.rs b/library/std/src/os/yggdrasil/io.rs deleted file mode 100644 index c42ed223ba1..00000000000 --- a/library/std/src/os/yggdrasil/io.rs +++ /dev/null @@ -1,297 +0,0 @@ -#![stable(feature = "os_fd", since = "1.66.0")] -#![allow(dead_code)] - -use crate::mem::MaybeUninit; -use crate::sys::cvt_io; -use yggdrasil_rt::sys as syscall; - -#[unstable(feature = "yggdrasil_os", issue = "none")] -pub use yggdrasil_rt::io::{ - DeviceRequest, TerminalInputOptions, TerminalLineOptions, TerminalOptions, - TerminalOutputOptions, -}; - -#[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<()>; -} - -#[unstable(feature = "yggdrasil_os", issue = "none")] -impl 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(()) - } -} - -#[unstable(feature = "yggdrasil_os", issue = "none")] -pub unsafe fn set_terminal_options( - 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(fd: F) -> crate::io::Result { - 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 update_terminal_options< - F: raw::AsRawFd, - M: Fn(TerminalOptions) -> TerminalOptions, ->( - fd: F, - mutator: M, -) -> crate::io::Result { - let fd = fd.as_raw_fd(); - let old = get_terminal_options(fd)?; - let new = mutator(old); - set_terminal_options(fd, new)?; - Ok(old) -} - -mod net { - use crate::os::yggdrasil::io::OwnedFd; - use crate::os::yggdrasil::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; - use crate::sys_common::{self, AsInner, FromInner, IntoInner}; - use crate::{net, sys}; - - macro_rules! impl_as_raw_fd { - ($($t:ident)*) => {$( - #[stable(feature = "rust1", since = "1.0.0")] - impl AsRawFd for net::$t { - #[inline] - fn as_raw_fd(&self) -> RawFd { - self.as_inner().socket().as_raw_fd() - } - } - )*}; - } - - macro_rules! impl_from_raw_fd { - ($($t:ident)*) => {$( - #[stable(feature = "rust1", since = "1.0.0")] - impl FromRawFd for net::$t { - #[inline] - unsafe fn from_raw_fd(fd: RawFd) -> net::$t { - let socket = sys::net::Socket::from_inner(FromInner::from_inner(OwnedFd::from_raw_fd(fd))); - net::$t::from_inner(sys_common::net::$t::from_inner(socket)) - } - } - )*}; - } - - macro_rules! impl_into_raw_fd { - ($($t:ident)*) => {$( - #[stable(feature = "rust1", since = "1.0.0")] - impl IntoRawFd for net::$t { - #[inline] - fn into_raw_fd(self) -> RawFd { - self.into_inner().into_socket().into_inner().into_raw_fd() - } - } - )*}; - } - - impl_as_raw_fd! { TcpStream TcpListener UdpSocket } - impl_from_raw_fd! { TcpStream TcpListener UdpSocket } - impl_into_raw_fd! { TcpStream TcpListener UdpSocket } -} - -#[stable(feature = "os_fd", since = "1.66.0")] -pub(crate) mod raw { - #[stable(feature = "rust1", since = "1.0.0")] - pub type RawFd = yggdrasil_rt::io::RawFd; - - macro_rules! stdio_impl_as_raw_fd { - ($($ty:ty => $n:expr),*) => {$( - #[stable(feature = "asraw_stdio", since = "1.21.0")] - impl AsRawFd for $ty { - #[inline] - fn as_raw_fd(&self) -> RawFd { - $n - } - } - - #[stable(feature = "asraw_stdio", since = "1.21.0")] - impl AsRawFd for &$ty { - #[inline] - fn as_raw_fd(&self) -> RawFd { - $n - } - } - )*}; - } - - #[stable(feature = "rust1", since = "1.0.0")] - pub trait AsRawFd { - #[stable(feature = "rust1", since = "1.0.0")] - fn as_raw_fd(&self) -> RawFd; - } - - #[stable(feature = "rust1", since = "1.0.0")] - pub trait FromRawFd { - #[stable(feature = "rust1", since = "1.0.0")] - unsafe fn from_raw_fd(fd: RawFd) -> Self; - } - - #[stable(feature = "rust1", since = "1.0.0")] - pub trait IntoRawFd { - #[stable(feature = "rust1", since = "1.0.0")] - fn into_raw_fd(self) -> RawFd; - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl AsRawFd for RawFd { - fn as_raw_fd(&self) -> RawFd { - *self - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl FromRawFd for RawFd { - unsafe fn from_raw_fd(fd: RawFd) -> Self { - fd - } - } - - #[stable(feature = "rust1", since = "1.0.0")] - impl IntoRawFd for RawFd { - fn into_raw_fd(self) -> RawFd { - self - } - } - - stdio_impl_as_raw_fd!( - crate::io::Stdin => RawFd::STDIN, - crate::io::Stdout => RawFd::STDOUT, - crate::io::Stderr => RawFd::STDERR - ); -} - -pub mod owned { - #![stable(feature = "io_safety", since = "1.63.0")] - - use super::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; - use crate::marker::PhantomData; - use crate::mem::forget; - - #[stable(feature = "io_safety", since = "1.63.0")] - #[repr(transparent)] - #[derive(Debug)] - pub struct OwnedFd { - fd: RawFd, - } - - #[stable(feature = "io_safety", since = "1.63.0")] - #[derive(Clone, Copy, Debug)] - #[repr(transparent)] - pub struct BorrowedFd<'fd> { - fd: RawFd, - _pd: PhantomData<&'fd OwnedFd>, - } - - #[stable(feature = "io_safety", since = "1.63.0")] - pub trait AsFd { - #[stable(feature = "io_safety", since = "1.63.0")] - fn as_fd(&self) -> BorrowedFd<'_>; - } - - #[stable(feature = "io_safety", since = "1.63.0")] - impl AsFd for &T { - fn as_fd(&self) -> BorrowedFd<'_> { - T::as_fd(self) - } - } - - // Borrowed - - impl BorrowedFd<'_> { - #[rustc_const_stable(feature = "io_safety", since = "1.63.0")] - #[stable(feature = "io_safety", since = "1.63.0")] - pub const unsafe fn borrow_raw(fd: RawFd) -> Self { - // assert_ne!(fd, u32::MAX as RawFd); - Self { fd, _pd: PhantomData } - } - } - - #[stable(feature = "io_safety", since = "1.63.0")] - impl AsFd for BorrowedFd<'_> { - fn as_fd(&self) -> BorrowedFd<'_> { - *self - } - } - - #[stable(feature = "io_safety", since = "1.63.0")] - impl AsRawFd for BorrowedFd<'_> { - fn as_raw_fd(&self) -> RawFd { - self.fd - } - } - - // Owned - - #[stable(feature = "io_safety", since = "1.63.0")] - impl AsFd for OwnedFd { - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } - } - } - - #[stable(feature = "io_safety", since = "1.63.0")] - impl IntoRawFd for OwnedFd { - fn into_raw_fd(self) -> RawFd { - let fd = self.fd; - forget(self); - fd - } - } - - #[stable(feature = "io_safety", since = "1.63.0")] - impl FromRawFd for OwnedFd { - unsafe fn from_raw_fd(fd: RawFd) -> Self { - Self { fd } - } - } - - #[stable(feature = "io_safety", since = "1.63.0")] - impl AsRawFd for OwnedFd { - fn as_raw_fd(&self) -> RawFd { - self.fd - } - } - - #[stable(feature = "io_safety", since = "1.63.0")] - impl Drop for OwnedFd { - fn drop(&mut self) { - unsafe { - yggdrasil_rt::sys::close(self.fd).ok(); - } - } - } - - // TODO: AsFd for File, From for OwnedFd, From for File, -} - -#[stable(feature = "io_safety", since = "1.63.0")] -pub use owned::*; -#[stable(feature = "rust1", since = "1.0.0")] -pub use raw::*; - -use crate::io::StdinLock; - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a> AsRawFd for StdinLock<'a> { - fn as_raw_fd(&self) -> RawFd { - todo!() - } -} diff --git a/library/std/src/os/yggdrasil/io/mod.rs b/library/std/src/os/yggdrasil/io/mod.rs new file mode 100644 index 00000000000..bdc3b7310d8 --- /dev/null +++ b/library/std/src/os/yggdrasil/io/mod.rs @@ -0,0 +1,80 @@ +#![stable(feature = "os_fd", since = "1.66.0")] +#![allow(dead_code)] + +mod net; +pub mod owned; +pub(crate) mod raw; + +use crate::io::StdinLock; + +use crate::mem::MaybeUninit; +use crate::sys::cvt_io; +use yggdrasil_rt::sys as syscall; + +// Public exports + +#[unstable(feature = "yggdrasil_os", issue = "none")] +pub use yggdrasil_rt::io::{ + DeviceRequest, TerminalInputOptions, TerminalLineOptions, TerminalOptions, + TerminalOutputOptions, +}; + +#[stable(feature = "io_safety", since = "1.63.0")] +pub use owned::*; +#[stable(feature = "rust1", since = "1.0.0")] +pub use raw::*; + +#[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<()>; +} + +#[unstable(feature = "yggdrasil_os", issue = "none")] +impl 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( + 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(fd: F) -> crate::io::Result { + 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 update_terminal_options< + F: raw::AsRawFd, + M: Fn(TerminalOptions) -> TerminalOptions, +>( + fd: F, + mutator: M, +) -> crate::io::Result { + let fd = fd.as_raw_fd(); + let old = get_terminal_options(fd)?; + let new = mutator(old); + set_terminal_options(fd, new)?; + Ok(old) +} diff --git a/library/std/src/os/yggdrasil/io/net.rs b/library/std/src/os/yggdrasil/io/net.rs new file mode 100644 index 00000000000..49daf43cb3a --- /dev/null +++ b/library/std/src/os/yggdrasil/io/net.rs @@ -0,0 +1,45 @@ +use crate::os::yggdrasil::io::OwnedFd; +use crate::os::yggdrasil::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; +use crate::sys_common::{self, AsInner, FromInner, IntoInner}; +use crate::{net, sys}; + +macro_rules! impl_as_raw_fd { + ($($t:ident)*) => {$( + #[stable(feature = "rust1", since = "1.0.0")] + impl AsRawFd for net::$t { + #[inline] + fn as_raw_fd(&self) -> RawFd { + self.as_inner().socket().as_raw_fd() + } + } + )*}; +} + +macro_rules! impl_from_raw_fd { + ($($t:ident)*) => {$( + #[stable(feature = "rust1", since = "1.0.0")] + impl FromRawFd for net::$t { + #[inline] + unsafe fn from_raw_fd(fd: RawFd) -> net::$t { + let socket = sys::net::Socket::from_inner(FromInner::from_inner(OwnedFd::from_raw_fd(fd))); + net::$t::from_inner(sys_common::net::$t::from_inner(socket)) + } + } + )*}; +} + +macro_rules! impl_into_raw_fd { + ($($t:ident)*) => {$( + #[stable(feature = "rust1", since = "1.0.0")] + impl IntoRawFd for net::$t { + #[inline] + fn into_raw_fd(self) -> RawFd { + self.into_inner().into_socket().into_inner().into_raw_fd() + } + } + )*}; +} + +impl_as_raw_fd! { TcpStream TcpListener UdpSocket } +impl_from_raw_fd! { TcpStream TcpListener UdpSocket } +impl_into_raw_fd! { TcpStream TcpListener UdpSocket } diff --git a/library/std/src/os/yggdrasil/io/owned.rs b/library/std/src/os/yggdrasil/io/owned.rs new file mode 100644 index 00000000000..4f82adf0088 --- /dev/null +++ b/library/std/src/os/yggdrasil/io/owned.rs @@ -0,0 +1,101 @@ +#![stable(feature = "io_safety", since = "1.63.0")] + +use super::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; +use crate::marker::PhantomData; +use crate::mem::forget; + +#[stable(feature = "io_safety", since = "1.63.0")] +#[repr(transparent)] +#[derive(Debug)] +pub struct OwnedFd { + fd: RawFd, +} + +#[stable(feature = "io_safety", since = "1.63.0")] +#[derive(Clone, Copy, Debug)] +#[repr(transparent)] +pub struct BorrowedFd<'fd> { + fd: RawFd, + _pd: PhantomData<&'fd OwnedFd>, +} + +#[stable(feature = "io_safety", since = "1.63.0")] +pub trait AsFd { + #[stable(feature = "io_safety", since = "1.63.0")] + fn as_fd(&self) -> BorrowedFd<'_>; +} + +#[stable(feature = "io_safety", since = "1.63.0")] +impl AsFd for &T { + fn as_fd(&self) -> BorrowedFd<'_> { + T::as_fd(self) + } +} + +// Borrowed + +impl BorrowedFd<'_> { + #[rustc_const_stable(feature = "io_safety", since = "1.63.0")] + #[stable(feature = "io_safety", since = "1.63.0")] + pub const unsafe fn borrow_raw(fd: RawFd) -> Self { + // assert_ne!(fd, u32::MAX as RawFd); + Self { fd, _pd: PhantomData } + } +} + +#[stable(feature = "io_safety", since = "1.63.0")] +impl AsFd for BorrowedFd<'_> { + fn as_fd(&self) -> BorrowedFd<'_> { + *self + } +} + +#[stable(feature = "io_safety", since = "1.63.0")] +impl AsRawFd for BorrowedFd<'_> { + fn as_raw_fd(&self) -> RawFd { + self.fd + } +} + +// Owned + +#[stable(feature = "io_safety", since = "1.63.0")] +impl AsFd for OwnedFd { + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } + } +} + +#[stable(feature = "io_safety", since = "1.63.0")] +impl IntoRawFd for OwnedFd { + fn into_raw_fd(self) -> RawFd { + let fd = self.fd; + forget(self); + fd + } +} + +#[stable(feature = "io_safety", since = "1.63.0")] +impl FromRawFd for OwnedFd { + unsafe fn from_raw_fd(fd: RawFd) -> Self { + Self { fd } + } +} + +#[stable(feature = "io_safety", since = "1.63.0")] +impl AsRawFd for OwnedFd { + fn as_raw_fd(&self) -> RawFd { + self.fd + } +} + +#[stable(feature = "io_safety", since = "1.63.0")] +impl Drop for OwnedFd { + fn drop(&mut self) { + unsafe { + yggdrasil_rt::sys::close(self.fd).ok(); + } + } +} + +// TODO: AsFd for File, From for OwnedFd, From for File, diff --git a/library/std/src/os/yggdrasil/io/raw.rs b/library/std/src/os/yggdrasil/io/raw.rs new file mode 100644 index 00000000000..dcaa7e9ef99 --- /dev/null +++ b/library/std/src/os/yggdrasil/io/raw.rs @@ -0,0 +1,69 @@ +#![stable(feature = "os_fd", since = "1.66.0")] + +#[stable(feature = "rust1", since = "1.0.0")] +pub type RawFd = yggdrasil_rt::io::RawFd; + +macro_rules! stdio_impl_as_raw_fd { + ($($ty:ty => $n:expr),*) => {$( + #[stable(feature = "asraw_stdio", since = "1.21.0")] + impl AsRawFd for $ty { + #[inline] + fn as_raw_fd(&self) -> RawFd { + $n + } + } + + #[stable(feature = "asraw_stdio", since = "1.21.0")] + impl AsRawFd for &$ty { + #[inline] + fn as_raw_fd(&self) -> RawFd { + $n + } + } + )*}; +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub trait AsRawFd { + #[stable(feature = "rust1", since = "1.0.0")] + fn as_raw_fd(&self) -> RawFd; +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub trait FromRawFd { + #[stable(feature = "rust1", since = "1.0.0")] + unsafe fn from_raw_fd(fd: RawFd) -> Self; +} + +#[stable(feature = "rust1", since = "1.0.0")] +pub trait IntoRawFd { + #[stable(feature = "rust1", since = "1.0.0")] + fn into_raw_fd(self) -> RawFd; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl AsRawFd for RawFd { + fn as_raw_fd(&self) -> RawFd { + *self + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromRawFd for RawFd { + unsafe fn from_raw_fd(fd: RawFd) -> Self { + fd + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoRawFd for RawFd { + fn into_raw_fd(self) -> RawFd { + self + } +} + +stdio_impl_as_raw_fd!( + crate::io::Stdin => RawFd::STDIN, + crate::io::Stdout => RawFd::STDOUT, + crate::io::Stderr => RawFd::STDERR +); diff --git a/library/std/src/sys/yggdrasil/locks.rs b/library/std/src/sys/yggdrasil/locks.rs deleted file mode 100644 index 21c6465b22f..00000000000 --- a/library/std/src/sys/yggdrasil/locks.rs +++ /dev/null @@ -1,135 +0,0 @@ -mod condvar { - use crate::sys::locks::Mutex; - use crate::time::Duration; - - pub struct Condvar {} - - impl Condvar { - #[inline] - #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] - pub const fn new() -> Condvar { - Condvar {} - } - - #[inline] - pub fn notify_one(&self) {} - - #[inline] - pub fn notify_all(&self) {} - - pub unsafe fn wait(&self, _mutex: &Mutex) { - panic!("condvar wait not supported") - } - - pub unsafe fn wait_timeout(&self, _mutex: &Mutex, _dur: Duration) -> bool { - panic!("condvar wait not supported"); - } - } -} - -mod mutex { - use crate::cell::Cell; - - pub struct Mutex { - // This platform has no threads, so we can use a Cell here. - locked: Cell, - } - - unsafe impl Send for Mutex {} - unsafe impl Sync for Mutex {} // no threads on this platform - - impl Mutex { - #[inline] - #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] - pub const fn new() -> Mutex { - Mutex { locked: Cell::new(false) } - } - - #[inline] - pub fn lock(&self) { - assert_eq!(self.locked.replace(true), false, "cannot recursively acquire mutex"); - } - - #[inline] - pub unsafe fn unlock(&self) { - self.locked.set(false); - } - - #[inline] - pub fn try_lock(&self) -> bool { - self.locked.replace(true) == false - } - } -} - -mod rwlock { - use crate::cell::Cell; - - pub struct RwLock { - // This platform has no threads, so we can use a Cell here. - mode: Cell, - } - - unsafe impl Send for RwLock {} - unsafe impl Sync for RwLock {} // no threads on this platform - - impl RwLock { - #[inline] - #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] - pub const fn new() -> RwLock { - RwLock { mode: Cell::new(0) } - } - - #[inline] - pub fn read(&self) { - let m = self.mode.get(); - if m >= 0 { - self.mode.set(m + 1); - } else { - rtabort!("rwlock locked for writing"); - } - } - - #[inline] - pub fn try_read(&self) -> bool { - let m = self.mode.get(); - if m >= 0 { - self.mode.set(m + 1); - true - } else { - false - } - } - - #[inline] - pub fn write(&self) { - if self.mode.replace(-1) != 0 { - rtabort!("rwlock locked for reading") - } - } - - #[inline] - pub fn try_write(&self) -> bool { - if self.mode.get() == 0 { - self.mode.set(-1); - true - } else { - false - } - } - - #[inline] - pub unsafe fn read_unlock(&self) { - self.mode.set(self.mode.get() - 1); - } - - #[inline] - pub unsafe fn write_unlock(&self) { - assert_eq!(self.mode.replace(0), -1); - } - } -} - -pub use condvar::Condvar; -pub use mutex::Mutex; -pub use rwlock::RwLock; diff --git a/library/std/src/sys/yggdrasil/locks/condvar.rs b/library/std/src/sys/yggdrasil/locks/condvar.rs new file mode 100644 index 00000000000..90d3ff85482 --- /dev/null +++ b/library/std/src/sys/yggdrasil/locks/condvar.rs @@ -0,0 +1,68 @@ +use crate::sync::atomic::{AtomicU32, Ordering}; +use crate::sys::locks::Mutex; +use crate::time::Duration; +use yggdrasil_rt::{process::MutexOperation, sys}; + +pub struct Condvar { + value: AtomicU32, +} + +impl Condvar { + #[inline] + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] + pub const fn new() -> Condvar { + Condvar { value: AtomicU32::new(0) } + } + + #[inline] + pub fn notify_one(&self) { + self.value.fetch_add(1, Ordering::Release); + + unsafe { + sys::mutex(&self.value, &MutexOperation::Wake).ok(); + } + } + + #[inline] + pub fn notify_all(&self) { + self.value.fetch_add(1, Ordering::Release); + + unsafe { + sys::mutex(&self.value, &MutexOperation::WakeAll).ok(); + } + } + + pub unsafe fn wait(&self, mutex: &Mutex) { + // Load the old value while the lock is still held + let compare_value = self.value.load(Ordering::Acquire); + + // Release the lock so others can now access the value + mutex.unlock(); + + // Wait for the value to change + self.wait_inner(compare_value, None); + + // Re-lock the mutex + mutex.lock(); + } + + pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool { + // Load the old value while the lock is still held + let compare_value = self.value.load(Ordering::Acquire); + + // Release the lock so others can now access the value + mutex.unlock(); + + // Wait for the value to change + let r = self.wait_inner(compare_value, Some(dur)); + + // Re-lock the mutex + mutex.lock(); + + r + } + + unsafe fn wait_inner(&self, value: u32, timeout: Option) -> bool { + sys::mutex(&self.value, &MutexOperation::Wait(value, timeout)).is_ok() + } +} diff --git a/library/std/src/sys/yggdrasil/locks/mod.rs b/library/std/src/sys/yggdrasil/locks/mod.rs new file mode 100644 index 00000000000..0bdc4a1e1db --- /dev/null +++ b/library/std/src/sys/yggdrasil/locks/mod.rs @@ -0,0 +1,7 @@ +mod condvar; +mod mutex; +mod rwlock; + +pub use condvar::Condvar; +pub use mutex::Mutex; +pub use rwlock::RwLock; diff --git a/library/std/src/sys/yggdrasil/locks/mutex.rs b/library/std/src/sys/yggdrasil/locks/mutex.rs new file mode 100644 index 00000000000..15bc5808e3e --- /dev/null +++ b/library/std/src/sys/yggdrasil/locks/mutex.rs @@ -0,0 +1,60 @@ +use crate::sync::atomic::{AtomicU32, Ordering}; +use crate::time::Duration; +use yggdrasil_rt::{process::MutexOperation, sys}; + +pub struct Mutex { + value: AtomicU32, +} + +unsafe impl Send for Mutex {} +unsafe impl Sync for Mutex {} // no threads on this platform + +impl Mutex { + const UNLOCKED: u32 = 0; + const LOCKED: u32 = 1; + + #[inline] + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] + pub const fn new() -> Mutex { + Mutex { value: AtomicU32::new(Self::UNLOCKED) } + } + + #[inline] + pub fn lock(&self) { + loop { + if self.try_lock() { + // Got a lock! + return; + } + + // Wait until the value becomes something other than "1" (0) + self.wait(Self::LOCKED); + } + } + + #[inline] + pub unsafe fn unlock(&self) { + if self.value.swap(Self::UNLOCKED, Ordering::Release) != Self::UNLOCKED { + self.wake(); + } + } + + #[inline] + pub fn try_lock(&self) -> bool { + self.value + .compare_exchange(Self::UNLOCKED, Self::LOCKED, Ordering::Acquire, Ordering::Relaxed) + .is_ok() + } + + fn wait(&self, value: u32) { + unsafe { + sys::mutex(&self.value, &MutexOperation::Wait(value, None)).ok(); + } + } + + fn wake(&self) { + unsafe { + sys::mutex(&self.value, &MutexOperation::Wake).ok(); + } + } +} diff --git a/library/std/src/sys/yggdrasil/locks/rwlock.rs b/library/std/src/sys/yggdrasil/locks/rwlock.rs new file mode 100644 index 00000000000..f9503717dae --- /dev/null +++ b/library/std/src/sys/yggdrasil/locks/rwlock.rs @@ -0,0 +1,64 @@ +use crate::cell::Cell; + +pub struct RwLock { + mode: Cell, +} + +unsafe impl Send for RwLock {} +unsafe impl Sync for RwLock {} // no threads on this platform + +impl RwLock { + #[inline] + #[rustc_const_stable(feature = "const_locks", since = "1.63.0")] + pub const fn new() -> RwLock { + RwLock { mode: Cell::new(0) } + } + + #[inline] + pub fn read(&self) { + let m = self.mode.get(); + if m >= 0 { + self.mode.set(m + 1); + } else { + rtabort!("rwlock locked for writing"); + } + } + + #[inline] + pub fn try_read(&self) -> bool { + let m = self.mode.get(); + if m >= 0 { + self.mode.set(m + 1); + true + } else { + false + } + } + + #[inline] + pub fn write(&self) { + if self.mode.replace(-1) != 0 { + rtabort!("rwlock locked for reading") + } + } + + #[inline] + pub fn try_write(&self) -> bool { + if self.mode.get() == 0 { + self.mode.set(-1); + true + } else { + false + } + } + + #[inline] + pub unsafe fn read_unlock(&self) { + self.mode.set(self.mode.get() - 1); + } + + #[inline] + pub unsafe fn write_unlock(&self) { + assert_eq!(self.mode.replace(0), -1); + } +} diff --git a/library/std/src/sys/yggdrasil/mod.rs b/library/std/src/sys/yggdrasil/mod.rs index ad868a22d7f..de107ad4d37 100644 --- a/library/std/src/sys/yggdrasil/mod.rs +++ b/library/std/src/sys/yggdrasil/mod.rs @@ -28,6 +28,7 @@ pub mod pipe; pub mod process; pub mod stdio; pub mod thread; +pub mod thread_local_dtor; pub mod thread_local_key; pub mod time; diff --git a/library/std/src/sys/yggdrasil/thread.rs b/library/std/src/sys/yggdrasil/thread.rs index 2945a97cfa6..d9674030f57 100644 --- a/library/std/src/sys/yggdrasil/thread.rs +++ b/library/std/src/sys/yggdrasil/thread.rs @@ -1,16 +1,32 @@ use crate::ffi::CStr; use crate::io; use crate::num::NonZeroUsize; +use crate::sys::cvt_io; use crate::time::Duration; -pub struct Thread(!); +use yggdrasil_rt::{process::ThreadSpawnOptions, sys}; + +#[repr(C)] +pub struct Thread { + id: u32, +} pub const DEFAULT_MIN_STACK_SIZE: usize = 8192; impl Thread { - pub unsafe fn new(_stack: usize, _p: Box) -> io::Result { - yggdrasil_rt::sys::debug_trace("Thread::new()"); - loop {} + pub unsafe fn new(stack_size: usize, p: Box) -> io::Result { + // Allocate the stack + let (stack_bottom, _, _) = Vec::into_raw_parts(vec![0u8; stack_size]); + let stack_bottom = stack_bottom.addr(); + let stack_top = stack_bottom + stack_size - 8; + + // Get the "argument" + let argument = Box::into_raw(Box::new(p)).addr() as u64; + + let options = ThreadSpawnOptions { entry: Thread::entry, argument, stack_top }; + let id = cvt_io(sys::spawn_thread(&options))?; + + Ok(Thread { id }) } pub fn yield_now() { @@ -35,6 +51,21 @@ impl Thread { } loop {} } + + extern "C" fn entry(arg: u64) -> ! { + use yggdrasil_rt::{debug_trace, process::ExitCode, sys}; + + unsafe { + #[allow(fuzzy_provenance_casts)] + let p: Box> = Box::from_raw(arg as *mut _); + + debug_trace!("Execute thread"); + p(); + debug_trace!("Thread finish"); + + sys::exit(ExitCode::Exited(0)); + } + } } pub fn available_parallelism() -> io::Result { diff --git a/library/std/src/sys/yggdrasil/thread_local_dtor.rs b/library/std/src/sys/yggdrasil/thread_local_dtor.rs new file mode 100644 index 00000000000..047a47df55b --- /dev/null +++ b/library/std/src/sys/yggdrasil/thread_local_dtor.rs @@ -0,0 +1,29 @@ +pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { + yggdrasil_rt::debug_trace!("TODO: thread_local_dtor::register_dtor()"); + + // From *nix impl: + // + // use crate::mem; + // use crate::sys_common::thread_local_dtor::register_dtor_fallback; + + // extern "C" { + // #[linkage = "extern_weak"] + // static __dso_handle: *mut u8; + // #[linkage = "extern_weak"] + // static __cxa_thread_atexit_impl: *const libc::c_void; + // } + // if !__cxa_thread_atexit_impl.is_null() { + // type F = unsafe extern "C" fn( + // dtor: unsafe extern "C" fn(*mut u8), + // arg: *mut u8, + // dso_handle: *mut u8, + // ) -> libc::c_int; + // mem::transmute::<*const libc::c_void, F>(__cxa_thread_atexit_impl)( + // dtor, + // t, + // &__dso_handle as *const _ as *mut _, + // ); + // return; + // } + // register_dtor_fallback(t, dtor); +} diff --git a/library/std/src/sys/yggdrasil/thread_local_key.rs b/library/std/src/sys/yggdrasil/thread_local_key.rs index f234a326565..c8e93639db3 100644 --- a/library/std/src/sys/yggdrasil/thread_local_key.rs +++ b/library/std/src/sys/yggdrasil/thread_local_key.rs @@ -27,6 +27,7 @@ impl LocalKey { #[inline] pub unsafe fn create(dtor: Option) -> Key { + yggdrasil_rt::debug_trace!("LocalKey::create()"); let boxed = Box::new(LocalKey::new(dtor)); let key = Box::into_raw(boxed); key as usize diff --git a/yggdrasil-rt b/yggdrasil-rt index f00ecdb926c..87874745c05 160000 --- a/yggdrasil-rt +++ b/yggdrasil-rt @@ -1 +1 @@ -Subproject commit f00ecdb926c2f912d658589f9f631100e41ad6c5 +Subproject commit 87874745c054a872226f00d9b7fe1756ec2c01ab