From 6f4bf66548e38c23b4fc169eafc730806c7e35d8 Mon Sep 17 00:00:00 2001 From: lhw Date: Sun, 15 Dec 2024 15:31:03 +0800 Subject: [PATCH] move signal handle into ruxtask and fix sys_rt_rigaction --- api/ruxos_posix_api/Cargo.toml | 2 +- api/ruxos_posix_api/src/imp/rt_sig.rs | 20 ++++++-- api/ruxos_posix_api/src/imp/signal.rs | 2 +- modules/ruxruntime/src/lib.rs | 4 +- modules/ruxtask/Cargo.toml | 1 + modules/ruxtask/src/lib.rs | 8 ++++ modules/{ruxruntime => ruxtask}/src/signal.rs | 46 +++++++++++++------ modules/ruxtask/src/task.rs | 36 ++++++++++++--- ulib/ruxlibc/src/signal.rs | 27 +++++++---- 9 files changed, 108 insertions(+), 38 deletions(-) rename modules/{ruxruntime => ruxtask}/src/signal.rs (74%) diff --git a/api/ruxos_posix_api/Cargo.toml b/api/ruxos_posix_api/Cargo.toml index 927068c81..4fe38279f 100644 --- a/api/ruxos_posix_api/Cargo.toml +++ b/api/ruxos_posix_api/Cargo.toml @@ -24,7 +24,7 @@ multitask = ["ruxfeat/multitask", "ruxtask/multitask", "dep:ruxfutex"] fd = ["alloc"] fs = ["dep:ruxfs", "ruxfeat/fs", "fd"] net = ["dep:ruxnet", "ruxfeat/net", "fd"] -signal = ["ruxruntime/signal", "ruxhal/signal"] +signal = ["ruxruntime/signal", "ruxhal/signal", "ruxtask/signal"] pipe = ["fd"] select = ["fd"] epoll = ["fd"] diff --git a/api/ruxos_posix_api/src/imp/rt_sig.rs b/api/ruxos_posix_api/src/imp/rt_sig.rs index 8d89cf6aa..252b6249a 100644 --- a/api/ruxos_posix_api/src/imp/rt_sig.rs +++ b/api/ruxos_posix_api/src/imp/rt_sig.rs @@ -95,10 +95,24 @@ pub unsafe fn sys_rt_sigaction( old: *mut ctypes::sigaction, _sigsetsize: ctypes::size_t, ) -> c_int { - debug!("sys_rt_sigaction <= sig: {}", sig); + debug!( + "sys_rt_sigaction <= sig: {} sa {:x} old {:x}", + sig, sa as u64, old as u64 + ); syscall_body!(sys_rt_sigaction, { - if sa as u64 == 0 || old as u64 == 0 { - Err(LinuxError::EFAULT) + if sa as u64 == 0 && old as u64 == 0 { + sys_sigaction(sig as _, None, None); + Ok(0) + } else if sa as u64 != 0 && old as u64 == 0 { + let sa = unsafe { *sa }; + let sa = k_sigaction::from(sa); + sys_sigaction(sig as _, Some(&sa), None); + Ok(0) + } else if sa as u64 == 0 && old as u64 != 0 { + let old = unsafe { *old }; + let mut old_sa = k_sigaction::from(old); + sys_sigaction(sig as _, None, Some(&mut old_sa)); + Ok(0) } else { let sa = unsafe { *sa }; let old = unsafe { *old }; diff --git a/api/ruxos_posix_api/src/imp/signal.rs b/api/ruxos_posix_api/src/imp/signal.rs index 743441583..929d4b3b1 100644 --- a/api/ruxos_posix_api/src/imp/signal.rs +++ b/api/ruxos_posix_api/src/imp/signal.rs @@ -14,7 +14,7 @@ use crate::ctypes::k_sigaction; use crate::ctypes::{self, pid_t}; use axerrno::LinuxError; -use ruxruntime::{rx_sigaction, Signal}; +use ruxtask::{rx_sigaction, Signal}; /// Set signal handler pub fn sys_sigaction( diff --git a/modules/ruxruntime/src/lib.rs b/modules/ruxruntime/src/lib.rs index d407ca36e..90e4034c0 100644 --- a/modules/ruxruntime/src/lib.rs +++ b/modules/ruxruntime/src/lib.rs @@ -39,8 +39,6 @@ extern crate axlog; #[cfg(all(target_os = "none", not(test)))] mod lang_items; -#[cfg(feature = "signal")] -mod signal; #[cfg(not(feature = "musl"))] mod trap; @@ -52,7 +50,7 @@ mod mp; pub use self::mp::rust_main_secondary; #[cfg(feature = "signal")] -pub use self::signal::{rx_sigaction, Signal}; +use ruxtask::signal::{rx_sigaction, Signal}; #[cfg(feature = "alloc")] extern crate alloc; diff --git a/modules/ruxtask/Cargo.toml b/modules/ruxtask/Cargo.toml index 3b4b13c6e..386912fbb 100644 --- a/modules/ruxtask/Cargo.toml +++ b/modules/ruxtask/Cargo.toml @@ -24,6 +24,7 @@ musl = [] preempt = ["irq", "percpu?/preempt", "kernel_guard/preempt"] paging = [] fs = [] +signal = [] sched_fifo = ["multitask"] sched_rr = ["multitask", "preempt"] diff --git a/modules/ruxtask/src/lib.rs b/modules/ruxtask/src/lib.rs index fbbbaf76d..0bcfaff3f 100644 --- a/modules/ruxtask/src/lib.rs +++ b/modules/ruxtask/src/lib.rs @@ -48,6 +48,8 @@ cfg_if::cfg_if! { pub mod task; mod api; mod wait_queue; + #[cfg(feature = "signal")] + pub mod signal; #[cfg(feature = "paging")] pub mod vma; // #[cfg(feature = "fs")] @@ -79,8 +81,14 @@ cfg_if::cfg_if! { pub use self::api::*; pub use self::api::{sleep, sleep_until, yield_now}; pub use task::TaskState; + #[cfg(feature = "signal")] + pub use self::signal::{rx_sigaction, Signal}; } else { mod api_s; + #[cfg(feature = "signal")] + pub mod signal; pub use self::api_s::{sleep, sleep_until, yield_now}; + #[cfg(feature = "signal")] + pub use self::signal::{rx_sigaction, Signal}; } } diff --git a/modules/ruxruntime/src/signal.rs b/modules/ruxtask/src/signal.rs similarity index 74% rename from modules/ruxruntime/src/signal.rs rename to modules/ruxtask/src/signal.rs index 148afd29f..0f64c63b7 100644 --- a/modules/ruxruntime/src/signal.rs +++ b/modules/ruxtask/src/signal.rs @@ -7,6 +7,7 @@ * See the Mulan PSL v2 for more details. */ +use crate::current; #[cfg(feature = "irq")] use core::sync::atomic::AtomicI64; use core::{ @@ -85,6 +86,17 @@ impl TrapHandler for SignalHandler { } impl Signal { + ///crate new Signal struct + pub fn new() -> Self { + Self { + #[cfg(feature = "irq")] + signal: AtomicI64::new(0), + sigaction: [rx_sigaction::new(); 32], + // Default::default() is not const + timer_value: [Duration::from_nanos(0); 3], + timer_interval: [Duration::from_nanos(0); 3], + } + } /// Set signal /// signum: signal number, if signum < 0, just return current signal /// on: true: enable signal, false: disable signal @@ -94,7 +106,9 @@ impl Signal { if signum >= 32 { return None; } - let mut old = unsafe { SIGNAL_IF.signal.load(Ordering::Acquire) }; + let binding = current(); + let mut current_signal_if = binding.signal_if.lock(); + let mut old = unsafe { current_signal_if.signal.load(Ordering::Acquire) }; if signum >= 0 { loop { let new = if on { @@ -104,7 +118,7 @@ impl Signal { }; match unsafe { - SIGNAL_IF.signal.compare_exchange_weak( + current_signal_if.signal.compare_exchange_weak( old, new, Ordering::AcqRel, @@ -126,21 +140,21 @@ impl Signal { sigaction: Option<*const rx_sigaction>, oldact: Option<*mut rx_sigaction>, ) { - if signum >= unsafe { SIGNAL_IF.sigaction }.len() as u8 { + let binding = current(); + let mut current_signal_if = binding.signal_if.lock(); + if signum >= unsafe { current_signal_if.sigaction }.len() as u8 { return; } if let Some(oldact) = oldact { unsafe { - *oldact = SIGNAL_IF.sigaction[signum as usize]; + *oldact = current_signal_if.sigaction[signum as usize]; } } match sigaction { Some(s) => unsafe { - SIGNAL_IF.sigaction[signum as usize] = *s; - }, - None => unsafe { - SIGNAL_IF.sigaction[signum as usize].sa_handler.unwrap()(signum as c_int) + current_signal_if.sigaction[signum as usize] = *s; }, + None => {}, } } /// Set timer @@ -148,13 +162,15 @@ impl Signal { /// new_value: new timer value /// old_value: old timer value pub fn timer_deadline(which: usize, new_deadline: Option) -> Option { - if which >= unsafe { SIGNAL_IF.timer_value }.len() { + let binding = current(); + let mut current_signal_if = binding.signal_if.lock(); + if which >= unsafe { current_signal_if.timer_value }.len() { return None; } - let old = unsafe { SIGNAL_IF.timer_value }[which]; + let old = unsafe { current_signal_if.timer_value }[which]; if let Some(s) = new_deadline { unsafe { - SIGNAL_IF.timer_value[which] = Duration::from_nanos(s); + current_signal_if.timer_value[which] = Duration::from_nanos(s); } } Some(old.as_nanos() as u64) @@ -164,13 +180,15 @@ impl Signal { /// new_interval: new timer interval /// old_interval: old timer interval pub fn timer_interval(which: usize, new_interval: Option) -> Option { - if which >= unsafe { SIGNAL_IF.timer_interval }.len() { + let binding = current(); + let mut current_signal_if = binding.signal_if.lock(); + if which >= unsafe { current_signal_if.timer_interval }.len() { return None; } - let old = unsafe { SIGNAL_IF.timer_interval }[which]; + let old = unsafe { current_signal_if.timer_interval }[which]; if let Some(s) = new_interval { unsafe { - SIGNAL_IF.timer_interval[which] = Duration::from_nanos(s); + current_signal_if.timer_interval[which] = Duration::from_nanos(s); } } Some(old.as_nanos() as u64) diff --git a/modules/ruxtask/src/task.rs b/modules/ruxtask/src/task.rs index cc1a45d20..ce9e086bf 100644 --- a/modules/ruxtask/src/task.rs +++ b/modules/ruxtask/src/task.rs @@ -38,6 +38,8 @@ use crate::current; use crate::tsd::{DestrFunction, KEYS, TSD}; #[cfg(feature = "paging")] use crate::vma::MmapStruct; +#[cfg(feature = "signal")] +use crate::Signal; use crate::{AxRunQueue, AxTask, AxTaskRef, WaitQueue}; /// A unique identifier for a thread. @@ -81,6 +83,7 @@ pub struct TaskInner { exit_code: AtomicI32, wait_for_exit: WaitQueue, + stack_map_addr: SpinNoIrq, kstack: SpinNoIrq>>, ctx: UnsafeCell, @@ -90,6 +93,9 @@ pub struct TaskInner { #[cfg(not(feature = "musl"))] tsd: TSD, + #[cfg(feature = "signal")] + pub signal_if: Arc>, + // set tid #[cfg(feature = "musl")] set_tid: AtomicU64, @@ -235,6 +241,7 @@ impl TaskInner { preempt_disable_count: AtomicUsize::new(0), exit_code: AtomicI32::new(0), wait_for_exit: WaitQueue::new(), + stack_map_addr: SpinNoIrq::new(VirtAddr::from(0)), // should be set later kstack: SpinNoIrq::new(Arc::new(None)), ctx: UnsafeCell::new(TaskContext::new()), #[cfg(feature = "tls")] @@ -243,6 +250,8 @@ impl TaskInner { tsd: spinlock::SpinNoIrq::new([core::ptr::null_mut(); ruxconfig::PTHREAD_KEY_MAX]), #[cfg(feature = "musl")] set_tid: AtomicU64::new(0), + #[cfg(feature = "signal")] + signal_if: current().signal_if.clone(), #[cfg(feature = "musl")] tl: AtomicU64::new(0), #[cfg(feature = "paging")] @@ -279,11 +288,14 @@ impl TaskInner { preempt_disable_count: AtomicUsize::new(0), exit_code: AtomicI32::new(0), wait_for_exit: WaitQueue::new(), + stack_map_addr: SpinNoIrq::new(VirtAddr::from(0)), kstack: SpinNoIrq::new(Arc::new(None)), ctx: UnsafeCell::new(TaskContext::new()), #[cfg(feature = "tls")] tls: TlsArea::new_with_addr(tls), set_tid, + #[cfg(feature = "signal")] + signal_if: current().signal_if.clone(), // clear child tid tl, #[cfg(feature = "paging")] @@ -299,6 +311,7 @@ impl TaskInner { pub fn set_stack_top(&self, begin: usize, size: usize) { debug!("set_stack_top: begin={:#x}, size={:#x}", begin, size); + *self.stack_map_addr.lock() = VirtAddr::from(begin); *self.kstack.lock() = Arc::new(Some(TaskStack { ptr: NonNull::new(begin as *mut u8).unwrap(), layout: Layout::from_size_align(size, PAGE_SIZE_4K).unwrap(), @@ -406,14 +419,14 @@ impl TaskInner { // Note: the stack region is mapped to the same position as the parent process's stack, be careful when update the stack region for the forked process. let (_, prev_flag, _) = cloned_page_table - .query(current_stack.end()) + .query(*current().stack_map_addr.lock()) .expect("failed to query stack region when forking"); cloned_page_table - .unmap_region(current_stack.end(), align_up_4k(stack_size)) + .unmap_region(*current().stack_map_addr.lock(), align_up_4k(stack_size)) .expect("failed to unmap stack region when forking"); cloned_page_table .map_region( - current_stack.end(), + *current().stack_map_addr.lock(), stack_paddr, stack_size, prev_flag, @@ -477,10 +490,11 @@ impl TaskInner { need_resched: AtomicBool::new(current_task.need_resched.load(Ordering::Relaxed)), #[cfg(feature = "preempt")] preempt_disable_count: AtomicUsize::new( - current_task.preempt_disable_count.load(Ordering::Relaxed), + current_task.preempt_disable_count.load(Ordering::Acquire), ), exit_code: AtomicI32::new(0), wait_for_exit: WaitQueue::new(), + stack_map_addr: SpinNoIrq::new(*current().stack_map_addr.lock()), kstack: SpinNoIrq::new(Arc::new(Some(new_stack))), ctx: UnsafeCell::new(TaskContext::new()), #[cfg(feature = "tls")] @@ -489,6 +503,8 @@ impl TaskInner { tsd: spinlock::SpinNoIrq::new([core::ptr::null_mut(); ruxconfig::PTHREAD_KEY_MAX]), #[cfg(feature = "musl")] set_tid: AtomicU64::new(0), + #[cfg(feature = "signal")] + signal_if: Arc::new(spinlock::SpinNoIrq::new(Signal::new())), #[cfg(feature = "musl")] tl: AtomicU64::new(0), #[cfg(feature = "paging")] @@ -515,6 +531,7 @@ impl TaskInner { .lock() .insert(new_pid.as_u64(), task_ref.clone()); + warn!("forked task: save_current_content {}", task_ref.id_name()); unsafe { // copy the stack content from current stack to new stack (*task_ref.ctx_mut_ptr()).save_current_content( @@ -554,6 +571,7 @@ impl TaskInner { preempt_disable_count: AtomicUsize::new(0), exit_code: AtomicI32::new(0), wait_for_exit: WaitQueue::new(), + stack_map_addr: SpinNoIrq::new(VirtAddr::from(0)), // set in set_stack_top kstack: SpinNoIrq::new(Arc::new(None)), ctx: UnsafeCell::new(TaskContext::new()), #[cfg(feature = "tls")] @@ -562,6 +580,8 @@ impl TaskInner { tsd: spinlock::SpinNoIrq::new([core::ptr::null_mut(); ruxconfig::PTHREAD_KEY_MAX]), #[cfg(feature = "musl")] set_tid: AtomicU64::new(0), + #[cfg(feature = "signal")] + signal_if: Arc::new(spinlock::SpinNoIrq::new(Signal::new())), #[cfg(feature = "musl")] tl: AtomicU64::new(0), #[cfg(feature = "paging")] @@ -590,6 +610,7 @@ impl TaskInner { let bindings = PROCESS_MAP.lock(); let (&_parent_id, &ref task_ref) = bindings.first_key_value().unwrap(); let idle_kstack = TaskStack::alloc(align_up_4k(IDLE_STACK_SIZE)); + let idle_kstack_top = idle_kstack.top(); let mut t = Self { parent_process: Some(Arc::downgrade(task_ref)), @@ -609,7 +630,8 @@ impl TaskInner { preempt_disable_count: AtomicUsize::new(0), exit_code: AtomicI32::new(0), wait_for_exit: WaitQueue::new(), - kstack: SpinNoIrq::new(Arc::new(None)), + stack_map_addr: SpinNoIrq::new(idle_kstack.end()), + kstack: SpinNoIrq::new(Arc::new(Some(idle_kstack))), ctx: UnsafeCell::new(TaskContext::new()), #[cfg(feature = "tls")] tls: TlsArea::alloc(), @@ -617,6 +639,8 @@ impl TaskInner { tsd: spinlock::SpinNoIrq::new([core::ptr::null_mut(); ruxconfig::PTHREAD_KEY_MAX]), #[cfg(feature = "musl")] set_tid: AtomicU64::new(0), + #[cfg(feature = "signal")] + signal_if: task_ref.signal_if.clone(), #[cfg(feature = "musl")] tl: AtomicU64::new(0), #[cfg(feature = "paging")] @@ -633,7 +657,7 @@ impl TaskInner { debug!("new idle task: {}", t.id_name()); t.ctx .get_mut() - .init(task_entry as usize, idle_kstack.top(), tls); + .init(task_entry as usize, idle_kstack_top, tls); let task_ref = Arc::new(AxTask::new(t)); diff --git a/ulib/ruxlibc/src/signal.rs b/ulib/ruxlibc/src/signal.rs index 1fc19d958..080c59f3f 100644 --- a/ulib/ruxlibc/src/signal.rs +++ b/ulib/ruxlibc/src/signal.rs @@ -29,17 +29,24 @@ pub unsafe extern "C" fn sigaction_inner( } #[cfg(feature = "signal")] { - let mut sh = (*_act).__sa_handler.sa_handler; - if let Some(h) = sh { - if h as usize == crate::ctypes::SIGIGN as usize { - sh = Some(ignore_handler as unsafe extern "C" fn(c_int)); + + let k_act = { + if _act.is_null() { + None + } else { + let mut sh = (*_act).__sa_handler.sa_handler; + if let Some(h) = sh { + if h as usize == crate::ctypes::SIGIGN as usize { + sh = Some(ignore_handler as unsafe extern "C" fn(c_int)); + } + } + k_sigaction { + handler: sh, + flags: (*_act).sa_flags as _, + restorer: (*_act).sa_restorer, + mask: Default::default(), + } } - } - let k_act = k_sigaction { - handler: sh, - flags: (*_act).sa_flags as _, - restorer: (*_act).sa_restorer, - mask: Default::default(), }; let mut k_oldact = k_sigaction::default(); sys_sigaction(