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:
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user