Add syscall nanosleep

This commit is contained in:
Chen Chengjun
2024-04-10 14:35:13 +08:00
committed by Tate, Hongliang Tian
parent ee740020d0
commit 1435dd0896
2 changed files with 46 additions and 14 deletions

View File

@ -27,7 +27,6 @@ use crate::{
chown::{sys_chown, sys_fchown, sys_fchownat, sys_lchown}, chown::{sys_chown, sys_fchown, sys_fchownat, sys_lchown},
chroot::sys_chroot, chroot::sys_chroot,
clock_gettime::sys_clock_gettime, clock_gettime::sys_clock_gettime,
clock_nanosleep::sys_clock_nanosleep,
clone::sys_clone, clone::sys_clone,
close::sys_close, close::sys_close,
dup::{sys_dup, sys_dup2}, dup::{sys_dup, sys_dup2},
@ -59,6 +58,7 @@ use crate::{
mmap::sys_mmap, mmap::sys_mmap,
mprotect::sys_mprotect, mprotect::sys_mprotect,
munmap::sys_munmap, munmap::sys_munmap,
nanosleep::{sys_clock_nanosleep, sys_nanosleep},
open::{sys_open, sys_openat}, open::{sys_open, sys_openat},
pause::sys_pause, pause::sys_pause,
pipe::{sys_pipe, sys_pipe2}, pipe::{sys_pipe, sys_pipe2},
@ -107,7 +107,6 @@ mod chmod;
mod chown; mod chown;
mod chroot; mod chroot;
mod clock_gettime; mod clock_gettime;
mod clock_nanosleep;
mod clone; mod clone;
mod close; mod close;
mod connect; mod connect;
@ -150,6 +149,7 @@ mod mkdir;
mod mmap; mod mmap;
mod mprotect; mod mprotect;
mod munmap; mod munmap;
mod nanosleep;
mod open; mod open;
mod pause; mod pause;
mod pipe; mod pipe;
@ -261,6 +261,7 @@ define_syscall_nums!(
SYS_DUP = 32, SYS_DUP = 32,
SYS_DUP2 = 33, SYS_DUP2 = 33,
SYS_PAUSE = 34, SYS_PAUSE = 34,
SYS_NANOSLEEP = 35,
SYS_ALARM = 37, SYS_ALARM = 37,
SYS_GETPID = 39, SYS_GETPID = 39,
SYS_SOCKET = 41, SYS_SOCKET = 41,
@ -449,6 +450,7 @@ pub fn syscall_dispatch(
SYS_DUP => syscall_handler!(1, sys_dup, args), SYS_DUP => syscall_handler!(1, sys_dup, args),
SYS_DUP2 => syscall_handler!(2, sys_dup2, args), SYS_DUP2 => syscall_handler!(2, sys_dup2, args),
SYS_PAUSE => syscall_handler!(0, sys_pause), SYS_PAUSE => syscall_handler!(0, sys_pause),
SYS_NANOSLEEP => syscall_handler!(2, sys_nanosleep, args),
SYS_ALARM => syscall_handler!(1, sys_alarm, args), SYS_ALARM => syscall_handler!(1, sys_alarm, args),
SYS_GETPID => syscall_handler!(0, sys_getpid), SYS_GETPID => syscall_handler!(0, sys_getpid),
SYS_SOCKET => syscall_handler!(3, sys_socket, args), SYS_SOCKET => syscall_handler!(3, sys_socket, args),

View File

@ -2,7 +2,7 @@
use core::time::Duration; use core::time::Duration;
use super::{SyscallReturn, SYS_CLOCK_NANOSLEEP}; use super::{SyscallReturn, SYS_CLOCK_NANOSLEEP, SYS_NANOSLEEP};
use crate::{ use crate::{
log_syscall_entry, log_syscall_entry,
prelude::*, prelude::*,
@ -11,6 +11,16 @@ use crate::{
util::{read_val_from_user, write_val_to_user}, util::{read_val_from_user, write_val_to_user},
}; };
pub fn sys_nanosleep(
request_timespec_addr: Vaddr,
remain_timespec_addr: Vaddr,
) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_NANOSLEEP);
let clock_id = ClockID::CLOCK_MONOTONIC;
do_clock_nanosleep(clock_id, false, request_timespec_addr, remain_timespec_addr)
}
pub fn sys_clock_nanosleep( pub fn sys_clock_nanosleep(
clockid: clockid_t, clockid: clockid_t,
flags: i32, flags: i32,
@ -19,7 +29,7 @@ pub fn sys_clock_nanosleep(
) -> Result<SyscallReturn> { ) -> Result<SyscallReturn> {
log_syscall_entry!(SYS_CLOCK_NANOSLEEP); log_syscall_entry!(SYS_CLOCK_NANOSLEEP);
let clock_id = ClockID::try_from(clockid)?; let clock_id = ClockID::try_from(clockid)?;
let abs_time = if flags == 0 { let is_abs_time = if flags == 0 {
false false
} else if flags == TIMER_ABSTIME { } else if flags == TIMER_ABSTIME {
true true
@ -27,37 +37,57 @@ pub fn sys_clock_nanosleep(
unreachable!() unreachable!()
}; };
let duration = { do_clock_nanosleep(
let timespec = read_val_from_user::<timespec_t>(request_timespec_addr)?; clock_id,
if abs_time { is_abs_time,
todo!("deal with abs time"); request_timespec_addr,
remain_timespec_addr,
)
} }
fn do_clock_nanosleep(
clock_id: ClockID,
is_abs_time: bool,
request_timespec_addr: Vaddr,
remain_timespec_addr: Vaddr,
) -> Result<SyscallReturn> {
let request_time = {
let timespec = read_val_from_user::<timespec_t>(request_timespec_addr)?;
Duration::from(timespec) Duration::from(timespec)
}; };
debug!( debug!(
"clockid = {:?}, abs_time = {}, duration = {:?}, remain_timespec_addr = 0x{:x}", "clockid = {:?}, is_abs_time = {}, request_time = {:?}, remain_timespec_addr = 0x{:x}",
clock_id, abs_time, duration, remain_timespec_addr clock_id, is_abs_time, request_time, remain_timespec_addr
); );
let start_time = now_as_duration(&clock_id)?; let start_time = now_as_duration(&clock_id)?;
let timeout = if is_abs_time {
if request_time < start_time {
return Ok(SyscallReturn::Return(0));
}
request_time - start_time
} else {
request_time
};
// FIXME: sleeping thread can only be interrupted by signals that will call signal handler or terminate // FIXME: sleeping thread can only be interrupted by signals that will call signal handler or terminate
// current process. i.e., the signals that should be ignored will not interrupt sleeping thread. // current process. i.e., the signals that should be ignored will not interrupt sleeping thread.
let pauser = Pauser::new(); let pauser = Pauser::new();
let res = pauser.pause_until_or_timeout(|| None, &duration); let res = pauser.pause_until_or_timeout(|| None, &timeout);
match res { match res {
Err(e) if e.error() == Errno::ETIME => Ok(SyscallReturn::Return(0)), Err(e) if e.error() == Errno::ETIME => Ok(SyscallReturn::Return(0)),
Err(e) if e.error() == Errno::EINTR => { Err(e) if e.error() == Errno::EINTR => {
let end_time = now_as_duration(&clock_id)?; let end_time = now_as_duration(&clock_id)?;
if end_time >= start_time + duration { if end_time >= start_time + timeout {
return Ok(SyscallReturn::Return(0)); return Ok(SyscallReturn::Return(0));
} }
if remain_timespec_addr != 0 { if remain_timespec_addr != 0 && !is_abs_time {
let remaining_duration = (start_time + duration) - end_time; let remaining_duration = (start_time + timeout) - end_time;
let remaining_timespec = timespec_t::from(remaining_duration); let remaining_timespec = timespec_t::from(remaining_duration);
write_val_to_user(remain_timespec_addr, &remaining_timespec)?; write_val_to_user(remain_timespec_addr, &remaining_timespec)?;
} }