pub use core::time::Duration;
pub type TimeValue = Duration;
pub const MILLIS_PER_SEC: u64 = 1_000;
pub const MICROS_PER_SEC: u64 = 1_000_000;
pub const NANOS_PER_SEC: u64 = 1_000_000_000;
pub const NANOS_PER_MILLIS: u64 = 1_000_000;
pub const NANOS_PER_MICROS: u64 = 1_000;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SchedulerClockStability {
Stable,
Unstable,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, thiserror::Error)]
pub enum SchedulerClockError {
#[error("logical CPU {cpu_id} is outside the installed per-CPU layout")]
InvalidCpu { cpu_id: usize },
#[error("the calling CPU has no validated CPU-local area")]
CurrentCpuUnavailable,
#[error("scheduler clock CPU mismatch: expected {expected_cpu_id}, current {actual_cpu_id}")]
WrongCurrentCpu {
expected_cpu_id: usize,
actual_cpu_id: usize,
},
#[error("the scheduler clock CPU is already online")]
CpuAlreadyOnline,
#[error("the scheduler clock CPU is offline")]
CpuOffline,
}
#[def_plat_interface]
pub trait TimeIf {
fn current_ticks() -> u64;
fn ticks_to_nanos(ticks: u64) -> u64;
fn nanos_to_ticks(nanos: u64) -> u64;
fn scheduler_clock_stability() -> SchedulerClockStability;
fn epochoffset_nanos() -> u64;
fn irq_num() -> irq_framework::IrqId;
fn set_oneshot_timer(deadline_ns: u64);
}
pub unsafe fn init_scheduler_clock(cpu_id: usize) -> Result<(), SchedulerClockError> {
let stability = scheduler_clock_stability();
let raw_clock = ticks_to_nanos(current_ticks());
unsafe { crate::scheduler_clock::online_current_cpu(cpu_id, raw_clock, stability) }
}
pub unsafe fn shutdown_scheduler_clock(cpu_id: usize) -> Result<(), SchedulerClockError> {
unsafe { crate::scheduler_clock::offline_current_cpu(cpu_id) }
}
#[inline]
pub unsafe fn scheduler_clock_source(cpu_id: usize) -> Result<u64, SchedulerClockError> {
let raw_clock = ticks_to_nanos(current_ticks());
unsafe { crate::scheduler_clock::source(cpu_id, raw_clock) }
}
#[inline]
pub unsafe fn scheduler_clock_tick() -> Result<u64, SchedulerClockError> {
let stability = scheduler_clock_stability();
let raw_clock = ticks_to_nanos(current_ticks());
unsafe { crate::scheduler_clock::tick(raw_clock, stability) }
}
pub fn monotonic_time_nanos() -> u64 {
ticks_to_nanos(current_ticks())
}
pub fn monotonic_time() -> TimeValue {
TimeValue::from_nanos(monotonic_time_nanos())
}
pub fn wall_time_nanos() -> u64 {
monotonic_time_nanos() + epochoffset_nanos()
}
pub fn wall_time() -> TimeValue {
TimeValue::from_nanos(monotonic_time_nanos() + epochoffset_nanos())
}
pub fn busy_wait(dur: Duration) {
busy_wait_until(monotonic_time() + dur);
}
pub fn busy_wait_until(deadline: TimeValue) {
while monotonic_time() < deadline {
core::hint::spin_loop();
}
}