|
1 | 1 | // SPDX-License-Identifier: GPL-2.0 |
2 | 2 |
|
3 | | -//! Time related primitives. |
| 3 | +//! Time related primitives and functions. |
4 | 4 | //! |
5 | 5 | //! This module contains the kernel APIs related to time and timers that |
6 | 6 | //! have been ported or wrapped for usage by Rust code in the kernel. |
7 | 7 | //! |
8 | 8 | //! C header: [`include/linux/jiffies.h`](srctree/include/linux/jiffies.h). |
9 | 9 | //! C header: [`include/linux/ktime.h`](srctree/include/linux/ktime.h). |
| 10 | +//! C header: [`include/linux/timekeeping.h`](srctree/include/linux/timekeeping.h) |
10 | 11 |
|
11 | 12 | /// The number of nanoseconds per millisecond. |
12 | 13 | pub const NSEC_PER_MSEC: i64 = bindings::NSEC_PER_MSEC as i64; |
@@ -81,3 +82,151 @@ impl core::ops::Sub for Ktime { |
81 | 82 | } |
82 | 83 | } |
83 | 84 | } |
| 85 | + |
| 86 | +use crate::{bindings, pr_err}; |
| 87 | +use core::marker::PhantomData; |
| 88 | +use core::time::Duration; |
| 89 | + |
| 90 | +/// Represents a clock, that is, a unique time source. |
| 91 | +pub trait Clock: Sized {} |
| 92 | + |
| 93 | +/// A time source that can be queried for the current time. |
| 94 | +pub trait Now: Clock { |
| 95 | + /// Returns the current time for this clock. |
| 96 | + fn now() -> Instant<Self>; |
| 97 | +} |
| 98 | + |
| 99 | +/// Marker trait for clock sources that are guaranteed to be monotonic. |
| 100 | +pub trait Monotonic {} |
| 101 | + |
| 102 | +/// Marker trait for clock sources that represent a calendar (wall clock) |
| 103 | +/// relative to the UNIX epoch. |
| 104 | +pub trait WallTime {} |
| 105 | + |
| 106 | +/// An instant in time associated with a given clock source. |
| 107 | +#[derive(Debug)] |
| 108 | +pub struct Instant<T: Clock> { |
| 109 | + nanoseconds: i64, |
| 110 | + _type: PhantomData<T>, |
| 111 | +} |
| 112 | + |
| 113 | +impl<T: Clock> Clone for Instant<T> { |
| 114 | + fn clone(&self) -> Self { |
| 115 | + *self |
| 116 | + } |
| 117 | +} |
| 118 | + |
| 119 | +impl<T: Clock> Copy for Instant<T> {} |
| 120 | + |
| 121 | +impl<T: Clock> Instant<T> { |
| 122 | + fn new(nanoseconds: i64) -> Self { |
| 123 | + Instant { |
| 124 | + nanoseconds, |
| 125 | + _type: PhantomData, |
| 126 | + } |
| 127 | + } |
| 128 | + |
| 129 | + /// Returns the time elapsed since an earlier Instant<t>, or |
| 130 | + /// None if the argument is a later Instant. |
| 131 | + pub fn since(&self, earlier: Instant<T>) -> Option<Duration> { |
| 132 | + if earlier.nanoseconds > self.nanoseconds { |
| 133 | + None |
| 134 | + } else { |
| 135 | + // Casting to u64 and subtracting is guaranteed to give the right |
| 136 | + // result for all inputs, as long as the condition we checked above |
| 137 | + // holds. |
| 138 | + Some(Duration::from_nanos( |
| 139 | + self.nanoseconds as u64 - earlier.nanoseconds as u64, |
| 140 | + )) |
| 141 | + } |
| 142 | + } |
| 143 | +} |
| 144 | + |
| 145 | +impl<T: Clock + Now + Monotonic> Instant<T> { |
| 146 | + /// Returns the time elapsed since this Instant<T>. |
| 147 | + /// |
| 148 | + /// This is guaranteed to return a positive result, since |
| 149 | + /// it is only implemented for monotonic clocks. |
| 150 | + pub fn elapsed(&self) -> Duration { |
| 151 | + T::now().since(*self).unwrap_or_else(|| { |
| 152 | + pr_err!( |
| 153 | + "Monotonic clock {} went backwards!", |
| 154 | + core::any::type_name::<T>() |
| 155 | + ); |
| 156 | + Duration::ZERO |
| 157 | + }) |
| 158 | + } |
| 159 | +} |
| 160 | + |
| 161 | +/// Contains the various clock source types available to the kernel. |
| 162 | +pub mod clock { |
| 163 | + use super::*; |
| 164 | + |
| 165 | + /// A clock representing the default kernel time source. |
| 166 | + /// |
| 167 | + /// This is `CLOCK_MONOTONIC` (though it is not the only |
| 168 | + /// monotonic clock) and also the default clock used by |
| 169 | + /// `ktime_get()` in the C API. |
| 170 | + /// |
| 171 | + /// This is like `BootTime`, but does not include time |
| 172 | + /// spent sleeping. |
| 173 | +
|
| 174 | + pub struct KernelTime; |
| 175 | + |
| 176 | + impl Clock for KernelTime {} |
| 177 | + impl Monotonic for KernelTime {} |
| 178 | + impl Now for KernelTime { |
| 179 | + fn now() -> Instant<Self> { |
| 180 | + // SAFETY: Always safe to call |
| 181 | + Instant::<Self>::new(unsafe { bindings::ktime_get() }) |
| 182 | + } |
| 183 | + } |
| 184 | + |
| 185 | + /// A clock representing the time elapsed since boot. |
| 186 | + /// |
| 187 | + /// This is `CLOCK_MONOTONIC` (though it is not the only |
| 188 | + /// monotonic clock) and also the default clock used by |
| 189 | + /// `ktime_get()` in the C API. |
| 190 | + /// |
| 191 | + /// This is like `KernelTime`, but does include time |
| 192 | + /// spent sleeping. |
| 193 | + pub struct BootTime; |
| 194 | + |
| 195 | + impl Clock for BootTime {} |
| 196 | + impl Monotonic for BootTime {} |
| 197 | + impl Now for BootTime { |
| 198 | + fn now() -> Instant<Self> { |
| 199 | + // SAFETY: Always safe to call |
| 200 | + Instant::<Self>::new(unsafe { bindings::ktime_get_boottime() }) |
| 201 | + } |
| 202 | + } |
| 203 | + |
| 204 | + /// A clock representing TAI time. |
| 205 | + /// |
| 206 | + /// This clock is not monotonic and can be changed from userspace. |
| 207 | + /// However, it is not affected by leap seconds. |
| 208 | + pub struct TaiTime; |
| 209 | + |
| 210 | + impl Clock for TaiTime {} |
| 211 | + impl WallTime for TaiTime {} |
| 212 | + impl Now for TaiTime { |
| 213 | + fn now() -> Instant<Self> { |
| 214 | + // SAFETY: Always safe to call |
| 215 | + Instant::<Self>::new(unsafe { bindings::ktime_get_clocktai() }) |
| 216 | + } |
| 217 | + } |
| 218 | + |
| 219 | + /// A clock representing wall clock time. |
| 220 | + /// |
| 221 | + /// This clock is not monotonic and can be changed from userspace. |
| 222 | + pub struct RealTime; |
| 223 | + |
| 224 | + impl Clock for RealTime {} |
| 225 | + impl WallTime for RealTime {} |
| 226 | + impl Now for RealTime { |
| 227 | + fn now() -> Instant<Self> { |
| 228 | + // SAFETY: Always safe to call |
| 229 | + Instant::<Self>::new(unsafe { bindings::ktime_get_real() }) |
| 230 | + } |
| 231 | + } |
| 232 | +} |
0 commit comments