|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
| 2 | + |
| 3 | +//! Intrusive high resolution timers. |
| 4 | +//! |
| 5 | +//! Allows running timer callbacks without doing allocations at the time of |
| 6 | +//! starting the timer. For now, only one timer per type is allowed. |
| 7 | +//! |
| 8 | +//! # Vocabulary |
| 9 | +//! |
| 10 | +//! States: |
| 11 | +//! |
| 12 | +//! - Stopped: initialized but not started, or cancelled, or not restarted. |
| 13 | +//! - Started: initialized and started or restarted. |
| 14 | +//! - Running: executing the callback. |
| 15 | +//! |
| 16 | +//! Operations: |
| 17 | +//! |
| 18 | +//! * Start |
| 19 | +//! * Cancel |
| 20 | +//! * Restart |
| 21 | +//! |
| 22 | +//! Events: |
| 23 | +//! |
| 24 | +//! * Expire |
| 25 | +//! |
| 26 | +//! ## State Diagram |
| 27 | +//! |
| 28 | +//! ```text |
| 29 | +//! Return NoRestart |
| 30 | +//! +---------------------------------------------------------------------+ |
| 31 | +//! | | |
| 32 | +//! | | |
| 33 | +//! | | |
| 34 | +//! | Return Restart | |
| 35 | +//! | +------------------------+ | |
| 36 | +//! | | | | |
| 37 | +//! | | | | |
| 38 | +//! v v | | |
| 39 | +//! +-----------------+ Start +------------------+ +--------+-----+--+ |
| 40 | +//! | +---------------->| | | | |
| 41 | +//! Init | | | | Expire | | |
| 42 | +//! --------->| Stopped | | Started +---------->| Running | |
| 43 | +//! | | Cancel | | | | |
| 44 | +//! | |<----------------+ | | | |
| 45 | +//! +-----------------+ +---------------+--+ +-----------------+ |
| 46 | +//! ^ | |
| 47 | +//! | | |
| 48 | +//! +---------+ |
| 49 | +//! Restart |
| 50 | +//! ``` |
| 51 | +//! |
| 52 | +//! |
| 53 | +//! A timer is initialized in the **stopped** state. A stopped timer can be |
| 54 | +//! **started** by the `start` operation, with an **expiry** time. After the |
| 55 | +//! `start` operation, the timer is in the **started** state. When the timer |
| 56 | +//! **expires**, the timer enters the **running** state and the handler is |
| 57 | +//! executed. After the handler has finished executing, the timer may enter the |
| 58 | +//! **started* or **stopped** state, depending on the return value of the |
| 59 | +//! handler. A running timer can be **canceled** by the `cancel` operation. A |
| 60 | +//! timer that is cancelled enters the **stopped** state. |
| 61 | +//! |
| 62 | +//! A `cancel` or `restart` operation on a timer in the **running** state takes |
| 63 | +//! effect after the handler has finished executing and the timer has transitioned |
| 64 | +//! out of the **running** state. |
| 65 | +//! |
| 66 | +//! A `restart` operation on a timer in the **stopped** state is equivalent to a |
| 67 | +//! `start` operation. |
| 68 | +
|
| 69 | +use crate::{init::PinInit, prelude::*, time::Ktime, types::Opaque}; |
| 70 | +use core::marker::PhantomData; |
| 71 | + |
| 72 | +/// A timer backed by a C `struct hrtimer`. |
| 73 | +/// |
| 74 | +/// # Invariants |
| 75 | +/// |
| 76 | +/// * `self.timer` is initialized by `bindings::hrtimer_setup`. |
| 77 | +#[pin_data] |
| 78 | +#[repr(C)] |
| 79 | +pub struct HrTimer<T> { |
| 80 | + #[pin] |
| 81 | + timer: Opaque<bindings::hrtimer>, |
| 82 | + _t: PhantomData<T>, |
| 83 | +} |
| 84 | + |
| 85 | +// SAFETY: Ownership of an `HrTimer` can be moved to other threads and |
| 86 | +// used/dropped from there. |
| 87 | +unsafe impl<T> Send for HrTimer<T> {} |
| 88 | + |
| 89 | +// SAFETY: Timer operations are locked on C side, so it is safe to operate on a |
| 90 | +// timer from multiple threads |
| 91 | +unsafe impl<T> Sync for HrTimer<T> {} |
| 92 | + |
| 93 | +impl<T> HrTimer<T> { |
| 94 | + /// Return an initializer for a new timer instance. |
| 95 | + pub fn new() -> impl PinInit<Self> |
| 96 | + where |
| 97 | + T: HrTimerCallback, |
| 98 | + { |
| 99 | + pin_init!(Self { |
| 100 | + // INVARIANTS: We initialize `timer` with `hrtimer_setup` below. |
| 101 | + timer <- Opaque::ffi_init(move |place: *mut bindings::hrtimer| { |
| 102 | + // SAFETY: By design of `pin_init!`, `place` is a pointer to a |
| 103 | + // live allocation. hrtimer_setup will initialize `place` and |
| 104 | + // does not require `place` to be initialized prior to the call. |
| 105 | + unsafe { |
| 106 | + bindings::hrtimer_setup( |
| 107 | + place, |
| 108 | + Some(T::Pointer::run), |
| 109 | + bindings::CLOCK_MONOTONIC as i32, |
| 110 | + bindings::hrtimer_mode_HRTIMER_MODE_REL, |
| 111 | + ); |
| 112 | + } |
| 113 | + }), |
| 114 | + _t: PhantomData, |
| 115 | + }) |
| 116 | + } |
| 117 | + |
| 118 | + /// Get a pointer to the contained `bindings::hrtimer`. |
| 119 | + /// |
| 120 | + /// This function do not create any references. |
| 121 | + /// |
| 122 | + /// # Safety |
| 123 | + /// |
| 124 | + /// `ptr` must point to a live allocation of at least the size of `Self`. |
| 125 | + unsafe fn raw_get(ptr: *const Self) -> *mut bindings::hrtimer { |
| 126 | + // SAFETY: The field projection to `timer` does not go out of bounds, |
| 127 | + // because the caller of this function promises that `ptr` points to an |
| 128 | + // allocation of at least the size of `Self`. |
| 129 | + unsafe { Opaque::raw_get(core::ptr::addr_of!((*ptr).timer)) } |
| 130 | + } |
| 131 | + |
| 132 | + /// Cancel an initialized and potentially running timer. |
| 133 | + /// |
| 134 | + /// If the timer handler is running, this will block until the handler is |
| 135 | + /// finished. |
| 136 | + /// |
| 137 | + /// Users of the `HrTimer` API would not usually call this method directly. |
| 138 | + /// Instead they would use the safe [`HrTimerHandle::cancel`] on the handle |
| 139 | + /// returned when the timer was started. |
| 140 | + /// |
| 141 | + /// This function does not create any references. |
| 142 | + /// |
| 143 | + /// # Safety |
| 144 | + /// |
| 145 | + /// `self_ptr` must point to a valid `Self`. |
| 146 | + #[allow(dead_code)] |
| 147 | + pub(crate) unsafe fn raw_cancel(self_ptr: *const Self) -> bool { |
| 148 | + // SAFETY: timer_ptr points to an allocation of at least `HrTimer` size. |
| 149 | + let c_timer_ptr = unsafe { HrTimer::raw_get(self_ptr) }; |
| 150 | + |
| 151 | + // If the handler is running, this will wait for the handler to finish |
| 152 | + // before returning. |
| 153 | + // SAFETY: `c_timer_ptr` is initialized and valid. Synchronization is |
| 154 | + // handled on C side. |
| 155 | + unsafe { bindings::hrtimer_cancel(c_timer_ptr) != 0 } |
| 156 | + } |
| 157 | +} |
| 158 | + |
| 159 | +/// Implemented by pointer types that point to structs that embed a [`HrTimer`]. |
| 160 | +/// |
| 161 | +/// Target (pointee) must be [`Sync`] because timer callbacks happen in another |
| 162 | +/// thread of execution (hard or soft interrupt context). |
| 163 | +/// |
| 164 | +/// Starting a timer returns a [`HrTimerHandle`] that can be used to manipulate |
| 165 | +/// the timer. Note that it is OK to call the start function repeatedly, and |
| 166 | +/// that more than one [`HrTimerHandle`] associated with a [`HrTimerPointer`] may |
| 167 | +/// exist. A timer can be manipulated through any of the handles, and a handle |
| 168 | +/// may represent a cancelled timer. |
| 169 | +pub trait HrTimerPointer: Sync + Sized { |
| 170 | + /// A handle representing a started or restarted timer. |
| 171 | + /// |
| 172 | + /// If the timer is running or if the timer callback is executing when the |
| 173 | + /// handle is dropped, the drop method of [`HrTimerHandle`] should not return |
| 174 | + /// until the timer is stopped and the callback has completed. |
| 175 | + /// |
| 176 | + /// Note: When implementing this trait, consider that it is not unsafe to |
| 177 | + /// leak the handle. |
| 178 | + type TimerHandle: HrTimerHandle; |
| 179 | + |
| 180 | + /// Start the timer with expiry after `expires` time units. If the timer was |
| 181 | + /// already running, it is restarted with the new expiry time. |
| 182 | + fn start(self, expires: Ktime) -> Self::TimerHandle; |
| 183 | +} |
| 184 | + |
| 185 | +/// Implemented by [`HrTimerPointer`] implementers to give the C timer callback a |
| 186 | +/// function to call. |
| 187 | +// This is split from `HrTimerPointer` to make it easier to specify trait bounds. |
| 188 | +pub trait RawHrTimerCallback { |
| 189 | + /// This type is passed to [`HrTimerCallback::run`]. It may be a borrow of |
| 190 | + /// [`Self::CallbackTarget`], or it may be `Self::CallbackTarget` if the |
| 191 | + /// implementation can guarantee correct access (exclusive or shared |
| 192 | + /// depending on the type) to the target during timer handler execution. |
| 193 | + type CallbackTarget<'a>; |
| 194 | + |
| 195 | + /// Callback to be called from C when timer fires. |
| 196 | + /// |
| 197 | + /// # Safety |
| 198 | + /// |
| 199 | + /// Only to be called by C code in `hrtimer` subsystem. `ptr` must point to |
| 200 | + /// the `bindings::hrtimer` structure that was used to start the timer. |
| 201 | + unsafe extern "C" fn run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart; |
| 202 | +} |
| 203 | + |
| 204 | +/// Implemented by structs that can be the target of a timer callback. |
| 205 | +pub trait HrTimerCallback { |
| 206 | + /// The type whose [`RawHrTimerCallback::run`] method will be invoked when |
| 207 | + /// the timer expires. |
| 208 | + type Pointer<'a>: RawHrTimerCallback; |
| 209 | + |
| 210 | + /// Called by the timer logic when the timer fires. |
| 211 | + fn run(this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>) |
| 212 | + where |
| 213 | + Self: Sized; |
| 214 | +} |
| 215 | + |
| 216 | +/// A handle representing a potentially running timer. |
| 217 | +/// |
| 218 | +/// More than one handle representing the same timer might exist. |
| 219 | +/// |
| 220 | +/// # Safety |
| 221 | +/// |
| 222 | +/// When dropped, the timer represented by this handle must be cancelled, if it |
| 223 | +/// is running. If the timer handler is running when the handle is dropped, the |
| 224 | +/// drop method must wait for the handler to finish before returning. |
| 225 | +/// |
| 226 | +/// Note: One way to satisfy the safety requirement is to call `Self::cancel` in |
| 227 | +/// the drop implementation for `Self.` |
| 228 | +pub unsafe trait HrTimerHandle { |
| 229 | + /// Cancel the timer, if it is running. If the timer handler is running, block |
| 230 | + /// till the handler has finished. |
| 231 | + fn cancel(&mut self) -> bool; |
| 232 | +} |
| 233 | + |
| 234 | +/// Implemented by structs that contain timer nodes. |
| 235 | +/// |
| 236 | +/// Clients of the timer API would usually safely implement this trait by using |
| 237 | +/// the [`crate::impl_has_hr_timer`] macro. |
| 238 | +/// |
| 239 | +/// # Safety |
| 240 | +/// |
| 241 | +/// Implementers of this trait must ensure that the implementer has a [`HrTimer`] |
| 242 | +/// field at the offset specified by `OFFSET` and that all trait methods are |
| 243 | +/// implemented according to their documentation. |
| 244 | +/// |
| 245 | +/// [`impl_has_timer`]: crate::impl_has_timer |
| 246 | +pub unsafe trait HasHrTimer<T> { |
| 247 | + /// Offset of the [`HrTimer`] field within `Self` |
| 248 | + const OFFSET: usize; |
| 249 | + |
| 250 | + /// Return a pointer to the [`HrTimer`] within `Self`. |
| 251 | + /// |
| 252 | + /// This function does not create any references. |
| 253 | + /// |
| 254 | + /// # Safety |
| 255 | + /// |
| 256 | + /// `ptr` must point to a valid struct of type `Self`. |
| 257 | + unsafe fn raw_get_timer(ptr: *const Self) -> *const HrTimer<T> { |
| 258 | + // SAFETY: By the safety requirement of this trait, the trait |
| 259 | + // implementor will have a `HrTimer` field at the specified offset. |
| 260 | + unsafe { ptr.cast::<u8>().add(Self::OFFSET).cast::<HrTimer<T>>() } |
| 261 | + } |
| 262 | + |
| 263 | + /// Return a pointer to the struct that is embedding the [`HrTimer`] pointed |
| 264 | + /// to by `ptr`. |
| 265 | + /// |
| 266 | + /// This function does not create any references. |
| 267 | + /// |
| 268 | + /// # Safety |
| 269 | + /// |
| 270 | + /// `ptr` must point to a [`HrTimer<T>`] field in a struct of type `Self`. |
| 271 | + unsafe fn timer_container_of(ptr: *mut HrTimer<T>) -> *mut Self |
| 272 | + where |
| 273 | + Self: Sized, |
| 274 | + { |
| 275 | + // SAFETY: By the safety requirement of this function and the `HasHrTimer` |
| 276 | + // trait, the following expression will yield a pointer to the `Self` |
| 277 | + // containing the timer addressed by `ptr`. |
| 278 | + unsafe { ptr.cast::<u8>().sub(Self::OFFSET).cast::<Self>() } |
| 279 | + } |
| 280 | + |
| 281 | + /// Get pointer to embedded `bindings::hrtimer` struct. |
| 282 | + /// |
| 283 | + /// This function does not create any references. |
| 284 | + /// |
| 285 | + /// # Safety |
| 286 | + /// |
| 287 | + /// `self_ptr` must point to a valid `Self`. |
| 288 | + unsafe fn c_timer_ptr(self_ptr: *const Self) -> *const bindings::hrtimer { |
| 289 | + // SAFETY: `self_ptr` is a valid pointer to a `Self`. |
| 290 | + let timer_ptr = unsafe { Self::raw_get_timer(self_ptr) }; |
| 291 | + |
| 292 | + // SAFETY: timer_ptr points to an allocation of at least `HrTimer` size. |
| 293 | + unsafe { HrTimer::raw_get(timer_ptr) } |
| 294 | + } |
| 295 | + |
| 296 | + /// Start the timer contained in the `Self` pointed to by `self_ptr`. If |
| 297 | + /// it is already running it is removed and inserted. |
| 298 | + /// |
| 299 | + /// # Safety |
| 300 | + /// |
| 301 | + /// - `self_ptr` must point to a valid `Self`. |
| 302 | + /// - Caller must ensure that `self` lives until the timer fires or is |
| 303 | + /// canceled. |
| 304 | + unsafe fn start(self_ptr: *const Self, expires: Ktime) { |
| 305 | + // SAFETY: By function safety requirement, `self_ptr`is a valid `Self`. |
| 306 | + unsafe { |
| 307 | + bindings::hrtimer_start_range_ns( |
| 308 | + Self::c_timer_ptr(self_ptr).cast_mut(), |
| 309 | + expires.to_ns(), |
| 310 | + 0, |
| 311 | + bindings::hrtimer_mode_HRTIMER_MODE_REL, |
| 312 | + ); |
| 313 | + } |
| 314 | + } |
| 315 | +} |
| 316 | + |
| 317 | +/// Use to implement the [`HasHrTimer<T>`] trait. |
| 318 | +/// |
| 319 | +/// See [`module`] documentation for an example. |
| 320 | +/// |
| 321 | +/// [`module`]: crate::time::hrtimer |
| 322 | +#[macro_export] |
| 323 | +macro_rules! impl_has_hr_timer { |
| 324 | + ( |
| 325 | + impl$({$($generics:tt)*})? |
| 326 | + HasHrTimer<$timer_type:ty> |
| 327 | + for $self:ty |
| 328 | + { self.$field:ident } |
| 329 | + $($rest:tt)* |
| 330 | + ) => { |
| 331 | + // SAFETY: This implementation of `raw_get_timer` only compiles if the |
| 332 | + // field has the right type. |
| 333 | + unsafe impl$(<$($generics)*>)? $crate::time::hrtimer::HasHrTimer<$timer_type> for $self { |
| 334 | + const OFFSET: usize = ::core::mem::offset_of!(Self, $field) as usize; |
| 335 | + |
| 336 | + #[inline] |
| 337 | + unsafe fn raw_get_timer(ptr: *const Self) -> |
| 338 | + *const $crate::time::hrtimer::HrTimer<$timer_type> |
| 339 | + { |
| 340 | + // SAFETY: The caller promises that the pointer is not dangling. |
| 341 | + unsafe { |
| 342 | + ::core::ptr::addr_of!((*ptr).$field) |
| 343 | + } |
| 344 | + } |
| 345 | + } |
| 346 | + } |
| 347 | +} |
0 commit comments