feat setitimer/getitimer and fix signal stack logic (#1377)

* 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 <longjin@DragonOS.org>

---------

Signed-off-by: aLinChe <1129332011@qq.com>
Signed-off-by: longjin <longjin@DragonOS.org>
Co-authored-by: longjin <longjin@DragonOS.org>
This commit is contained in:
aLinChe 2025-11-19 00:33:56 +08:00 committed by GitHub
parent fe7cf2ae00
commit ffc628df53
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 681 additions and 83 deletions

View File

@ -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::<Self>::zeroed();

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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

View File

@ -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<i32, SystemError> =
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
}

View File

@ -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);

View File

@ -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);

View File

@ -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<usize, SystemError> {
fn handle(&self, args: &[usize], frame: &mut TrapFrame) -> Result<usize, SystemError> {
//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::<StackUser>(), true)?;
user_buffer.copy_one_to_user(&temp, 0)?;
let mut writer = UserBufferWriter::new(old_ss, size_of::<StackUser>(), 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::<StackUser>(), true)?;
let sus: &[StackUser] = user_buffer.read_from_user(0)?;
let reader = UserBufferReader::new(ss, size_of::<StackUser>(), 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)
}

View File

@ -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, &param, &load_result, user_sp, argv_ptr)
}

View File

@ -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<crate::time::timer::Timer>,
pub config: crate::time::syscall::Itimerval,
}
#[derive(Debug, Default)]
pub struct ProcessItimers {
pub real: Option<ProcessItimer>, // 用于 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<Option<AlarmTimer>>,
itimers: SpinLock<ProcessItimers>,
/// CPU时间片
cpu_time: Arc<ProcessCpuTime>,
/// 进程的robust lock列表
robust_list: RwLock<Option<RobustListHead>>,
@ -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<AlarmTimer>> {
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<ProcessCpuTime> {
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) {
// 关闭文件描述符表

View File

@ -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

View File

@ -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<ProcessControlBlock>,
_user_tick: bool,
pcb: &Arc<ProcessControlBlock>,
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 {

View File

@ -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<i32> for ItimerType {
type Error = SystemError;
fn try_from(value: i32) -> Result<Self, Self::Error> {
<Self as num_traits::FromPrimitive>::from_i32(value).ok_or(SystemError::EINVAL)
}
}
#[repr(C)]
#[derive(Default, Debug, Copy, Clone)]
/// 当前时区信息

View File

@ -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, SystemError> {
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<usize, SystemError> {
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::<Itimerval>(), true)?;
writer.copy_one_to_user(&itv, 0)?;
}
Ok(0)
}
fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
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);

View File

@ -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<ProcessControlBlock>,
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() + <Jiffies as From<Duration>>::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<ProcessControlBlock>,
which: ItimerType,
interval: PosixTimeval,
}
impl ItimerHelper {
fn new(
target_pcb: Arc<ProcessControlBlock>,
which: ItimerType,
interval: PosixTimeval,
) -> Box<Self> {
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() + <Jiffies as From<Duration>>::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<ProcessControlBlock>,
which: ItimerType,
new_value_ptr: *const Itimerval,
old_value_ptr: *mut Itimerval,
) -> Result<usize, SystemError> {
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::<Itimerval>(), 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::<Itimerval>(), 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, SystemError> {
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<usize, SystemError> {
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<FormattedSyscallParam> {
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);

View File

@ -0,0 +1,5 @@
#
ItimerTest.DeliversSIGALRMToMainThread
# 多线程信号公平性未实现
ItimerTest.DeliversSIGPROFToThreadsRoughlyFairlyActive
ItimerTest.DeliversSIGPROFToThreadsRoughlyFairlyIdle

View File

@ -0,0 +1,4 @@
# Linux 上也跑不通这个测例
SigaltstackTest.ResetByExecve
# 还在修复中
SigaltstackTest.WalksOffBottom

View File

@ -0,0 +1,2 @@
# 还在修复中
SigIretTest.CheckRcxR11

View File

@ -10,4 +10,4 @@ WriteTest.PartialWriteSIGSEGV
# Line: 675, Column: 24
# Message:
# no cache_page in PageFaultMessage
WriteTest.PartialWriteSIGBUS
WriteTest.PartialWriteSIGBUS

View File

@ -51,3 +51,8 @@ madvise_test
#signal_test
sigaction_test
sigprocmask_test
sigaltstack_test
sigreturn_test
# 其他测试
itimer_test