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