alnyan/yggdrasil: thread+static TLS, mutex+condvar impl
This commit is contained in:
@@ -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*)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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*)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<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(())
|
||||
}
|
||||
}
|
||||
|
||||
#[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 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)
|
||||
}
|
||||
|
||||
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<T: AsFd> 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<File> for OwnedFd, From<OwnedFd> 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!()
|
||||
}
|
||||
}
|
||||
@@ -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<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 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)
|
||||
}
|
||||
@@ -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 }
|
||||
@@ -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<T: AsFd> 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<File> for OwnedFd, From<OwnedFd> for File,
|
||||
@@ -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
|
||||
);
|
||||
@@ -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<bool>,
|
||||
}
|
||||
|
||||
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<isize>,
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -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<Duration>) -> bool {
|
||||
sys::mutex(&self.value, &MutexOperation::Wait(value, timeout)).is_ok()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
mod condvar;
|
||||
mod mutex;
|
||||
mod rwlock;
|
||||
|
||||
pub use condvar::Condvar;
|
||||
pub use mutex::Mutex;
|
||||
pub use rwlock::RwLock;
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
use crate::cell::Cell;
|
||||
|
||||
pub struct RwLock {
|
||||
mode: Cell<i32>,
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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<dyn FnOnce()>) -> io::Result<Thread> {
|
||||
yggdrasil_rt::sys::debug_trace("Thread::new()");
|
||||
loop {}
|
||||
pub unsafe fn new(stack_size: usize, p: Box<dyn FnOnce()>) -> io::Result<Thread> {
|
||||
// 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<dyn FnOnce()>> = 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<NonZeroUsize> {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -27,6 +27,7 @@ impl LocalKey {
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn create(dtor: Option<unsafe extern "C" fn(*mut u8)>) -> Key {
|
||||
yggdrasil_rt::debug_trace!("LocalKey::create()");
|
||||
let boxed = Box::new(LocalKey::new(dtor));
|
||||
let key = Box::into_raw(boxed);
|
||||
key as usize
|
||||
|
||||
+1
-1
Submodule yggdrasil-rt updated: f00ecdb926...87874745c0
Reference in New Issue
Block a user