pub const KTIME_MAX_NANOS: u64 = i64::MAX as u64;
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct MonotonicInstant(u64);
impl MonotonicInstant {
pub const fn from_nanos(now_ns: u64) -> Option<Self> {
if now_ns <= KTIME_MAX_NANOS {
Some(Self(now_ns))
} else {
None
}
}
pub const fn as_nanos(self) -> u64 {
self.0
}
pub const fn reached(self, deadline: MonotonicDeadline) -> bool {
self.0 >= deadline.0
}
pub fn deadline_after(self, timeout: core::time::Duration) -> MonotonicDeadline {
let timeout_ns = timeout.as_nanos();
let sum = self.0 as u128 + timeout_ns;
if sum >= KTIME_MAX_NANOS as u128 {
MonotonicDeadline(KTIME_MAX_NANOS)
} else {
MonotonicDeadline(sum as u64)
}
}
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
pub struct MonotonicDeadline(u64);
impl MonotonicDeadline {
pub const ORIGIN: Self = Self(0);
pub const fn from_nanos(deadline_ns: u64) -> Option<Self> {
if deadline_ns <= KTIME_MAX_NANOS {
Some(Self(deadline_ns))
} else {
None
}
}
pub fn from_duration(deadline: core::time::Duration) -> Self {
const NANOS_PER_SECOND: u64 = 1_000_000_000;
const KTIME_SEC_MAX: u64 = KTIME_MAX_NANOS / NANOS_PER_SECOND;
if deadline.as_secs() >= KTIME_SEC_MAX {
return Self(KTIME_MAX_NANOS);
}
Self(deadline.as_secs() * NANOS_PER_SECOND + u64::from(deadline.subsec_nanos()))
}
pub const fn as_nanos(self) -> u64 {
self.0
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(C)]
pub struct RqClockSample {
clock: crate::sched::SchedulerTimestamp,
hardirq_time_ns: Option<u64>,
frequency_capacity: u32,
cpu_capacity: u32,
}
impl RqClockSample {
pub const fn new(clock: crate::sched::SchedulerTimestamp, hardirq_time_ns: u64) -> Self {
Self {
clock,
hardirq_time_ns: Some(hardirq_time_ns),
frequency_capacity: 1_024,
cpu_capacity: 1_024,
}
}
pub const fn without_irq_time_accounting(clock: crate::sched::SchedulerTimestamp) -> Self {
Self {
clock,
hardirq_time_ns: None,
frequency_capacity: 1_024,
cpu_capacity: 1_024,
}
}
pub const fn with_capacity_scales(
clock: crate::sched::SchedulerTimestamp,
hardirq_time_ns: u64,
frequency_capacity: u32,
cpu_capacity: u32,
) -> Option<Self> {
if frequency_capacity == 0
|| frequency_capacity > 1_024
|| cpu_capacity == 0
|| cpu_capacity > 1_024
{
return None;
}
Some(Self {
clock,
hardirq_time_ns: Some(hardirq_time_ns),
frequency_capacity,
cpu_capacity,
})
}
pub const fn clock(self) -> crate::sched::SchedulerTimestamp {
self.clock
}
pub const fn hardirq_time_ns(self) -> Option<u64> {
self.hardirq_time_ns
}
pub const fn frequency_capacity(self) -> u32 {
self.frequency_capacity
}
pub const fn cpu_capacity(self) -> u32 {
self.cpu_capacity
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct SchedulerDeadlineUpdate {
generation: u64,
deadline: Option<MonotonicDeadline>,
}
impl SchedulerDeadlineUpdate {
pub const fn try_new(generation: u64, deadline: Option<MonotonicDeadline>) -> Option<Self> {
if generation == 0 {
None
} else {
Some(Self {
generation,
deadline,
})
}
}
pub const fn generation(self) -> u64 {
self.generation
}
pub const fn deadline(self) -> Option<MonotonicDeadline> {
self.deadline
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SchedulerRuntimeDeadline {
Disarmed,
Due,
After(core::time::Duration),
}
#[cfg(test)]
mod monotonic_time_tests {
use super::*;
#[test]
fn monotonic_time_matches_linux_ktime_boundaries() {
let deadline = MonotonicDeadline::from_nanos(0).unwrap();
assert_eq!(deadline, MonotonicDeadline::ORIGIN);
assert!(MonotonicInstant::from_nanos(1).unwrap().reached(deadline));
assert!(MonotonicInstant::from_nanos(KTIME_MAX_NANOS - 1).is_some());
assert!(MonotonicDeadline::from_nanos(KTIME_MAX_NANOS - 1).is_some());
assert!(MonotonicInstant::from_nanos(KTIME_MAX_NANOS).is_some());
assert_eq!(
MonotonicDeadline::from_nanos(KTIME_MAX_NANOS),
Some(MonotonicDeadline(KTIME_MAX_NANOS))
);
assert!(MonotonicDeadline::from_nanos(KTIME_MAX_NANOS + 1).is_none());
assert_eq!(
MonotonicDeadline::from_duration(core::time::Duration::MAX),
MonotonicDeadline::from_nanos(KTIME_MAX_NANOS).unwrap()
);
let now = MonotonicInstant::from_nanos(KTIME_MAX_NANOS - 2).unwrap();
assert_eq!(
now.deadline_after(core::time::Duration::from_nanos(2)),
MonotonicDeadline::from_nanos(KTIME_MAX_NANOS).unwrap()
);
}
}