From ffc628df539052d4a8e757209608ea28b33ba7d8 Mon Sep 17 00:00:00 2001 From: aLinChe <1129332011@qq.com> Date: Wed, 19 Nov 2025 00:33:56 +0800 Subject: [PATCH] feat setitimer/getitimer and fix signal stack logic (#1377) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add sys_get/setitimer and fix sig Signed-off-by: aLinChe <1129332011@qq.com> * feat cputime Signed-off-by: aLinChe <1129332011@qq.com> * fix sas and fix ABI Signed-off-by: aLinChe <1129332011@qq.com> * fix fmt Signed-off-by: aLinChe <1129332011@qq.com> * fix diff arch::on_sig_stack compile bug Signed-off-by: aLinChe <1129332011@qq.com> * fix better code Signed-off-by: aLinChe <1129332011@qq.com> * fix arch Signed-off-by: aLinChe <1129332011@qq.com> * fix fmt Signed-off-by: aLinChe <1129332011@qq.com> * refactor: 简化定时器类型格式化逻辑 - 移除不必要的字符串转换操作 - 使用Debug trait直接格式化枚举值 Signed-off-by: longjin --------- Signed-off-by: aLinChe <1129332011@qq.com> Signed-off-by: longjin Co-authored-by: longjin --- kernel/src/arch/loongarch64/interrupt/mod.rs | 6 + kernel/src/arch/loongarch64/ipc/signal.rs | 15 +- kernel/src/arch/riscv64/interrupt/mod.rs | 6 + kernel/src/arch/riscv64/ipc/signal.rs | 16 +- kernel/src/arch/x86_64/interrupt/mod.rs | 6 + kernel/src/arch/x86_64/ipc/signal.rs | 61 +++-- kernel/src/ipc/generic_signal.rs | 10 + kernel/src/ipc/sighand.rs | 7 +- kernel/src/ipc/syscall/sys_sigaltstack.rs | 88 +++--- kernel/src/process/execve.rs | 11 + kernel/src/process/mod.rs | 68 ++++- kernel/src/process/namespace/unshare.rs | 9 +- kernel/src/sched/cputime.rs | 50 +++- kernel/src/time/syscall/mod.rs | 49 ++++ kernel/src/time/syscall/sys_getitimer.rs | 94 +++++++ kernel/src/time/syscall/sys_setitimer.rs | 250 ++++++++++++++++++ .../syscall/gvisor/blocklists/itimer_test | 5 + .../gvisor/blocklists/sigaltstack_test | 4 + .../syscall/gvisor/blocklists/sigreturn_test | 2 + .../syscall/gvisor/blocklists/write_test | 2 +- user/apps/tests/syscall/gvisor/whitelist.txt | 5 + 21 files changed, 681 insertions(+), 83 deletions(-) create mode 100644 kernel/src/time/syscall/sys_getitimer.rs create mode 100644 kernel/src/time/syscall/sys_setitimer.rs create mode 100644 user/apps/tests/syscall/gvisor/blocklists/itimer_test create mode 100644 user/apps/tests/syscall/gvisor/blocklists/sigaltstack_test create mode 100644 user/apps/tests/syscall/gvisor/blocklists/sigreturn_test diff --git a/kernel/src/arch/loongarch64/interrupt/mod.rs b/kernel/src/arch/loongarch64/interrupt/mod.rs index bcc952861..72e0e09b2 100644 --- a/kernel/src/arch/loongarch64/interrupt/mod.rs +++ b/kernel/src/arch/loongarch64/interrupt/mod.rs @@ -104,6 +104,12 @@ impl TrapFrame { loongArch64::register::crmd::Crmd::from(self.csr_crmd).plv() == CpuMode::Ring3 } + /// 返回当前 TrapFrame 对应的用户态栈指针。 + #[inline(always)] + pub fn stack_pointer(&self) -> usize { + self.usp as usize + } + #[inline(never)] pub const fn new() -> Self { let x = core::mem::MaybeUninit::::zeroed(); diff --git a/kernel/src/arch/loongarch64/ipc/signal.rs b/kernel/src/arch/loongarch64/ipc/signal.rs index 429eaec6a..110e01bc3 100644 --- a/kernel/src/arch/loongarch64/ipc/signal.rs +++ b/kernel/src/arch/loongarch64/ipc/signal.rs @@ -1,13 +1,14 @@ use crate::arch::interrupt::TrapFrame; pub use crate::ipc::generic_signal::AtomicGenericSignal as AtomicSignal; pub use crate::ipc::generic_signal::GenericSigChildCode as SigChildCode; +pub use crate::ipc::generic_signal::GenericSigFlags as SigFlags; pub use crate::ipc::generic_signal::GenericSigSet as SigSet; +pub use crate::ipc::generic_signal::GenericSigStackFlags as SigStackFlags; pub use crate::ipc::generic_signal::GenericSignal as Signal; + pub use crate::ipc::generic_signal::GENERIC_MAX_SIG_NUM as MAX_SIG_NUM; pub use crate::ipc::generic_signal::GENERIC_STACK_ALIGN as STACK_ALIGN; -pub use crate::ipc::generic_signal::GenericSigFlags as SigFlags; - use crate::ipc::signal_types::SignalArch; pub struct LoongArch64SignalArch; @@ -30,7 +31,7 @@ impl SignalArch for LoongArch64SignalArch { #[derive(Debug, Clone, Copy)] pub struct LoongArch64SigStack { pub sp: usize, - pub flags: u32, + pub flags: SigStackFlags, pub size: u32, } @@ -38,10 +39,16 @@ impl LoongArch64SigStack { pub fn new() -> Self { Self { sp: 0, - flags: 0, + flags: SigStackFlags::SS_DISABLE, size: 0, } } + + /// 检查给定的栈指针 `sp` 是否在当前备用信号栈的范围内。 + #[inline] + pub fn on_sig_stack(&self, sp: usize) -> bool { + self.sp != 0 && self.size != 0 && (sp.wrapping_sub(self.sp) < self.size as usize) + } } impl Default for LoongArch64SigStack { diff --git a/kernel/src/arch/riscv64/interrupt/mod.rs b/kernel/src/arch/riscv64/interrupt/mod.rs index bc366098f..d29b88198 100644 --- a/kernel/src/arch/riscv64/interrupt/mod.rs +++ b/kernel/src/arch/riscv64/interrupt/mod.rs @@ -167,6 +167,12 @@ impl TrapFrame { pub fn set_pc(&mut self, pc: usize) { self.epc = pc; } + + /// 返回当前 TrapFrame 对应的用户态栈指针。 + #[inline(always)] + pub fn stack_pointer(&self) -> usize { + self.sp + } } impl ProbeArgs for TrapFrame { diff --git a/kernel/src/arch/riscv64/ipc/signal.rs b/kernel/src/arch/riscv64/ipc/signal.rs index cf4f37aac..9cb095563 100644 --- a/kernel/src/arch/riscv64/ipc/signal.rs +++ b/kernel/src/arch/riscv64/ipc/signal.rs @@ -1,14 +1,16 @@ pub use crate::ipc::generic_signal::AtomicGenericSignal as AtomicSignal; pub use crate::ipc::generic_signal::GenericSigChildCode as SigChildCode; pub use crate::ipc::generic_signal::GenericSigSet as SigSet; +pub use crate::ipc::generic_signal::GenericSigStackFlags as SigStackFlags; pub use crate::ipc::generic_signal::GenericSignal as Signal; + +pub use crate::ipc::generic_signal::GENERIC_MAX_SIG_NUM as MAX_SIG_NUM; + use crate::{ arch::interrupt::TrapFrame, ipc::signal_types::{SigCode, SignalArch}, }; -pub use crate::ipc::generic_signal::GENERIC_MAX_SIG_NUM as MAX_SIG_NUM; - pub struct RiscV64SignalArch; impl SignalArch for RiscV64SignalArch { @@ -46,7 +48,7 @@ bitflags! { #[derive(Debug, Clone, Copy)] pub struct RiscV64SigStack { pub sp: usize, - pub flags: u32, + pub flags: SigStackFlags, pub size: u32, } @@ -54,10 +56,16 @@ impl RiscV64SigStack { pub fn new() -> Self { Self { sp: 0, - flags: 0, + flags: SigStackFlags::SS_DISABLE, size: 0, } } + + /// 检查给定的栈指针 `sp` 是否在当前备用信号栈的范围内。 + #[inline] + pub fn on_sig_stack(&self, sp: usize) -> bool { + self.sp != 0 && self.size != 0 && (sp.wrapping_sub(self.sp) < self.size as usize) + } } impl Default for RiscV64SigStack { diff --git a/kernel/src/arch/x86_64/interrupt/mod.rs b/kernel/src/arch/x86_64/interrupt/mod.rs index 8198a0633..457c139c9 100644 --- a/kernel/src/arch/x86_64/interrupt/mod.rs +++ b/kernel/src/arch/x86_64/interrupt/mod.rs @@ -185,6 +185,12 @@ impl TrapFrame { self.rip = pc as u64; } + /// 返回当前 TrapFrame 对应的用户态栈指针。 + #[inline(always)] + pub fn stack_pointer(&self) -> usize { + self.rsp as usize + } + /// 获取系统调用号 /// /// # Safety diff --git a/kernel/src/arch/x86_64/ipc/signal.rs b/kernel/src/arch/x86_64/ipc/signal.rs index 64193642b..8b0b791e4 100644 --- a/kernel/src/arch/x86_64/ipc/signal.rs +++ b/kernel/src/arch/x86_64/ipc/signal.rs @@ -8,6 +8,7 @@ use system_error::SystemError; pub use crate::ipc::generic_signal::AtomicGenericSignal as AtomicSignal; pub use crate::ipc::generic_signal::GenericSigChildCode as SigChildCode; pub use crate::ipc::generic_signal::GenericSigSet as SigSet; +pub use crate::ipc::generic_signal::GenericSigStackFlags as SigStackFlags; pub use crate::ipc::generic_signal::GenericSignal as Signal; use crate::{ @@ -353,7 +354,7 @@ bitflags! { #[derive(Debug, Clone, Copy)] pub struct X86SigStack { pub sp: usize, - pub flags: u32, + pub flags: SigStackFlags, pub size: u32, } @@ -361,10 +362,16 @@ impl X86SigStack { pub fn new() -> Self { Self { sp: 0, - flags: 0, + flags: SigStackFlags::SS_DISABLE, size: 0, } } + + /// 检查给定的栈指针 `sp` 是否在当前备用信号栈的范围内。 + #[inline] + pub fn on_sig_stack(&self, sp: usize) -> bool { + self.sp != 0 && self.size != 0 && (sp.wrapping_sub(self.sp) < self.size as usize) + } } impl Default for X86SigStack { @@ -534,13 +541,15 @@ unsafe fn do_signal(frame: &mut TrapFrame, got_signal: &mut bool) { let res: Result = handle_signal(sig_number, &mut sigaction, &info.unwrap(), &oldset, frame); compiler_fence(Ordering::SeqCst); - if res.is_err() { - error!( - "Error occurred when handling signal: {}, pid={:?}, errcode={:?}", - sig_number as i32, - ProcessManager::current_pcb().raw_pid(), - res.as_ref().unwrap_err() - ); + if let Err(e) = res { + if e != SystemError::EFAULT { + error!( + "Error occurred when handling signal: {}, pid={:?}, errcode={:?}", + sig_number as i32, + ProcessManager::current_pcb().raw_pid(), + &e + ); + } } } @@ -706,16 +715,14 @@ fn setup_frame( return Ok(0); } SaHandlerType::Customized(handler) => { - // 如果handler位于内核空间 + // 如果handler地址大于等于用户空间末尾,说明它在内核空间,这是非法的。 if handler >= MMArch::USER_END_VADDR { - if sig == Signal::SIGSEGV { - sig.handle_default(); - return Ok(0); - } else { - error!("attempting to execute a signal handler from kernel"); - sig.handle_default(); - return Err(SystemError::EINVAL); - } + error!("attempting to execute a signal handler from kernel"); + let _ = crate::ipc::kill::kill_process( + ProcessManager::current_pcb().raw_pid(), + Signal::SIGSEGV, + ); + return Err(SystemError::EFAULT); } else { // 64位程序必须由用户自行指定restorer if sigaction.flags().contains(SigFlags::SA_RESTORER) { @@ -732,13 +739,6 @@ fn setup_frame( ); return Err(SystemError::EINVAL); } - if sigaction.restorer().is_none() { - error!( - "restorer in process:{:?} is not defined", - ProcessManager::current_pcb().raw_pid() - ); - return Err(SystemError::EINVAL); - } handler_addr = handler.data(); } } @@ -824,13 +824,16 @@ fn setup_frame( #[inline(always)] fn get_stack(sigaction: &mut Sigaction, frame: &TrapFrame, size: usize) -> *mut SigFrame { - let binding = ProcessManager::current_pcb(); - let stack = binding.sig_altstack(); + let pcb = ProcessManager::current_pcb(); + let stack = pcb.sig_altstack(); let mut rsp: usize; // 检查是否使用备用栈 - if sigaction.flags().contains(SigFlags::SA_ONSTACK) { + if sigaction.flags().contains(SigFlags::SA_ONSTACK) + && !stack.flags.contains(SigStackFlags::SS_DISABLE) + && !stack.on_sig_stack(frame.rsp as usize) + { rsp = stack.sp + stack.size as usize - size; } else { // 默认使用用户栈:rsp - 红区(128) - size @@ -838,7 +841,7 @@ fn get_stack(sigaction: &mut Sigaction, frame: &TrapFrame, size: usize) -> *mut } // 16字节对齐,减8是为了保持 x86_64 ABI 的栈对齐约定 - rsp &= (!(STACK_ALIGN - 1)) as usize - 8; + rsp = (rsp & !(STACK_ALIGN - 1) as usize) - 8; rsp as *mut SigFrame } diff --git a/kernel/src/ipc/generic_signal.rs b/kernel/src/ipc/generic_signal.rs index f8cd5cb3e..b0ee483b8 100644 --- a/kernel/src/ipc/generic_signal.rs +++ b/kernel/src/ipc/generic_signal.rs @@ -377,6 +377,16 @@ bitflags! { } } +bitflags! { + #[repr(C)] + #[derive(Default)] + pub struct GenericSigStackFlags:u32{ + const SS_ONSTACK = 1; + const SS_DISABLE = 2; + const SS_AUTODISARM = 1 << 31; + } +} + /// 信号默认处理函数——终止进程 fn sig_terminate(sig: Signal) { ProcessManager::exit(sig as usize); diff --git a/kernel/src/ipc/sighand.rs b/kernel/src/ipc/sighand.rs index 1e48f085b..ad549066d 100644 --- a/kernel/src/ipc/sighand.rs +++ b/kernel/src/ipc/sighand.rs @@ -130,6 +130,10 @@ impl SigHand { pub fn load_count(&self) -> i64 { self.inner().cnt } + + pub fn is_shared(&self) -> bool { + self.load_count() > 1 + } } impl Default for InnerSigHand { @@ -179,7 +183,8 @@ impl ProcessControlBlock { } // 清除flags中,除了DFL和IGN以外的所有标志 sigaction.set_restorer(None); - sigaction.mask_mut().remove(SigSet::all()); + *sigaction.mask_mut() = SigSet::empty(); + *sigaction.flags_mut() = SigFlags::empty(); compiler_fence(core::sync::atomic::Ordering::SeqCst); } compiler_fence(core::sync::atomic::Ordering::SeqCst); diff --git a/kernel/src/ipc/syscall/sys_sigaltstack.rs b/kernel/src/ipc/syscall/sys_sigaltstack.rs index 896e7a698..9ce5c5517 100644 --- a/kernel/src/ipc/syscall/sys_sigaltstack.rs +++ b/kernel/src/ipc/syscall/sys_sigaltstack.rs @@ -1,8 +1,8 @@ use alloc::string::ToString; use alloc::vec::Vec; -use core::ffi::{c_int, c_void}; +use core::ffi::c_void; -use crate::arch::interrupt::TrapFrame; +use crate::arch::{interrupt::TrapFrame, ipc::signal::SigStackFlags}; use crate::syscall::table::FormattedSyscallParam; use crate::syscall::table::Syscall; use crate::{arch::syscall::nr::SYS_SIGALTSTACK, process::ProcessManager}; @@ -10,23 +10,16 @@ use system_error::SystemError; use crate::syscall::user_access::{UserBufferReader, UserBufferWriter}; +// 最小信号栈大小 +const MINSIGSTKSZ: usize = 2048; + /// C 中定义的信号栈, 等于 C 中的 stack_t #[repr(C)] -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, Default)] pub struct StackUser { - pub ss_sp: *mut c_void, // 栈的基地址 - pub ss_flags: c_int, // 标志 - pub ss_size: usize, // 栈的字节数 -} - -impl StackUser { - pub fn new() -> Self { - Self { - ss_sp: core::ptr::null_mut(), - ss_flags: 0, - ss_size: 0, - } - } + pub ss_sp: *mut c_void, // 栈的基地址 + pub ss_flags: SigStackFlags, // 标志 + pub ss_size: usize, // 栈的字节数 } pub struct SysAltStackHandle; @@ -49,7 +42,7 @@ impl Syscall for SysAltStackHandle { 2 } - fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + fn handle(&self, args: &[usize], frame: &mut TrapFrame) -> Result { //warn!("SYS_SIGALTSTACK has not yet been fully realized and still needs to be supplemented"); //warn!("SYS_SIGALTSTACK has not yet been fully realized and still needs to be supplemented"); //warn!("SYS_SIGALTSTACK has not yet been fully realized and still needs to be supplemented"); @@ -57,33 +50,60 @@ impl Syscall for SysAltStackHandle { let ss = Self::ss(args); let old_ss = Self::old_ss(args); - let binding = ProcessManager::current_pcb(); - let mut stack = binding.sig_altstack_mut(); + let pcb = ProcessManager::current_pcb(); + let mut stack = pcb.sig_altstack_mut(); + let is_on_stack = stack.on_sig_stack(frame.stack_pointer()); if !old_ss.is_null() { - // 需要从 current() 中读结构体写入 old_ss - //log::info!("old_ss impl"); - let mut temp = StackUser::new(); + let mut old_stack_user = StackUser { + ss_sp: stack.sp as *mut c_void, + ss_size: stack.size as usize, + ..Default::default() + }; - temp.ss_sp = stack.sp as *mut c_void; - temp.ss_size = stack.size as usize; - // temp.ss_flags = 0; 这个要根据情况设置 + if stack.size == 0 { + old_stack_user.ss_flags = SigStackFlags::SS_DISABLE; + } else if is_on_stack { + old_stack_user.ss_flags = SigStackFlags::SS_ONSTACK; + } else { + // 栈已启用但当前不在其上 + old_stack_user.ss_flags = stack.flags; // 保留 SS_AUTODISARM 等标志 + } - let mut user_buffer = UserBufferWriter::new(old_ss, size_of::(), true)?; - user_buffer.copy_one_to_user(&temp, 0)?; + let mut writer = UserBufferWriter::new(old_ss, size_of::(), true)?; + writer.copy_one_to_user(&old_stack_user, 0)?; } if !ss.is_null() { - // 需要向 current() 中结构体写入 ss 的内容 - //log::info!("ss impl"); + if is_on_stack { + return Err(SystemError::EPERM); + } - let user_buffer = UserBufferReader::new(ss, size_of::(), true)?; - let sus: &[StackUser] = user_buffer.read_from_user(0)?; + let reader = UserBufferReader::new(ss, size_of::(), true)?; + let sus: &[StackUser] = reader.read_from_user(0)?; let ss: StackUser = sus[0]; - stack.sp = ss.ss_sp as usize; - stack.size = ss.ss_size as u32; - stack.flags = ss.ss_flags as u32; + if !ss + .ss_flags + .difference(SigStackFlags::SS_DISABLE | SigStackFlags::SS_AUTODISARM) + .is_empty() + { + return Err(SystemError::EINVAL); + } + // 如果用户请求禁用备用栈 + if ss.ss_flags.contains(SigStackFlags::SS_DISABLE) { + stack.sp = 0; + stack.flags = SigStackFlags::SS_DISABLE; + stack.size = 0; + } else { + // 如果用户请求设置一个新的栈 + if ss.ss_size < MINSIGSTKSZ { + return Err(SystemError::ENOMEM); + } + stack.sp = ss.ss_sp as usize; + stack.flags = ss.ss_flags; // 保留 SS_AUTODISARM 等标志 + stack.size = ss.ss_size as u32; + } } Ok(0) } diff --git a/kernel/src/process/execve.rs b/kernel/src/process/execve.rs index afe994cde..309dad189 100644 --- a/kernel/src/process/execve.rs +++ b/kernel/src/process/execve.rs @@ -66,6 +66,17 @@ pub fn do_execve( completion.complete_all(); } + if pcb.sighand().is_shared() { + // Linux出于进程和线程隔离,要确保在execve时,对共享的 SigHand 进行深拷贝 + // 参考 https://code.dragonos.org.cn/xref/linux-6.6.21/fs/exec.c#1187 + let new_sighand = crate::ipc::sighand::SigHand::new(); + new_sighand.copy_handlers_from(&pcb.sighand()); + pcb.replace_sighand(new_sighand); + } + // 重置所有信号处理器为默认行为(SIG_DFL),禁用并清空备用信号栈。 + pcb.flush_signal_handlers(false); + *pcb.sig_altstack_mut() = crate::arch::SigStackArch::new(); + Syscall::arch_do_execve(regs, ¶m, &load_result, user_sp, argv_ptr) } diff --git a/kernel/src/process/mod.rs b/kernel/src/process/mod.rs index 7fc28902f..53d128ea6 100644 --- a/kernel/src/process/mod.rs +++ b/kernel/src/process/mod.rs @@ -4,7 +4,7 @@ use core::{ hint::spin_loop, intrinsics::unlikely, mem::ManuallyDrop, - sync::atomic::{compiler_fence, fence, AtomicBool, AtomicUsize, Ordering}, + sync::atomic::{compiler_fence, fence, AtomicBool, AtomicU64, AtomicUsize, Ordering}, }; use alloc::{ @@ -729,6 +729,35 @@ impl ProcessFlags { r } } + +// TODO 完善相关的方法 +#[derive(Debug, Default)] +pub struct ProcessCpuTime { + pub utime: AtomicU64, + pub stime: AtomicU64, + pub sum_exec_runtime: AtomicU64, +} + +#[derive(Debug, Default)] +pub struct CpuItimer { + pub value: u64, // 剩余时间 ns + pub interval: u64, // 间隔时间 ns + pub is_active: bool, +} + +#[derive(Debug, Clone)] +pub struct ProcessItimer { + pub timer: Arc, + pub config: crate::time::syscall::Itimerval, +} + +#[derive(Debug, Default)] +pub struct ProcessItimers { + pub real: Option, // 用于 ITIMER_REAL + pub virt: CpuItimer, // 用于 ITIMER_REAL + pub prof: CpuItimer, // 用于 ITIMER_PROF +} + #[derive(Debug)] pub struct ProcessControlBlock { /// 当前进程的pid @@ -787,6 +816,10 @@ pub struct ProcessControlBlock { ///闹钟定时器 alarm_timer: SpinLock>, + itimers: SpinLock, + + /// CPU时间片 + cpu_time: Arc, /// 进程的robust lock列表 robust_list: RwLock>, @@ -915,6 +948,8 @@ impl ProcessControlBlock { thread: RwLock::new(ThreadInfo::new()), fs: RwLock::new(Arc::new(FsStruct::new())), alarm_timer: SpinLock::new(None), + itimers: SpinLock::new(ProcessItimers::default()), + cpu_time: Arc::new(ProcessCpuTime::default()), robust_list: RwLock::new(None), cred: SpinLock::new(cred), self_ref: weak.clone(), @@ -1423,10 +1458,41 @@ impl ProcessControlBlock { *self.robust_list.write_irqsave() = new_robust_list; } + #[inline(always)] pub fn alarm_timer_irqsave(&self) -> SpinLockGuard<'_, Option> { return self.alarm_timer.lock_irqsave(); } + #[inline(always)] + pub fn itimers_irqsave(&self) -> SpinLockGuard<'_, ProcessItimers> { + return self.itimers.lock_irqsave(); + } + + #[inline(always)] + pub fn cputime(&self) -> Arc { + return self.cpu_time.clone(); + } + #[inline(always)] + pub fn account_utime(&self, ns: u64) { + if ns == 0 { + return; + } + self.cpu_time.utime.fetch_add(ns, Ordering::Relaxed); + } + #[inline(always)] + pub fn account_stime(&self, ns: u64) { + if ns == 0 { + return; + } + self.cpu_time.stime.fetch_add(ns, Ordering::Relaxed); + } + #[inline(always)] + pub fn add_sum_exec_runtime(&self, ns: u64) { + self.cpu_time + .sum_exec_runtime + .fetch_add(ns, Ordering::Relaxed); + } + /// Exit fd table when process exit fn exit_files(&self) { // 关闭文件描述符表 diff --git a/kernel/src/process/namespace/unshare.rs b/kernel/src/process/namespace/unshare.rs index aba0b6951..5e0c4fb17 100644 --- a/kernel/src/process/namespace/unshare.rs +++ b/kernel/src/process/namespace/unshare.rs @@ -88,11 +88,10 @@ fn check_unshare_flags(flags: CloneFlags) -> Result<(), SystemError> { // 如果请求 unshare CLONE_SIGHAND 或 CLONE_VM, // 必须确保信号处理结构的引用计数为1 - if flags.intersects(CloneFlags::CLONE_SIGHAND | CloneFlags::CLONE_VM) { - let sighand_count = current_pcb.sighand().load_count(); - if sighand_count > 1 { - return Err(SystemError::EINVAL); - } + if flags.intersects(CloneFlags::CLONE_SIGHAND | CloneFlags::CLONE_VM) + && current_pcb.sighand().is_shared() + { + return Err(SystemError::EINVAL); } // TODO: 如果请求 unshare CLONE_VM, diff --git a/kernel/src/sched/cputime.rs b/kernel/src/sched/cputime.rs index c372238cf..f8bec7fcc 100644 --- a/kernel/src/sched/cputime.rs +++ b/kernel/src/sched/cputime.rs @@ -1,8 +1,9 @@ use core::sync::atomic::{compiler_fence, AtomicUsize, Ordering}; use crate::{ - arch::CurrentIrqArch, + arch::{ipc::signal::Signal, CurrentIrqArch}, exception::InterruptArch, + ipc::kill::kill_process_by_pcb, process::ProcessControlBlock, smp::{core::smp_get_processor_id, cpu::ProcessorId}, time::jiffies::TICK_NESC, @@ -75,8 +76,8 @@ impl IrqTime { pub struct CpuTimeFunc; impl CpuTimeFunc { pub fn irqtime_account_process_tick( - _pcb: &Arc, - _user_tick: bool, + pcb: &Arc, + user_tick: bool, ticks: u64, ) { let cputime = TICK_NESC as u64 * ticks; @@ -87,7 +88,48 @@ impl CpuTimeFunc { return; } - // TODO: update process time + if user_tick { + pcb.account_utime(cputime); + } else { + pcb.account_stime(cputime); + } + pcb.add_sum_exec_runtime(cputime); + + let cputime_ns = TICK_NESC as u64 * ticks; + let accounted_cputime = cputime_ns - other; + // 检查并处理CPU时间定时器 + let mut itimers = pcb.itimers_irqsave(); + // 处理 ITIMER_VIRTUAL (仅在用户态tick时消耗时间) + if user_tick && itimers.virt.is_active { + if itimers.virt.value <= accounted_cputime { + kill_process_by_pcb(pcb.clone(), Signal::SIGVTALRM).ok(); + if itimers.virt.interval > 0 { + // 周期性定时器:在旧的剩余时间上增加间隔时间 + itimers.virt.value += itimers.virt.interval; + } else { + // 一次性定时器:禁用 + itimers.virt.is_active = false; + itimers.virt.value = 0; + } + } else { + itimers.virt.value -= accounted_cputime; + } + } + + // 处理 ITIMER_PROF (在用户态和内核态tick时都消耗时间) + if itimers.prof.is_active { + if itimers.prof.value <= accounted_cputime { + kill_process_by_pcb(pcb.clone(), Signal::SIGPROF).ok(); + if itimers.prof.interval > 0 { + itimers.prof.value += itimers.prof.interval; + } else { + itimers.prof.is_active = false; + itimers.prof.value = 0; + } + } else { + itimers.prof.value -= accounted_cputime; + } + } } pub fn account_other_time(max: u64) -> u64 { diff --git a/kernel/src/time/syscall/mod.rs b/kernel/src/time/syscall/mod.rs index 870eeee70..b66ad0f9f 100644 --- a/kernel/src/time/syscall/mod.rs +++ b/kernel/src/time/syscall/mod.rs @@ -8,8 +8,10 @@ use crate::syscall::Syscall; mod sys_alarm; mod sys_clock_gettime; mod sys_clock_nanosleep; +mod sys_getitimer; mod sys_gettimeofday; mod sys_nanosleep; +mod sys_setitimer; pub type PosixTimeT = c_longlong; pub type PosixSusecondsT = c_int; @@ -21,6 +23,53 @@ pub struct PosixTimeval { pub tv_usec: PosixSusecondsT, } +impl PosixTimeval { + /// 从内核统一使用的 u64 纳秒创建一个 PosixTimeval 实例 + pub fn from_ns(ns: u64) -> Self { + Self { + tv_sec: (ns / 1_000_000_000) as PosixTimeT, + tv_usec: ((ns % 1_000_000_000) / 1000) as PosixSusecondsT, + } + } + + /// 将当前的 PosixTimeval 精确转换为内核统一使用的 u64 纳秒 + pub fn to_ns(self) -> u64 { + if self.tv_usec < 0 || self.tv_usec >= 1_000_000 as PosixSusecondsT { + (self.tv_sec as u64).saturating_mul(1_000_000_000) + } else { + let sec_ns = (self.tv_sec as u64).saturating_mul(1_000_000_000); + let usec_ns = (self.tv_usec as u64).saturating_mul(1000); + sec_ns.saturating_add(usec_ns) + } + } +} + +#[repr(C)] +#[derive(Default, Debug, Copy, Clone)] +pub struct Itimerval { + pub it_interval: PosixTimeval, + pub it_value: PosixTimeval, +} + +#[repr(C)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, FromPrimitive)] +pub enum ItimerType { + /// 真实时间定时器,基于时钟时间。触发 SIGALRM + Real = 0, + /// 虚拟时间定时器,仅计算进程在用户态下的CPU时间。触发 SIGVTALRM + Virtual = 1, + /// 性能分析定时器,计算进程在用户态和内核态下的总CPU时间。触发 SIGPROF + Prof = 2, +} + +impl TryFrom for ItimerType { + type Error = SystemError; + + fn try_from(value: i32) -> Result { + ::from_i32(value).ok_or(SystemError::EINVAL) + } +} + #[repr(C)] #[derive(Default, Debug, Copy, Clone)] /// 当前时区信息 diff --git a/kernel/src/time/syscall/sys_getitimer.rs b/kernel/src/time/syscall/sys_getitimer.rs new file mode 100644 index 000000000..7512d66e8 --- /dev/null +++ b/kernel/src/time/syscall/sys_getitimer.rs @@ -0,0 +1,94 @@ +use crate::{ + arch::{interrupt::TrapFrame, syscall::nr::SYS_GETITIMER}, + process::ProcessManager, + syscall::{ + table::{FormattedSyscallParam, Syscall}, + user_access::UserBufferWriter, + }, + time::{ + syscall::{ItimerType, Itimerval, PosixSusecondsT, PosixTimeT, PosixTimeval}, + timer::{self, Jiffies}, + }, +}; +use alloc::vec::Vec; +use core::mem::size_of; +use system_error::SystemError; + +pub struct SysGetitimerHandle; + +impl SysGetitimerHandle { + fn which(args: &[usize]) -> Result { + ItimerType::try_from(args[0] as i32) + } + + fn curr_value_ptr(args: &[usize]) -> *mut Itimerval { + args[1] as *mut Itimerval + } +} + +impl Syscall for SysGetitimerHandle { + fn num_args(&self) -> usize { + 2 + } + + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let which = Self::which(args)?; + let curr_value_ptr = Self::curr_value_ptr(args); + + let pcb = ProcessManager::current_pcb(); + let itimers = pcb.itimers_irqsave(); + let mut itv = Itimerval::default(); + + match which { + ItimerType::Real => { + // 读取真实时间定时器 + if let Some(current_itimer) = itimers.real.as_ref() { + itv.it_interval = current_itimer.config.it_interval; + let now = timer::clock(); + let expires = current_itimer.timer.inner().expire_jiffies; + + if expires > now { + let remaining_jiffies = Jiffies::new(expires - now); + let remaining_duration = core::time::Duration::from(remaining_jiffies); + itv.it_value.tv_sec = remaining_duration.as_secs() as PosixTimeT; + itv.it_value.tv_usec = + remaining_duration.subsec_micros() as PosixSusecondsT; + } + } + } + ItimerType::Virtual => { + if itimers.virt.is_active { + itv.it_value = PosixTimeval::from_ns(itimers.virt.value); + itv.it_interval = PosixTimeval::from_ns(itimers.virt.interval); + } + } + ItimerType::Prof => { + if itimers.prof.is_active { + itv.it_value = PosixTimeval::from_ns(itimers.prof.value); + itv.it_interval = PosixTimeval::from_ns(itimers.prof.interval); + } + } + } + + if !curr_value_ptr.is_null() { + let mut writer = UserBufferWriter::new(curr_value_ptr, size_of::(), true)?; + writer.copy_one_to_user(&itv, 0)?; + } + + Ok(0) + } + + fn entry_format(&self, args: &[usize]) -> Vec { + let which_str = match ItimerType::try_from(args[0] as i32) { + Ok(v) => format!("{:?}", v), + Err(_) => format!("Invalid({})", args[0]), + }; + vec![ + FormattedSyscallParam::new("which", which_str), + FormattedSyscallParam::new("value", format!("{:#x}", args[1])), + ] + } +} + +// 注册系统调用 +syscall_table_macros::declare_syscall!(SYS_GETITIMER, SysGetitimerHandle); diff --git a/kernel/src/time/syscall/sys_setitimer.rs b/kernel/src/time/syscall/sys_setitimer.rs new file mode 100644 index 000000000..c09010233 --- /dev/null +++ b/kernel/src/time/syscall/sys_setitimer.rs @@ -0,0 +1,250 @@ +use crate::{ + arch::{interrupt::TrapFrame, ipc::signal::Signal, syscall::nr::SYS_SETITIMER}, + ipc::kill::kill_process, + process::{ProcessControlBlock, ProcessItimers, ProcessManager}, + syscall::{ + table::{FormattedSyscallParam, Syscall}, + user_access::{UserBufferReader, UserBufferWriter}, + }, + time::{ + syscall::{ItimerType, Itimerval, PosixTimeval}, + timer::{self, Jiffies, Timer, TimerFunction}, + }, +}; +use alloc::{ + boxed::Box, + sync::{Arc, Weak}, + vec::Vec, +}; +use core::{mem::size_of, time::Duration}; +use system_error::SystemError; + +impl ItimerType { + /// 根据定时器类型,从内部状态获取当前的 Itimerval 值。 + fn get_current_value(&self, itimers: &ProcessItimers) -> Itimerval { + match self { + ItimerType::Real => { + let mut old_itv = Itimerval::default(); + if let Some(current_itimer) = itimers.real.as_ref() { + old_itv.it_interval = current_itimer.config.it_interval; + let now = timer::clock(); + let expires = current_itimer.timer.inner().expire_jiffies; + if expires > now { + let remaining_jiffies = Jiffies::new(expires - now); + let remaining_duration = Duration::from(remaining_jiffies); + old_itv.it_value.tv_sec = remaining_duration.as_secs() as i64; + old_itv.it_value.tv_usec = remaining_duration.subsec_micros() as i32; + } + } + old_itv + } + ItimerType::Virtual | ItimerType::Prof => { + let mut old_itv = Itimerval::default(); + let cpu_timer_slot = if *self == ItimerType::Virtual { + &itimers.virt + } else { + &itimers.prof + }; + + if cpu_timer_slot.is_active { + old_itv.it_value = PosixTimeval::from_ns(cpu_timer_slot.value); + old_itv.it_interval = PosixTimeval::from_ns(cpu_timer_slot.interval); + } + old_itv + } + } + } + + /// 根据定时器类型,使用新的配置来更新内部状态。 + fn set_new_value( + &self, + pcb: Arc, + itimers: &mut ProcessItimers, + new_config: Itimerval, + ) { + match self { + ItimerType::Real => { + // 先取消旧的真实时间定时器 + if let Some(old_itimer) = itimers.real.take() { + old_itimer.timer.cancel(); + } + // 如果 it_value 非零,创建并激活新的真实时间定时器 + if new_config.it_value.tv_sec > 0 || new_config.it_value.tv_usec > 0 { + let value_duration = Duration::new( + new_config.it_value.tv_sec as u64, + new_config.it_value.tv_usec as u32 * 1000, + ); + let expire_jiffies = + timer::clock() + >::from(value_duration).data(); + let helper = ItimerHelper::new(pcb, ItimerType::Real, new_config.it_interval); + let new_timer = Timer::new(helper, expire_jiffies); + new_timer.activate(); + + // 将新的定时器放回 itimers + itimers.real = Some(crate::process::ProcessItimer { + timer: new_timer, + config: new_config, + }); + } + } + ItimerType::Virtual | ItimerType::Prof => { + let cpu_timer_slot = if *self == ItimerType::Virtual { + &mut itimers.virt + } else { + &mut itimers.prof + }; + + let value_ns = new_config.it_value.to_ns(); + if value_ns > 0 { + // 激活或重置定时器 + cpu_timer_slot.value = value_ns; + cpu_timer_slot.interval = new_config.it_interval.to_ns(); + cpu_timer_slot.is_active = true; + } else { + // value 为 0,表示取消定时器 + cpu_timer_slot.is_active = false; + } + } + } + } +} + +#[derive(Debug)] +struct ItimerHelper { + target_pcb: Weak, + which: ItimerType, + interval: PosixTimeval, +} + +impl ItimerHelper { + fn new( + target_pcb: Arc, + which: ItimerType, + interval: PosixTimeval, + ) -> Box { + Box::new(Self { + target_pcb: Arc::downgrade(&target_pcb), + which, + interval, + }) + } +} + +impl TimerFunction for ItimerHelper { + fn run(&mut self) -> Result<(), SystemError> { + let pcb = match self.target_pcb.upgrade() { + Some(pcb) => pcb, + None => return Ok(()), // 进程已退出 + }; + + // 根据Linux行为,ITIMER_REAL (SIGALRM) 优先发送给线程组的leader。 + let thread_group_leader = pcb.threads_read_irqsave().group_leader(); + if let Some(leader) = thread_group_leader { + let _ = kill_process(leader.raw_pid(), Signal::SIGALRM); + } else { + let _ = kill_process(pcb.raw_pid(), Signal::SIGALRM); + } + + // 周期性定时器,则重新启动定时器 + if self.interval.tv_sec > 0 || self.interval.tv_usec > 0 { + let interval_duration = Duration::new( + self.interval.tv_sec as u64, + self.interval.tv_usec as u32 * 1000, + ); + let expire_jiffies = + timer::clock() + >::from(interval_duration).data(); + + let next_helper = ItimerHelper::new(pcb.clone(), self.which, self.interval); + let next_timer = Timer::new(next_helper, expire_jiffies); + next_timer.activate(); + + let mut itimers = pcb.itimers_irqsave(); + let new_itimer = crate::process::ProcessItimer { + timer: next_timer, + config: Itimerval { + it_interval: self.interval, + it_value: self.interval, // 下一次的值就是间隔 + }, + }; + itimers.real = Some(new_itimer); + } else { + // 一次性定时器,从 PCB 中清除 + let mut itimers = pcb.itimers_irqsave(); + itimers.real = None; + } + Ok(()) + } +} + +fn handle_itimer( + pcb: Arc, + which: ItimerType, + new_value_ptr: *const Itimerval, + old_value_ptr: *mut Itimerval, +) -> Result { + let mut itimers = pcb.itimers_irqsave(); + + // old_value: 获取旧值并写入用户空间 + if !old_value_ptr.is_null() { + let old_itv = which.get_current_value(&itimers); + + let mut writer = UserBufferWriter::new(old_value_ptr, size_of::(), true)?; + writer.copy_one_to_user(&old_itv, 0)?; + } + + // new_value: 从用户空间读取新值并设置 + if !new_value_ptr.is_null() { + let mut new_config = Itimerval::default(); + let reader = UserBufferReader::new(new_value_ptr, size_of::(), true)?; + reader.copy_one_from_user(&mut new_config, 0)?; + + which.set_new_value(pcb.clone(), &mut itimers, new_config); + } + Ok(0) +} + +pub struct SysSetitimerHandle; + +impl SysSetitimerHandle { + fn which(args: &[usize]) -> Result { + ItimerType::try_from(args[0] as i32) + } + + fn new_value_ptr(args: &[usize]) -> *const Itimerval { + args[1] as *const Itimerval + } + + fn old_value_ptr(args: &[usize]) -> *mut Itimerval { + args[2] as *mut Itimerval + } +} + +impl Syscall for SysSetitimerHandle { + fn num_args(&self) -> usize { + 3 + } + + fn handle(&self, args: &[usize], _frame: &mut TrapFrame) -> Result { + let which = Self::which(args)?; + let new_value_ptr = Self::new_value_ptr(args); + let old_value_ptr = Self::old_value_ptr(args); + + let pcb = ProcessManager::current_pcb(); + handle_itimer(pcb, which, new_value_ptr, old_value_ptr) + } + + fn entry_format(&self, args: &[usize]) -> Vec { + let which_str = match ItimerType::try_from(args[0] as i32) { + Ok(which) => format!("{:?}", which), + Err(_) => format!("Invalid({})", args[0]), + }; + vec![ + FormattedSyscallParam::new("which", which_str), + FormattedSyscallParam::new("new_value", format!("{:#x}", args[1])), + FormattedSyscallParam::new("old_value", format!("{:#x}", args[2])), + ] + } +} + +// 注册系统调用 +syscall_table_macros::declare_syscall!(SYS_SETITIMER, SysSetitimerHandle); diff --git a/user/apps/tests/syscall/gvisor/blocklists/itimer_test b/user/apps/tests/syscall/gvisor/blocklists/itimer_test new file mode 100644 index 000000000..232594e7b --- /dev/null +++ b/user/apps/tests/syscall/gvisor/blocklists/itimer_test @@ -0,0 +1,5 @@ +# +ItimerTest.DeliversSIGALRMToMainThread +# 多线程信号公平性未实现 +ItimerTest.DeliversSIGPROFToThreadsRoughlyFairlyActive +ItimerTest.DeliversSIGPROFToThreadsRoughlyFairlyIdle diff --git a/user/apps/tests/syscall/gvisor/blocklists/sigaltstack_test b/user/apps/tests/syscall/gvisor/blocklists/sigaltstack_test new file mode 100644 index 000000000..0c80ab9b3 --- /dev/null +++ b/user/apps/tests/syscall/gvisor/blocklists/sigaltstack_test @@ -0,0 +1,4 @@ +# Linux 上也跑不通这个测例 +SigaltstackTest.ResetByExecve +# 还在修复中 +SigaltstackTest.WalksOffBottom diff --git a/user/apps/tests/syscall/gvisor/blocklists/sigreturn_test b/user/apps/tests/syscall/gvisor/blocklists/sigreturn_test new file mode 100644 index 000000000..89bd7355d --- /dev/null +++ b/user/apps/tests/syscall/gvisor/blocklists/sigreturn_test @@ -0,0 +1,2 @@ +# 还在修复中 +SigIretTest.CheckRcxR11 diff --git a/user/apps/tests/syscall/gvisor/blocklists/write_test b/user/apps/tests/syscall/gvisor/blocklists/write_test index 87838e146..29d9762b6 100644 --- a/user/apps/tests/syscall/gvisor/blocklists/write_test +++ b/user/apps/tests/syscall/gvisor/blocklists/write_test @@ -10,4 +10,4 @@ WriteTest.PartialWriteSIGSEGV # Line: 675, Column: 24 # Message: # no cache_page in PageFaultMessage -WriteTest.PartialWriteSIGBUS \ No newline at end of file +WriteTest.PartialWriteSIGBUS diff --git a/user/apps/tests/syscall/gvisor/whitelist.txt b/user/apps/tests/syscall/gvisor/whitelist.txt index f01b722f2..10ed562a9 100644 --- a/user/apps/tests/syscall/gvisor/whitelist.txt +++ b/user/apps/tests/syscall/gvisor/whitelist.txt @@ -51,3 +51,8 @@ madvise_test #signal_test sigaction_test sigprocmask_test +sigaltstack_test +sigreturn_test + +# 其他测试 +itimer_test