From 1435dd08968b351eeba8a816cab362a87073d9d1 Mon Sep 17 00:00:00 2001 From: Chen Chengjun Date: Wed, 10 Apr 2024 14:35:13 +0800 Subject: [PATCH] Add syscall nanosleep --- kernel/aster-nix/src/syscall/mod.rs | 6 ++- .../{clock_nanosleep.rs => nanosleep.rs} | 54 ++++++++++++++----- 2 files changed, 46 insertions(+), 14 deletions(-) rename kernel/aster-nix/src/syscall/{clock_nanosleep.rs => nanosleep.rs} (55%) diff --git a/kernel/aster-nix/src/syscall/mod.rs b/kernel/aster-nix/src/syscall/mod.rs index 1c80dcbaf..acec14877 100644 --- a/kernel/aster-nix/src/syscall/mod.rs +++ b/kernel/aster-nix/src/syscall/mod.rs @@ -27,7 +27,6 @@ use crate::{ chown::{sys_chown, sys_fchown, sys_fchownat, sys_lchown}, chroot::sys_chroot, clock_gettime::sys_clock_gettime, - clock_nanosleep::sys_clock_nanosleep, clone::sys_clone, close::sys_close, dup::{sys_dup, sys_dup2}, @@ -59,6 +58,7 @@ use crate::{ mmap::sys_mmap, mprotect::sys_mprotect, munmap::sys_munmap, + nanosleep::{sys_clock_nanosleep, sys_nanosleep}, open::{sys_open, sys_openat}, pause::sys_pause, pipe::{sys_pipe, sys_pipe2}, @@ -107,7 +107,6 @@ mod chmod; mod chown; mod chroot; mod clock_gettime; -mod clock_nanosleep; mod clone; mod close; mod connect; @@ -150,6 +149,7 @@ mod mkdir; mod mmap; mod mprotect; mod munmap; +mod nanosleep; mod open; mod pause; mod pipe; @@ -261,6 +261,7 @@ define_syscall_nums!( SYS_DUP = 32, SYS_DUP2 = 33, SYS_PAUSE = 34, + SYS_NANOSLEEP = 35, SYS_ALARM = 37, SYS_GETPID = 39, SYS_SOCKET = 41, @@ -449,6 +450,7 @@ pub fn syscall_dispatch( SYS_DUP => syscall_handler!(1, sys_dup, args), SYS_DUP2 => syscall_handler!(2, sys_dup2, args), SYS_PAUSE => syscall_handler!(0, sys_pause), + SYS_NANOSLEEP => syscall_handler!(2, sys_nanosleep, args), SYS_ALARM => syscall_handler!(1, sys_alarm, args), SYS_GETPID => syscall_handler!(0, sys_getpid), SYS_SOCKET => syscall_handler!(3, sys_socket, args), diff --git a/kernel/aster-nix/src/syscall/clock_nanosleep.rs b/kernel/aster-nix/src/syscall/nanosleep.rs similarity index 55% rename from kernel/aster-nix/src/syscall/clock_nanosleep.rs rename to kernel/aster-nix/src/syscall/nanosleep.rs index 95b34e6f9..88ab63156 100644 --- a/kernel/aster-nix/src/syscall/clock_nanosleep.rs +++ b/kernel/aster-nix/src/syscall/nanosleep.rs @@ -2,7 +2,7 @@ use core::time::Duration; -use super::{SyscallReturn, SYS_CLOCK_NANOSLEEP}; +use super::{SyscallReturn, SYS_CLOCK_NANOSLEEP, SYS_NANOSLEEP}; use crate::{ log_syscall_entry, prelude::*, @@ -11,6 +11,16 @@ use crate::{ util::{read_val_from_user, write_val_to_user}, }; +pub fn sys_nanosleep( + request_timespec_addr: Vaddr, + remain_timespec_addr: Vaddr, +) -> Result { + 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( clockid: clockid_t, flags: i32, @@ -19,7 +29,7 @@ pub fn sys_clock_nanosleep( ) -> Result { log_syscall_entry!(SYS_CLOCK_NANOSLEEP); let clock_id = ClockID::try_from(clockid)?; - let abs_time = if flags == 0 { + let is_abs_time = if flags == 0 { false } else if flags == TIMER_ABSTIME { true @@ -27,37 +37,57 @@ pub fn sys_clock_nanosleep( unreachable!() }; - let duration = { + do_clock_nanosleep( + clock_id, + is_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 { + let request_time = { let timespec = read_val_from_user::(request_timespec_addr)?; - if abs_time { - todo!("deal with abs time"); - } Duration::from(timespec) }; debug!( - "clockid = {:?}, abs_time = {}, duration = {:?}, remain_timespec_addr = 0x{:x}", - clock_id, abs_time, duration, remain_timespec_addr + "clockid = {:?}, is_abs_time = {}, request_time = {:?}, remain_timespec_addr = 0x{:x}", + clock_id, is_abs_time, request_time, remain_timespec_addr ); 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 // current process. i.e., the signals that should be ignored will not interrupt sleeping thread. let pauser = Pauser::new(); - let res = pauser.pause_until_or_timeout(|| None, &duration); + let res = pauser.pause_until_or_timeout(|| None, &timeout); match res { Err(e) if e.error() == Errno::ETIME => Ok(SyscallReturn::Return(0)), Err(e) if e.error() == Errno::EINTR => { 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)); } - if remain_timespec_addr != 0 { - let remaining_duration = (start_time + duration) - end_time; + if remain_timespec_addr != 0 && !is_abs_time { + let remaining_duration = (start_time + timeout) - end_time; let remaining_timespec = timespec_t::from(remaining_duration); write_val_to_user(remain_timespec_addr, &remaining_timespec)?; }