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:
parent
fe7cf2ae00
commit
ffc628df53
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
// 关闭文件描述符表
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
/// 当前时区信息
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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);
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
#
|
||||
ItimerTest.DeliversSIGALRMToMainThread
|
||||
# 多线程信号公平性未实现
|
||||
ItimerTest.DeliversSIGPROFToThreadsRoughlyFairlyActive
|
||||
ItimerTest.DeliversSIGPROFToThreadsRoughlyFairlyIdle
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
# Linux 上也跑不通这个测例
|
||||
SigaltstackTest.ResetByExecve
|
||||
# 还在修复中
|
||||
SigaltstackTest.WalksOffBottom
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
# 还在修复中
|
||||
SigIretTest.CheckRcxR11
|
||||
|
|
@ -10,4 +10,4 @@ WriteTest.PartialWriteSIGSEGV
|
|||
# Line: 675, Column: 24
|
||||
# Message:
|
||||
# no cache_page in PageFaultMessage
|
||||
WriteTest.PartialWriteSIGBUS
|
||||
WriteTest.PartialWriteSIGBUS
|
||||
|
|
|
|||
|
|
@ -51,3 +51,8 @@ madvise_test
|
|||
#signal_test
|
||||
sigaction_test
|
||||
sigprocmask_test
|
||||
sigaltstack_test
|
||||
sigreturn_test
|
||||
|
||||
# 其他测试
|
||||
itimer_test
|
||||
|
|
|
|||
Loading…
Reference in New Issue