diff --git a/src/header/spawn/spawn_attr.rs b/src/header/spawn/spawn_attr.rs index 2c541585eb..4f3d95a911 100644 --- a/src/header/spawn/spawn_attr.rs +++ b/src/header/spawn/spawn_attr.rs @@ -41,7 +41,7 @@ pub struct posix_spawnattr_t { pub param: sched_param, pub flags: c_short, pub pgroup: c_int, - policy: c_int, + pub(crate) policy: c_int, pub sigdefault: sigset_t, pub sigmask: sigset_t, } diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index a1844ba887..1e73aa2d39 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -38,6 +38,7 @@ use crate::{ }, limits::{self}, pthread::{pthread_cancel, pthread_create}, + sched::{SCHED_FIFO, SCHED_OTHER, SCHED_RR}, signal::{NSIG, SIGEV_NONE, SIGEV_SIGNAL, SIGEV_THREAD, SIGRTMIN, sigevent}, stdio::RENAME_NOREPLACE, stdlib::posix_memalign, @@ -56,7 +57,7 @@ use crate::{ time::{ CLOCK_MONOTONIC, CLOCK_REALTIME, TIMER_ABSTIME, itimerspec, timer_internal_t, timespec, }, - unistd::{F_OK, R_OK, SEEK_CUR, SEEK_SET, W_OK, X_OK}, + unistd::{F_OK, R_OK, SEEK_CUR, SEEK_END, SEEK_SET, W_OK, X_OK}, }, io::{self, BufReader, prelude::*}, iter::NulTerminated, @@ -367,7 +368,7 @@ impl Pal for Sys { fn fcntl(fd: c_int, cmd: c_int, args: c_ulonglong) -> Result { match cmd { - F_SETLK | F_OFD_SETLK => { + F_SETLK | F_OFD_SETLK | F_SETLKW => { let is_ofd = cmd == F_OFD_SETLK; let flock = unsafe { &mut *(args as *mut flock) }; @@ -471,8 +472,6 @@ impl Pal for Sys { return Ok(0); } - F_SETLKW => log::warn!("F_SETLKW: not yet implemented"), - _ => {} } @@ -1484,7 +1483,15 @@ impl Pal for Sys { Ok(()) } }; - let set_scheduler = || -> Result<()> { todo!() }; + let set_scheduler = || -> Result<()> { + // SCHED_OTHER is the kernel default (no-op); RT policies need + // kernel support Redox lacks, so ENOSYS per POSIX. + match attr.policy { + SCHED_OTHER => Ok(()), + SCHED_FIFO | SCHED_RR => Err(Errno(ENOSYS)), + _ => Err(Errno(EINVAL)), + } + }; // scheduling paramters must be set regardless of whether the flag POSIX_SPAWN_SETSCHEDPARAM is set if flags.contains(Flags::POSIX_SPAWN_SETSCHEDULER) { @@ -1986,12 +1993,31 @@ impl Sys { assert!(len >= 0); Ok((start, len)) } - // FIXME: andypython: SEEK_CUR, SEEK_END + c if c == i32::from(SEEK_CUR) || c == i32::from(SEEK_END) => { + let base = if c == i32::from(SEEK_CUR) { + syscall::lseek(fd, 0, SEEK_CUR as usize)? as off_t + } else { + let mut st: stat = unsafe { mem::zeroed() }; + unsafe { libredox::fstat(fd, &raw mut st) }?; + st.st_size as off_t + }; + + let abs_start = base + start; + let (abs_start, abs_len) = if len < 0 { + (abs_start + len, -len) + } else { + (abs_start, len) + }; + + if abs_start < 0 { + return Err(Errno(EINVAL)); + } + + assert!(abs_len >= 0); + Ok((abs_start, abs_len)) + } c => { - log::warn!( - "Sys::relative_to_absolute_foffset: whence={whence} not yet implemented" - ); - Ok((0, 0)) + return Err(Errno(EINVAL)); } } } diff --git a/src/platform/redox/ptrace.rs b/src/platform/redox/ptrace.rs index 4ac81a00c7..482df1f4d3 100644 --- a/src/platform/redox/ptrace.rs +++ b/src/platform/redox/ptrace.rs @@ -14,7 +14,7 @@ use crate::{ error::Errno, fs::File, header::{ - errno::{self as errnoh, EIO}, + errno::{self as errnoh, EIO, ENOSYS}, fcntl, }, io, @@ -118,24 +118,22 @@ pub fn get_session( #[cfg(target_arch = "aarch64")] unsafe fn inner_ptrace( - request: c_int, - pid: pid_t, - addr: *mut c_void, - data: *mut c_void, + _request: c_int, + _pid: pid_t, + _addr: *mut c_void, + _data: *mut c_void, ) -> io::Result { - //TODO: aarch64 - unimplemented!("inner_ptrace not implemented on aarch64"); + Err(io::Error::from_raw_os_error(ENOSYS)) } #[cfg(target_arch = "x86")] unsafe fn inner_ptrace( - request: c_int, - pid: pid_t, - addr: *mut c_void, - data: *mut c_void, + _request: c_int, + _pid: pid_t, + _addr: *mut c_void, + _data: *mut c_void, ) -> io::Result { - //TODO: x86 - unimplemented!("inner_ptrace not implemented on x86"); + Err(io::Error::from_raw_os_error(ENOSYS)) } #[cfg(target_arch = "x86_64")] @@ -270,13 +268,12 @@ unsafe fn inner_ptrace( #[cfg(target_arch = "riscv64")] fn inner_ptrace( - request: c_int, - pid: pid_t, - addr: *mut c_void, - data: *mut c_void, + _request: c_int, + _pid: pid_t, + _addr: *mut c_void, + _data: *mut c_void, ) -> io::Result { - //TODO: riscv64 - unimplemented!("inner_ptrace not implemented on riscv64"); + Err(io::Error::from_raw_os_error(ENOSYS)) } impl PalPtrace for Sys { diff --git a/src/platform/redox/signal.rs b/src/platform/redox/signal.rs index 6d29af132b..6885c131ba 100644 --- a/src/platform/redox/signal.rs +++ b/src/platform/redox/signal.rs @@ -8,13 +8,16 @@ use crate::{ error::{Errno, Result}, header::{ bits_sigset_t::sigset_t, - errno::{EINVAL, ENOSYS}, + errno::{EINVAL}, signal::{ - SIG_BLOCK, SIG_DFL, SIG_IGN, SIG_SETMASK, SIG_UNBLOCK, SS_DISABLE, SS_ONSTACK, - sigaction, siginfo_t, sigval, stack_t, ucontext_t, + SIGALRM, SIG_BLOCK, SIG_DFL, SIG_IGN, SIG_SETMASK, SIG_UNBLOCK, SS_DISABLE, + SS_ONSTACK, SIGEV_SIGNAL, sigaction, sigevent, siginfo_t, sigval, stack_t, + ucontext_t, }, - time::timespec, + time::{CLOCK_REALTIME, itimerspec, timespec}, }, + out::Out, + sync::Mutex, }; use core::mem::offset_of; use redox_protocols::protocol::ProcKillTarget; @@ -22,6 +25,11 @@ use redox_rt::signal::{ PosixStackt, SigStack, Sigaction, SigactionFlags, SigactionKind, Sigaltstack, SignalHandler, }; +struct ItimerTimer(timer_t); +unsafe impl Send for ItimerTimer {} + +static ITIMER_REAL_TIMER: Mutex> = Mutex::new(None); + const _: () = { #[track_caller] const fn assert_eq(a: usize, b: usize) { @@ -47,20 +55,21 @@ const _: () = { impl PalSignal for Sys { #[allow(deprecated)] fn getitimer(which: c_int, out: &mut itimerval) -> Result<()> { - let path = match which { - ITIMER_REAL => "/scheme/itimer/1", - _ => return Err(Errno(EINVAL)), - }; - // TODO: implement setitimer - // let fd = FdGuard::new(redox_rt::sys::open(path, syscall::O_RDONLY | syscall::O_CLOEXEC)?); - // let count = syscall::read(*fd, &mut spec)?; - - let spec = syscall::ITimerSpec::default(); - out.it_interval.tv_sec = spec.it_interval.tv_sec as time_t; - out.it_interval.tv_usec = spec.it_interval.tv_nsec / 1000; - out.it_value.tv_sec = spec.it_value.tv_sec as time_t; - out.it_value.tv_usec = spec.it_value.tv_nsec / 1000; + if which != ITIMER_REAL { + return Err(Errno(EINVAL)); + } + let guard = ITIMER_REAL_TIMER.lock(); + if let Some(ref timer) = *guard { + let mut cur = itimerspec::default(); + Sys::timer_gettime(timer.0, Out::from_mut(&mut cur))?; + out.it_interval.tv_sec = cur.it_interval.tv_sec as time_t; + out.it_interval.tv_usec = (cur.it_interval.tv_nsec / 1000) as suseconds_t; + out.it_value.tv_sec = cur.it_value.tv_sec as time_t; + out.it_value.tv_usec = (cur.it_value.tv_nsec / 1000) as suseconds_t; + } else { + *out = unsafe { core::mem::zeroed() }; + } Ok(()) } @@ -89,12 +98,67 @@ impl PalSignal for Sys { } #[allow(deprecated)] - fn setitimer(which: c_int, _new: &itimerval, old: Option<&mut itimerval>) -> Result<()> { - // TODO: setitimer is no longer part of POSIX and should not be implemented in Redox - // Change the platform-independent implementation to use POSIX timers. - // For Redox, the timer should probably use "/scheme/time" - todo_skip!(0, "setitimer not implemented"); - Err(Errno(ENOSYS)) + fn setitimer(which: c_int, new: &itimerval, old: Option<&mut itimerval>) -> Result<()> { + if which != ITIMER_REAL { + return Err(Errno(EINVAL)); + } + + let mut guard = ITIMER_REAL_TIMER.lock(); + + if let Some(old_out) = old { + if let Some(ref timer) = *guard { + let mut cur = itimerspec::default(); + if Sys::timer_gettime(timer.0, Out::from_mut(&mut cur)).is_ok() { + old_out.it_interval.tv_sec = cur.it_interval.tv_sec as time_t; + old_out.it_interval.tv_usec = + (cur.it_interval.tv_nsec / 1000) as suseconds_t; + old_out.it_value.tv_sec = cur.it_value.tv_sec as time_t; + old_out.it_value.tv_usec = (cur.it_value.tv_nsec / 1000) as suseconds_t; + } else { + *old_out = unsafe { core::mem::zeroed() }; + } + } else { + *old_out = unsafe { core::mem::zeroed() }; + } + } + + let disarm = new.it_value.tv_sec == 0 && new.it_value.tv_usec == 0; + + if disarm { + if let Some(ref timer) = *guard { + let zero = itimerspec::default(); + let _ = Sys::timer_settime(timer.0, 0, &zero, None); + } + return Ok(()); + } + + if guard.is_none() { + let mut evp: sigevent = unsafe { core::mem::zeroed() }; + evp.sigev_notify = SIGEV_SIGNAL; + evp.sigev_signo = SIGALRM as c_int; + let mut timer_id: timer_t = core::ptr::null_mut(); + Sys::timer_create(CLOCK_REALTIME, &evp, Out::from_mut(&mut timer_id))?; + *guard = Some(ItimerTimer(timer_id)); + } + + let timer_id = guard + .as_ref() + .expect("itimer must exist after lazy init") + .0; + + let spec = itimerspec { + it_value: timespec { + tv_sec: new.it_value.tv_sec, + tv_nsec: new.it_value.tv_usec as i64 * 1000, + }, + it_interval: timespec { + tv_sec: new.it_interval.tv_sec, + tv_nsec: new.it_interval.tv_usec as i64 * 1000, + }, + }; + + Sys::timer_settime(timer_id, 0, &spec, None)?; + Ok(()) } fn sigaction(