From 8e5ddbd6547d44e4fdde5a50fb92b693f9dd16e0 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 4 Aug 2024 18:31:24 +0200 Subject: [PATCH] Implement sigsuspend. --- redox-rt/src/signal.rs | 27 +++++++++++++++++++++++---- src/header/signal/mod.rs | 2 +- src/platform/linux/signal.rs | 6 ++++-- src/platform/pal/signal.rs | 2 +- src/platform/redox/signal.rs | 19 +++++-------------- 5 files changed, 34 insertions(+), 22 deletions(-) diff --git a/redox-rt/src/signal.rs b/redox-rt/src/signal.rs index 73e26ba02..ce2a4344d 100644 --- a/redox-rt/src/signal.rs +++ b/redox-rt/src/signal.rs @@ -657,11 +657,30 @@ pub unsafe fn sigaltstack( pub const MIN_SIGALTSTACK_SIZE: usize = 8192; -pub fn currently_pending() -> u64 { +pub fn currently_pending_blocked() -> u64 { let control = &unsafe { Tcb::current().unwrap() }.os_specific.control; let w0 = control.word[0].load(Ordering::Relaxed); let w1 = control.word[1].load(Ordering::Relaxed); - let pending_blocked_lo = w0 & !(w0 >> 32); - let pending_unblocked_hi = w1 & !(w0 >> 32); - pending_blocked_lo | (pending_unblocked_hi << 32) + let allow = (w0 >> 32) | ((w1 >> 32) << 32); + let thread_pending = (w0 & 0xffff_ffff) | ((w1 >> 32) & 0xffff_ffff); + let proc_pending = PROC_CONTROL_STRUCT.pending.load(Ordering::Relaxed); + + core::sync::atomic::fence(Ordering::Acquire); // TODO: Correct ordering? + + (thread_pending | proc_pending) & !allow +} +pub enum Unreachable {} +pub fn wait_with_mask(mask: u64) -> Result<Unreachable, Error> { + let mut old = 0; + set_sigmask(Some(mask), Some(&mut old))?; + let res = syscall::nanosleep( + &syscall::TimeSpec { + tv_sec: i64::MAX, + tv_nsec: 0, + }, + &mut syscall::TimeSpec::default(), + ); + set_sigmask(Some(old), None)?; + res?; + unreachable!() } diff --git a/src/header/signal/mod.rs b/src/header/signal/mod.rs index 6fe93ed26..5a4e4f252 100644 --- a/src/header/signal/mod.rs +++ b/src/header/signal/mod.rs @@ -359,7 +359,7 @@ pub unsafe extern "C" fn sigset( #[no_mangle] pub unsafe extern "C" fn sigsuspend(sigmask: *const sigset_t) -> c_int { - Sys::sigsuspend(&*sigmask) + Err(Sys::sigsuspend(&*sigmask)).or_minus_one_errno() } #[no_mangle] diff --git a/src/platform/linux/signal.rs b/src/platform/linux/signal.rs index a6ec22fb3..7d0f4990a 100644 --- a/src/platform/linux/signal.rs +++ b/src/platform/linux/signal.rs @@ -155,8 +155,10 @@ impl PalSignal for Sys { .map(|_| ()) } - fn sigsuspend(set: &sigset_t) -> c_int { - unsafe { e(syscall!(RT_SIGSUSPEND, set as *const sigset_t, NSIG / 8)) as c_int } + fn sigsuspend(set: &sigset_t) -> Errno { + unsafe { + e_raw(syscall!(RT_SIGSUSPEND, set as *const sigset_t, NSIG / 8)).expect_err("must fail") + } } unsafe fn sigtimedwait( diff --git a/src/platform/pal/signal.rs b/src/platform/pal/signal.rs index b00525a83..690ecdf38 100644 --- a/src/platform/pal/signal.rs +++ b/src/platform/pal/signal.rs @@ -37,7 +37,7 @@ pub trait PalSignal: Pal { oset: Option<&mut sigset_t>, ) -> Result<(), Errno>; - fn sigsuspend(set: &sigset_t) -> c_int; + fn sigsuspend(set: &sigset_t) -> Errno; // always fails unsafe fn sigtimedwait(set: *const sigset_t, sig: *mut siginfo_t, tp: *const timespec) -> c_int; diff --git a/src/platform/redox/signal.rs b/src/platform/redox/signal.rs index de89f5845..fab3e5641 100644 --- a/src/platform/redox/signal.rs +++ b/src/platform/redox/signal.rs @@ -246,7 +246,7 @@ impl PalSignal for Sys { } fn sigpending(set: &mut sigset_t) -> Result<(), Errno> { - *set = redox_rt::signal::currently_pending(); + *set = redox_rt::signal::currently_pending_blocked(); Ok(()) } @@ -264,20 +264,11 @@ impl PalSignal for Sys { }) } - fn sigsuspend(set: &sigset_t) -> c_int { - //TODO: correct implementation - let mut oset = sigset_t::default(); - if let Err(err) = redox_rt::signal::set_sigmask(Some(*set), Some(&mut oset)) { - Errno::from(err).sync(); - return -1; - } - //TODO: wait for signal - Self::sched_yield(); - if let Err(err) = redox_rt::signal::set_sigmask(Some(oset), None) { - Errno::from(err).sync(); - return -1; + fn sigsuspend(set: &sigset_t) -> Errno { + match redox_rt::signal::wait_with_mask(*set) { + Ok(_) => unreachable!(), + Err(err) => err.into(), } - 0 } unsafe fn sigtimedwait( -- GitLab