Make syscall restart mechanism work across all architectures

This commit is contained in:
Zejun Zhao 2025-09-26 13:28:12 +08:00 committed by Ruihan Li
parent 4c26a7a7c5
commit 6a42bb3b4a
6 changed files with 8 additions and 23 deletions

View File

@ -17,10 +17,6 @@ impl LinuxAbi for UserContext {
self.a7()
}
fn set_syscall_num(&mut self, num: usize) {
self.set_a7(num);
}
fn syscall_ret(&self) -> usize {
self.a0()
}

View File

@ -17,10 +17,6 @@ impl LinuxAbi for UserContext {
self.a7()
}
fn set_syscall_num(&mut self, num: usize) {
self.set_a7(num);
}
fn syscall_ret(&self) -> usize {
self.a0()
}

View File

@ -29,10 +29,6 @@ impl LinuxAbi for UserContext {
self.rax()
}
fn set_syscall_num(&mut self, num: usize) {
self.set_rax(num);
}
fn set_syscall_ret(&mut self, ret: usize) {
self.set_rax(ret);
}

View File

@ -8,9 +8,6 @@ pub trait LinuxAbi {
/// Gets the return value of the system call.
fn syscall_ret(&self) -> usize;
/// Sets the system call number.
fn set_syscall_num(&mut self, num: usize);
/// Sets the return value of the system call.
fn set_syscall_ret(&mut self, ret: usize);

View File

@ -49,14 +49,14 @@ pub trait SignalContext {
pub fn handle_pending_signal(
user_ctx: &mut UserContext,
ctx: &Context,
syscall_number: Option<usize>,
pre_syscall_ret: Option<usize>,
) {
let syscall_restart = if let Some(syscall_number) = syscall_number
let syscall_restart = if let Some(pre_syscall_ret) = pre_syscall_ret
&& user_ctx.syscall_ret() == -(Errno::ERESTARTSYS as i32) as usize
{
// We should never return `ERESTARTSYS` to the userspace.
user_ctx.set_syscall_ret(-(Errno::EINTR as i32) as usize);
Some(syscall_number)
Some(pre_syscall_ret)
} else {
None
};
@ -90,7 +90,7 @@ pub fn handle_pending_signal(
restorer_addr,
mask,
} => {
if let Some(syscall_number) = syscall_restart
if let Some(pre_syscall_ret) = syscall_restart
&& flags.contains(SigActionFlags::SA_RESTART)
{
#[cfg(target_arch = "x86_64")]
@ -100,7 +100,7 @@ pub fn handle_pending_signal(
#[cfg(target_arch = "loongarch64")]
const SYSCALL_INSTR_LEN: usize = 4; // syscall
user_ctx.set_syscall_num(syscall_number);
user_ctx.set_syscall_ret(pre_syscall_ret);
user_ctx
.set_instruction_pointer(user_ctx.instruction_pointer() - SYSCALL_INSTR_LEN);
}

View File

@ -83,14 +83,14 @@ pub fn create_new_user_task(
// Handle user events
let user_ctx = user_mode.context_mut();
let mut syscall_number = None;
let mut pre_syscall_ret = None;
match return_reason {
ReturnReason::UserException => {
let exception = user_ctx.take_exception().unwrap();
handle_exception(&ctx, user_ctx, exception)
}
ReturnReason::UserSyscall => {
syscall_number = Some(user_ctx.syscall_num());
pre_syscall_ret = Some(user_ctx.syscall_ret());
handle_syscall(&ctx, user_ctx);
}
ReturnReason::KernelEvent => {}
@ -102,7 +102,7 @@ pub fn create_new_user_task(
}
// Handle signals
handle_pending_signal(user_ctx, &ctx, syscall_number);
handle_pending_signal(user_ctx, &ctx, pre_syscall_ret);
// Handle signals while the thread is stopped
// FIXME: Currently, we handle all signals when the process is stopped.