Files
RedBear-OS/src/syscall/time.rs
T
vasilito ca67b1da37 0.3.0: converge kernel onto upstream master
- Rebase all Red Bear kernel changes onto upstream master (4d5d36d4).
- Update version to 0.5.12+rb0.3.0 and add Red Bear author attribution.
- Switch redox_syscall direct dependency to local fork path (../syscall).
- Bump rust-toolchain.toml to nightly-2026-05-24.
- Regenerate Cargo.lock for +rb0.3.0 suffixes and path deps.
2026-07-06 18:43:52 +03:00

92 lines
2.5 KiB
Rust

use crate::{
context,
sync::CleanLockToken,
syscall::{
data::TimeSpec,
error::*,
flag::{CLOCK_MONOTONIC, CLOCK_REALTIME},
},
time,
};
use super::usercopy::{UserSliceRo, UserSliceWo};
pub fn clock_gettime(clock: usize, buf: UserSliceWo, token: &mut CleanLockToken) -> Result<()> {
let arch_time = match clock {
CLOCK_REALTIME => time::realtime(token),
CLOCK_MONOTONIC => time::monotonic(token),
_ => return Err(Error::new(EINVAL)),
};
buf.copy_exactly(&TimeSpec {
tv_sec: (arch_time / time::NANOS_PER_SEC) as i64,
tv_nsec: (arch_time % time::NANOS_PER_SEC) as i32,
})
}
/// Nanosleep will sleep by switching the current context
pub fn nanosleep(
req_buf: UserSliceRo,
rem_buf_opt: Option<UserSliceWo>,
token: &mut CleanLockToken,
) -> Result<()> {
let req = unsafe { req_buf.read_exact::<TimeSpec>()? };
if req.tv_sec < 0 || req.tv_nsec < 0 || req.tv_nsec >= time::NANOS_PER_SEC as i32 {
return Err(Error::new(EINVAL));
}
let start = time::monotonic(token);
let end = start + (req.tv_sec as u128 * time::NANOS_PER_SEC) + (req.tv_nsec as u128);
let current_context = context::current();
{
let mut context = current_context.write(token.token());
if let Some((tctl, pctl, _)) = context.sigcontrol()
&& tctl.currently_pending_unblocked(pctl) != 0
{
return Err(Error::new(EINTR));
}
context.wake = Some(end);
context.block("nanosleep");
}
// TODO: The previous wakeup reason was most likely signals, but is there any other possible
// reason?
context::switch(token);
let was_interrupted = current_context.write(token.token()).wake.take().is_some();
if let Some(rem_buf) = rem_buf_opt {
let current = time::monotonic(token);
rem_buf.copy_exactly(&if current < end {
let diff = end - current;
TimeSpec {
tv_sec: (diff / time::NANOS_PER_SEC) as i64,
tv_nsec: (diff % time::NANOS_PER_SEC) as i32,
}
} else {
TimeSpec {
tv_sec: 0,
tv_nsec: 0,
}
})?;
}
if was_interrupted {
Err(Error::new(EINTR))
} else {
Ok(())
}
}
pub fn sched_yield(token: &mut CleanLockToken) -> Result<()> {
context::switch(token);
// TODO: Do this check in userspace
context::signal::signal_handler(token);
Ok(())
}