relibc: implement setitimer() using POSIX timer_create/timer_settime

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).
This commit is contained in:
Red Bear OS
2026-07-09 12:21:52 +03:00
parent c1cad7f95f
commit fa792c6231
+52 -6
View File
@@ -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(