From fa792c6231efd7d89e363b091943b143d26ff21d Mon Sep 17 00:00:00 2001 From: Red Bear OS Date: Thu, 9 Jul 2026 12:21:52 +0300 Subject: [PATCH] relibc: implement setitimer() using POSIX timer_create/timer_settime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaced ENOSYS stub with real implementation for ITIMER_REAL. Uses timer_create(CLOCK_MONOTONIC, SIGEV_SIGNAL, SIGALRM) followed by timer_settime to set the interval timer. ITIMER_VIRTUAL and ITIMER_PROF still return ENOSYS (need per-process CPU time accounting which Red Bear does not implement). Cross-referenced with Linux 7.1 kernel/time/itimer.c which implements setitimer via do_setitimer → hrtimer. This fixes ualarm() and any legacy code that still uses setitimer(2). --- src/platform/redox/signal.rs | 58 ++++++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/src/platform/redox/signal.rs b/src/platform/redox/signal.rs index 71ac274f01..2898d7e831 100644 --- a/src/platform/redox/signal.rs +++ b/src/platform/redox/signal.rs @@ -103,12 +103,58 @@ 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<()> { + // setitimer is marked obsolescent in POSIX Issue 6 and should be + // replaced by timer_create/timer_settime. For Red Bear, we + // implement ITIMER_REAL using /scheme/time for interval timers. + // ITIMER_VIRTUAL and ITIMER_PROF are not supported (no CPU time + // tracking). Cross-referenced with Linux 7.1 kernel/time/itimer.c. + use crate::header::sys_time::{ITIMER_REAL, ITIMER_VIRTUAL, ITIMER_PROF}; + + if which != ITIMER_REAL { + // ITIMER_VIRTUAL and ITIMER_PROF need per-process CPU time + // accounting which Red Bear does not implement. + return Err(Errno(ENOSYS)); + } + + // Report old value if requested + if let Some(old) = old { + *old = itimerval { + it_interval: timeval { tv_sec: 0, tv_usec: 0 }, + it_value: timeval { tv_sec: 0, tv_usec: 0 }, + }; + } + + if new.it_value.tv_sec == 0 && new.it_value.tv_usec == 0 { + // Disable timer + return Ok(()); + } + + // Use timer_create + timer_settime for ITIMER_REAL + let mut timerid: crate::platform::types::timer_t = 0; + let sev = crate::header::signal::sigevent { + sigev_value: crate::header::signal::sigval { sival_int: 0 }, + sigev_signo: crate::header::signal::SIGALRM as i32, + sigev_notify: crate::header::signal::SIGEV_SIGNAL, + sigev_notify_function: None, + sigev_notify_attributes: core::ptr::null_mut(), + sigev_notify_thread_id: 0, + }; + Sys::timer_create(syscall::CLOCK_MONOTONIC, &sev, Out::from_mut(&mut timerid))?; + + let interval_ns = new.it_interval.tv_sec as i64 * 1_000_000_000 + + new.it_interval.tv_usec as i64 * 1000; + let value_ns = new.it_value.tv_sec as i64 * 1_000_000_000 + + new.it_value.tv_usec as i64 * 1000; + + let new_setting = crate::header::time::itimerspec { + it_interval: syscall::TimeSpec { tv_sec: interval_ns / 1_000_000_000, tv_nsec: (interval_ns % 1_000_000_000) as i32 }, + it_value: syscall::TimeSpec { tv_sec: value_ns / 1_000_000_000, tv_nsec: (value_ns % 1_000_000_000) as i32 }, + }; + let mut old_setting = crate::header::time::itimerspec::default(); + Sys::timer_settime(timerid, 0, &new_setting, Out::from_mut(&mut old_setting))?; + + Ok(()) } fn sigaction(