From 0fee0fd239845b1b5a798bb99c6240e20cd462e8 Mon Sep 17 00:00:00 2001 From: Stefan Lankes Date: Wed, 28 Feb 2024 09:46:58 +0100 Subject: [PATCH] add error number in thread local storage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keep a copy of the the error number in TLS Signed-off-by: Martin Kröning --- src/errno.rs | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ src/macros.rs | 52 ++++++++++++++++++++-------------- 3 files changed, 110 insertions(+), 21 deletions(-) diff --git a/src/errno.rs b/src/errno.rs index dc22dc8ced..07c68b64f7 100644 --- a/src/errno.rs +++ b/src/errno.rs @@ -395,3 +395,80 @@ pub const ERFKILL: i32 = 132; /// Robust mutexes: Memory page has hardware error pub const EHWPOISON: i32 = 133; + +#[cfg(all(not(feature = "common-os"), not(target_arch = "riscv64")))] +#[thread_local] +pub(crate) static ERRNO: core::cell::UnsafeCell = core::cell::UnsafeCell::new(0); + +/// Get the error number from the thread local storage +#[no_mangle] +pub extern "C" fn sys_get_errno() -> i32 { + cfg_if::cfg_if! { + if #[cfg(any(feature = "common-os", target_arch = "riscv64"))] { + 0 + } else { + unsafe { ERRNO.get().read() } + } + } +} + +pub(crate) trait ToErrno { + fn to_errno(&self) -> Option { + None + } + + fn set_errno(self) -> Self + where + Self: Sized, + { + if let Some(errno) = self.to_errno() { + cfg_if::cfg_if! { + if #[cfg(any(feature = "common-os", target_arch = "riscv64"))] { + let _ = errno; + } else { + unsafe { + ERRNO.get().write(errno); + } + } + } + } + self + } +} + +impl ToErrno for i32 { + fn to_errno(&self) -> Option { + let errno = if *self < 0 { -self } else { 0 }; + Some(errno) + } +} + +impl ToErrno for i64 { + fn to_errno(&self) -> Option { + let errno = if *self < 0 { + i32::try_from(-self).unwrap() + } else { + 0 + }; + Some(errno) + } +} + +impl ToErrno for isize { + fn to_errno(&self) -> Option { + let errno = if *self < 0 { + i32::try_from(-self).unwrap() + } else { + 0 + }; + Some(errno) + } +} + +impl ToErrno for u8 {} +impl ToErrno for u16 {} +impl ToErrno for u32 {} +impl ToErrno for usize {} +impl ToErrno for *mut u8 {} +impl ToErrno for () {} +impl ToErrno for ! {} diff --git a/src/lib.rs b/src/lib.rs index 443e2b3a6e..d1ba286635 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,6 +18,7 @@ #![feature(linked_list_cursors)] #![feature(maybe_uninit_slice)] #![feature(naked_functions)] +#![feature(never_type)] #![feature(new_uninit)] #![feature(noop_waker)] #![feature(pointer_is_aligned)] @@ -27,6 +28,7 @@ feature(specialization) )] #![feature(strict_provenance)] +#![feature(thread_local)] #![cfg_attr(target_os = "none", no_std)] #![cfg_attr(target_os = "none", feature(custom_test_frameworks))] #![cfg_attr(all(target_os = "none", test), test_runner(crate::test_runner))] diff --git a/src/macros.rs b/src/macros.rs index 4dca430372..64a1b22d04 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -78,33 +78,41 @@ macro_rules! dbg { feature = "common-os" )))] macro_rules! kernel_function { - ($f:ident()) => { - $crate::arch::switch::kernel_function0($f) - }; + ($f:ident()) => {{ + use $crate::errno::ToErrno; + $crate::arch::switch::kernel_function0($f).set_errno() + }}; - ($f:ident($arg1:expr)) => { - $crate::arch::switch::kernel_function1($f, $arg1) - }; + ($f:ident($arg1:expr)) => {{ + use $crate::errno::ToErrno; + #[allow(unreachable_code)] + $crate::arch::switch::kernel_function1($f, $arg1).set_errno() + }}; - ($f:ident($arg1:expr, $arg2:expr)) => { - $crate::arch::switch::kernel_function2($f, $arg1, $arg2) - }; + ($f:ident($arg1:expr, $arg2:expr)) => {{ + use $crate::errno::ToErrno; + $crate::arch::switch::kernel_function2($f, $arg1, $arg2).set_errno() + }}; - ($f:ident($arg1:expr, $arg2:expr, $arg3:expr)) => { - $crate::arch::switch::kernel_function3($f, $arg1, $arg2, $arg3) - }; + ($f:ident($arg1:expr, $arg2:expr, $arg3:expr)) => {{ + use $crate::errno::ToErrno; + $crate::arch::switch::kernel_function3($f, $arg1, $arg2, $arg3).set_errno() + }}; - ($f:ident($arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr)) => { - $crate::arch::switch::kernel_function4($f, $arg1, $arg2, $arg3, $arg4) - }; + ($f:ident($arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr)) => {{ + use $crate::errno::ToErrno; + $crate::arch::switch::kernel_function4($f, $arg1, $arg2, $arg3, $arg4).set_errno() + }}; - ($f:ident($arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr)) => { - $crate::arch::switch::kernel_function5($f, $arg1, $arg2, $arg3, $arg4, $arg5) - }; + ($f:ident($arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr)) => {{ + $crate::arch::switch::kernel_function5($f, $arg1, $arg2, $arg3, $arg4, $arg5).set_errno() + }}; - ($f:ident($arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr, $arg6:expr)) => { + ($f:ident($arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr, $arg6:expr)) => {{ + use $crate::errno::ToErrno; $crate::arch::switch::kernel_function6($f, $arg1, $arg2, $arg3, $arg4, $arg5, $arg6) - }; + .set_errno() + }}; } // TODO: Properly switch kernel stack with newlib @@ -117,7 +125,9 @@ macro_rules! kernel_function { ))] macro_rules! kernel_function { ($f:ident($($x:tt)*)) => {{ - $f($($x)*) + use $crate::errno::ToErrno; + #[allow(unreachable_code)] + $f($($x)*).set_errno() }}; }