diff --git a/kernel/src/arch/x86_64/asm/entry.S b/kernel/src/arch/x86_64/asm/entry.S index 8df6566cf..9c2c5732c 100644 --- a/kernel/src/arch/x86_64/asm/entry.S +++ b/kernel/src/arch/x86_64/asm/entry.S @@ -407,6 +407,11 @@ ENTRY(syscall_64) popq %rax addq $0x10, %rsp // 弹出变量FUNC和errcode + cmpq (%rsp), %rcx + jne .L_syscall_must_use_iret + cmpq 0x10(%rsp), %r11 + jne .L_syscall_must_use_iret + popq %rcx // pop rip到rcx addq $0x8, %rsp // 弹出cs @@ -415,3 +420,9 @@ ENTRY(syscall_64) swapgs sysretq + +// 适用于 sigreturn, ptrace, 或任何修改了上下文的情况 +// 此时栈结构完美符合 iretq 要求: [RIP, CS, RFLAGS, RSP, SS] +.L_syscall_must_use_iret: + swapgs + iretq diff --git a/kernel/src/ipc/syscall/sys_rt_sigtimedwait.rs b/kernel/src/ipc/syscall/sys_rt_sigtimedwait.rs index 818bd3909..0ac548c41 100644 --- a/kernel/src/ipc/syscall/sys_rt_sigtimedwait.rs +++ b/kernel/src/ipc/syscall/sys_rt_sigtimedwait.rs @@ -58,19 +58,12 @@ pub fn do_kernel_rt_sigtimedwait( let reader = UserBufferReader::new(uthese, size_of::(), from_user)?; let sigset = reader.read_one_from_user::(0)?; // 移除不可屏蔽的信号(SIGKILL 和 SIGSTOP) - let sigset_val: SigSet = SigSet::from_bits(sigset.bits()).ok_or(SystemError::EINVAL)?; - let kill_stop_mask: SigSet = - SigSet::from_bits_truncate((Signal::SIGKILL as u64) | (Signal::SIGSTOP as u64)); - let result = sigset_val & !kill_stop_mask; - - result + let mut sigset_val = SigSet::from_bits(sigset.bits()).ok_or(SystemError::EINVAL)?; + sigset_val.remove(SigSet::from(Signal::SIGKILL)); + sigset_val.remove(SigSet::from(Signal::SIGSTOP)); + sigset_val }; - // 如果信号集合为空,直接返回 EINVAL(根据 POSIX 标准) - if these.is_empty() { - return Err(SystemError::EINVAL); - } - // 构造等待/屏蔽语义:与Linux一致 // - 等待集合 these // - 临时屏蔽集合 = 旧blocked ∪ these(将这些信号作为masked的常规语义,但仍由本系统调用专门消费) @@ -134,13 +127,21 @@ pub fn do_kernel_rt_sigtimedwait( } } - // 第四步:释放中断,然后真正进入调度睡眠(窗口期内,线程保持可中断阻塞,发送侧会唤醒) + // 第四步:检查是否有其他未屏蔽的待处理信号打断,若被其他信号唤醒了,必须返回 EINTR 让内核去处理那个信号 + pcb.recalc_sigpending(None); + if pcb.has_pending_signal_fast() { + drop(preempt_guard); + restore_saved_sigmask(); + return Err(SystemError::EINTR); + } + // 第五步:释放中断,然后真正进入调度睡眠(窗口期内,线程保持可中断阻塞,发送侧会唤醒) // 计算剩余等待时间 let remaining_time = if let Some(deadline) = deadline { let now = PosixTimeSpec::now(); let remaining = deadline.total_nanos() - now.total_nanos(); if remaining <= 0 { + drop(preempt_guard); restore_saved_sigmask(); return Err(SystemError::EAGAIN_OR_EWOULDBLOCK); } diff --git a/kernel/src/sched/cputime.rs b/kernel/src/sched/cputime.rs index f8bec7fcc..0339b499f 100644 --- a/kernel/src/sched/cputime.rs +++ b/kernel/src/sched/cputime.rs @@ -88,15 +88,15 @@ impl CpuTimeFunc { return; } - if user_tick { - pcb.account_utime(cputime); - } else { - pcb.account_stime(cputime); - } - pcb.add_sum_exec_runtime(cputime); + let accounted_cputime = cputime - other; + + if user_tick { + pcb.account_utime(accounted_cputime); + } else { + pcb.account_stime(accounted_cputime); + } + pcb.add_sum_exec_runtime(accounted_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时消耗时间) diff --git a/user/apps/tests/syscall/gvisor/blocklists/sigreturn_test b/user/apps/tests/syscall/gvisor/blocklists/sigreturn_test deleted file mode 100644 index 89bd7355d..000000000 --- a/user/apps/tests/syscall/gvisor/blocklists/sigreturn_test +++ /dev/null @@ -1,2 +0,0 @@ -# 还在修复中 -SigIretTest.CheckRcxR11 diff --git a/user/apps/tests/syscall/gvisor/blocklists/sigtimedwait_test b/user/apps/tests/syscall/gvisor/blocklists/sigtimedwait_test new file mode 100644 index 000000000..d46c39df5 --- /dev/null +++ b/user/apps/tests/syscall/gvisor/blocklists/sigtimedwait_test @@ -0,0 +1,3 @@ +# getpid() 好像有点问题,还在修 +SigtimedwaitTest.IgnoredUnmaskedSignal +SigtimedwaitTest.IgnoredMaskedSignal diff --git a/user/apps/tests/syscall/gvisor/whitelist.txt b/user/apps/tests/syscall/gvisor/whitelist.txt index bd5bca749..69760d340 100644 --- a/user/apps/tests/syscall/gvisor/whitelist.txt +++ b/user/apps/tests/syscall/gvisor/whitelist.txt @@ -57,6 +57,7 @@ sigaction_test sigprocmask_test sigaltstack_test sigreturn_test +sigtimedwait_test # 其他测试 itimer_test