520 lines · 20.2 KB · Rust
RawDownload
// SPDX-License-Identifier: GPL-2.0 //! Intrusive high resolution timers.//!//! Allows running timer callbacks without doing allocations at the time of//! starting the timer. For now, only one timer per type is allowed.//!//! # Vocabulary//!//! States://!//! - Stopped: initialized but not started, or cancelled, or not restarted.//! - Started: initialized and started or restarted.//! - Running: executing the callback.//!//! Operations://!//! * Start//! * Cancel//! * Restart//!//! Events://!//! * Expire//!//! ## State Diagram//!//! ```text//!                                                   Return NoRestart//!                       +---------------------------------------------------------------------+//!                       |                                                                     |//!                       |                                                                     |//!                       |                                                                     |//!                       |                                         Return Restart              |//!                       |                                      +------------------------+     |//!                       |                                      |                        |     |//!                       |                                      |                        |     |//!                       v                                      v                        |     |//!           +-----------------+      Start      +------------------+           +--------+-----+--+//!           |                 +---------------->|                  |           |                 |//! Init      |                 |                 |                  |  Expire   |                 |//! --------->|    Stopped      |                 |      Started     +---------->|     Running     |//!           |                 |     Cancel      |                  |           |                 |//!           |                 |<----------------+                  |           |                 |//!           +-----------------+                 +---------------+--+           +-----------------+//!                                                     ^         |//!                                                     |         |//!                                                     +---------+//!                                                      Restart//! ```//!//!//! A timer is initialized in the **stopped** state. A stopped timer can be//! **started** by the `start` operation, with an **expiry** time. After the//! `start` operation, the timer is in the **started** state. When the timer//! **expires**, the timer enters the **running** state and the handler is//! executed. After the handler has returned, the timer may enter the//! **started* or **stopped** state, depending on the return value of the//! handler. A timer in the **started** or **running** state may be **canceled**//! by the `cancel` operation. A timer that is cancelled enters the **stopped**//! state.//!//! A `cancel` or `restart` operation on a timer in the **running** state takes//! effect after the handler has returned and the timer has transitioned//! out of the **running** state.//!//! A `restart` operation on a timer in the **stopped** state is equivalent to a//! `start` operation. use super::ClockId;use crate::{prelude::*, time::Ktime, types::Opaque};use core::marker::PhantomData;use pin_init::PinInit; /// A timer backed by a C `struct hrtimer`.////// # Invariants////// * `self.timer` is initialized by `bindings::hrtimer_setup`.#[pin_data]#[repr(C)]pub struct HrTimer<T> {    #[pin]    timer: Opaque<bindings::hrtimer>,    mode: HrTimerMode,    _t: PhantomData<T>,} // SAFETY: Ownership of an `HrTimer` can be moved to other threads and// used/dropped from there.unsafe impl<T> Send for HrTimer<T> {} // SAFETY: Timer operations are locked on the C side, so it is safe to operate// on a timer from multiple threads.unsafe impl<T> Sync for HrTimer<T> {} impl<T> HrTimer<T> {    /// Return an initializer for a new timer instance.    pub fn new(mode: HrTimerMode, clock: ClockId) -> impl PinInit<Self>    where        T: HrTimerCallback,    {        pin_init!(Self {            // INVARIANT: We initialize `timer` with `hrtimer_setup` below.            timer <- Opaque::ffi_init(move |place: *mut bindings::hrtimer| {                // SAFETY: By design of `pin_init!`, `place` is a pointer to a                // live allocation. hrtimer_setup will initialize `place` and                // does not require `place` to be initialized prior to the call.                unsafe {                    bindings::hrtimer_setup(                        place,                        Some(T::Pointer::run),                        clock.into_c(),                        mode.into_c(),                    );                }            }),            mode: mode,            _t: PhantomData,        })    }     /// Get a pointer to the contained `bindings::hrtimer`.    ///    /// This function is useful to get access to the value without creating    /// intermediate references.    ///    /// # Safety    ///    /// `this` must point to a live allocation of at least the size of `Self`.    unsafe fn raw_get(this: *const Self) -> *mut bindings::hrtimer {        // SAFETY: The field projection to `timer` does not go out of bounds,        // because the caller of this function promises that `this` points to an        // allocation of at least the size of `Self`.        unsafe { Opaque::raw_get(core::ptr::addr_of!((*this).timer)) }    }     /// Cancel an initialized and potentially running timer.    ///    /// If the timer handler is running, this function will block until the    /// handler returns.    ///    /// Note that the timer might be started by a concurrent start operation. If    /// so, the timer might not be in the **stopped** state when this function    /// returns.    ///    /// Users of the `HrTimer` API would not usually call this method directly.    /// Instead they would use the safe [`HrTimerHandle::cancel`] on the handle    /// returned when the timer was started.    ///    /// This function is useful to get access to the value without creating    /// intermediate references.    ///    /// # Safety    ///    /// `this` must point to a valid `Self`.    pub(crate) unsafe fn raw_cancel(this: *const Self) -> bool {        // SAFETY: `this` points to an allocation of at least `HrTimer` size.        let c_timer_ptr = unsafe { HrTimer::raw_get(this) };         // If the handler is running, this will wait for the handler to return        // before returning.        // SAFETY: `c_timer_ptr` is initialized and valid. Synchronization is        // handled on the C side.        unsafe { bindings::hrtimer_cancel(c_timer_ptr) != 0 }    }} /// Implemented by pointer types that point to structs that contain a [`HrTimer`].////// `Self` must be [`Sync`] because it is passed to timer callbacks in another/// thread of execution (hard or soft interrupt context).////// Starting a timer returns a [`HrTimerHandle`] that can be used to manipulate/// the timer. Note that it is OK to call the start function repeatedly, and/// that more than one [`HrTimerHandle`] associated with a [`HrTimerPointer`] may/// exist. A timer can be manipulated through any of the handles, and a handle/// may represent a cancelled timer.pub trait HrTimerPointer: Sync + Sized {    /// A handle representing a started or restarted timer.    ///    /// If the timer is running or if the timer callback is executing when the    /// handle is dropped, the drop method of [`HrTimerHandle`] should not return    /// until the timer is stopped and the callback has completed.    ///    /// Note: When implementing this trait, consider that it is not unsafe to    /// leak the handle.    type TimerHandle: HrTimerHandle;     /// Start the timer with expiry after `expires` time units. If the timer was    /// already running, it is restarted with the new expiry time.    fn start(self, expires: Ktime) -> Self::TimerHandle;} /// Unsafe version of [`HrTimerPointer`] for situations where leaking the/// [`HrTimerHandle`] returned by `start` would be unsound. This is the case for/// stack allocated timers.////// Typical implementers are pinned references such as [`Pin<&T>`].////// # Safety////// Implementers of this trait must ensure that instances of types implementing/// [`UnsafeHrTimerPointer`] outlives any associated [`HrTimerPointer::TimerHandle`]/// instances.pub unsafe trait UnsafeHrTimerPointer: Sync + Sized {    /// A handle representing a running timer.    ///    /// # Safety    ///    /// If the timer is running, or if the timer callback is executing when the    /// handle is dropped, the drop method of [`Self::TimerHandle`] must not return    /// until the timer is stopped and the callback has completed.    type TimerHandle: HrTimerHandle;     /// Start the timer after `expires` time units. If the timer was already    /// running, it is restarted at the new expiry time.    ///    /// # Safety    ///    /// Caller promises keep the timer structure alive until the timer is dead.    /// Caller can ensure this by not leaking the returned [`Self::TimerHandle`].    unsafe fn start(self, expires: Ktime) -> Self::TimerHandle;} /// A trait for stack allocated timers.////// # Safety////// Implementers must ensure that `start_scoped` does not return until the/// timer is dead and the timer handler is not running.pub unsafe trait ScopedHrTimerPointer {    /// Start the timer to run after `expires` time units and immediately    /// after call `f`. When `f` returns, the timer is cancelled.    fn start_scoped<T, F>(self, expires: Ktime, f: F) -> T    where        F: FnOnce() -> T;} // SAFETY: By the safety requirement of [`UnsafeHrTimerPointer`], dropping the// handle returned by [`UnsafeHrTimerPointer::start`] ensures that the timer is// killed.unsafe impl<T> ScopedHrTimerPointer for Twhere    T: UnsafeHrTimerPointer,{    fn start_scoped<U, F>(self, expires: Ktime, f: F) -> U    where        F: FnOnce() -> U,    {        // SAFETY: We drop the timer handle below before returning.        let handle = unsafe { UnsafeHrTimerPointer::start(self, expires) };        let t = f();        drop(handle);        t    }} /// Implemented by [`HrTimerPointer`] implementers to give the C timer callback a/// function to call.// This is split from `HrTimerPointer` to make it easier to specify trait bounds.pub trait RawHrTimerCallback {    /// Type of the parameter passed to [`HrTimerCallback::run`]. It may be    /// [`Self`], or a pointer type derived from [`Self`].    type CallbackTarget<'a>;     /// Callback to be called from C when timer fires.    ///    /// # Safety    ///    /// Only to be called by C code in the `hrtimer` subsystem. `this` must point    /// to the `bindings::hrtimer` structure that was used to start the timer.    unsafe extern "C" fn run(this: *mut bindings::hrtimer) -> bindings::hrtimer_restart;} /// Implemented by structs that can be the target of a timer callback.pub trait HrTimerCallback {    /// The type whose [`RawHrTimerCallback::run`] method will be invoked when    /// the timer expires.    type Pointer<'a>: RawHrTimerCallback;     /// Called by the timer logic when the timer fires.    fn run(this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>) -> HrTimerRestart    where        Self: Sized;} /// A handle representing a potentially running timer.////// More than one handle representing the same timer might exist.////// # Safety////// When dropped, the timer represented by this handle must be cancelled, if it/// is running. If the timer handler is running when the handle is dropped, the/// drop method must wait for the handler to return before returning.////// Note: One way to satisfy the safety requirement is to call `Self::cancel` in/// the drop implementation for `Self.`pub unsafe trait HrTimerHandle {    /// Cancel the timer. If the timer is in the running state, block till the    /// handler has returned.    ///    /// Note that the timer might be started by a concurrent start operation. If    /// so, the timer might not be in the **stopped** state when this function    /// returns.    fn cancel(&mut self) -> bool;} /// Implemented by structs that contain timer nodes.////// Clients of the timer API would usually safely implement this trait by using/// the [`crate::impl_has_hr_timer`] macro.////// # Safety////// Implementers of this trait must ensure that the implementer has a/// [`HrTimer`] field and that all trait methods are implemented according to/// their documentation. All the methods of this trait must operate on the same/// field.pub unsafe trait HasHrTimer<T> {    /// Return a pointer to the [`HrTimer`] within `Self`.    ///    /// This function is useful to get access to the value without creating    /// intermediate references.    ///    /// # Safety    ///    /// `this` must be a valid pointer.    unsafe fn raw_get_timer(this: *const Self) -> *const HrTimer<T>;     /// Return a pointer to the struct that is containing the [`HrTimer`] pointed    /// to by `ptr`.    ///    /// This function is useful to get access to the value without creating    /// intermediate references.    ///    /// # Safety    ///    /// `ptr` must point to a [`HrTimer<T>`] field in a struct of type `Self`.    unsafe fn timer_container_of(ptr: *mut HrTimer<T>) -> *mut Self    where        Self: Sized;     /// Get pointer to the contained `bindings::hrtimer` struct.    ///    /// This function is useful to get access to the value without creating    /// intermediate references.    ///    /// # Safety    ///    /// `this` must be a valid pointer.    unsafe fn c_timer_ptr(this: *const Self) -> *const bindings::hrtimer {        // SAFETY: `this` is a valid pointer to a `Self`.        let timer_ptr = unsafe { Self::raw_get_timer(this) };         // SAFETY: timer_ptr points to an allocation of at least `HrTimer` size.        unsafe { HrTimer::raw_get(timer_ptr) }    }     /// Start the timer contained in the `Self` pointed to by `self_ptr`. If    /// it is already running it is removed and inserted.    ///    /// # Safety    ///    /// - `this` must point to a valid `Self`.    /// - Caller must ensure that the pointee of `this` lives until the timer    ///   fires or is canceled.    unsafe fn start(this: *const Self, expires: Ktime) {        // SAFETY: By function safety requirement, `this` is a valid `Self`.        unsafe {            bindings::hrtimer_start_range_ns(                Self::c_timer_ptr(this).cast_mut(),                expires.to_ns(),                0,                (*Self::raw_get_timer(this)).mode.into_c(),            );        }    }} /// Restart policy for timers.#[derive(Copy, Clone, PartialEq, Eq, Debug)]#[repr(u32)]pub enum HrTimerRestart {    /// Timer should not be restarted.    #[allow(clippy::unnecessary_cast)]    NoRestart = bindings::hrtimer_restart_HRTIMER_NORESTART as u32,    /// Timer should be restarted.    #[allow(clippy::unnecessary_cast)]    Restart = bindings::hrtimer_restart_HRTIMER_RESTART as u32,} impl HrTimerRestart {    fn into_c(self) -> bindings::hrtimer_restart {        self as bindings::hrtimer_restart    }} /// Operational mode of [`HrTimer`].// NOTE: Some of these have the same encoding on the C side, so we keep// `repr(Rust)` and convert elsewhere.#[derive(Clone, Copy, PartialEq, Eq, Debug)]pub enum HrTimerMode {    /// Timer expires at the given expiration time.    Absolute,    /// Timer expires after the given expiration time interpreted as a duration from now.    Relative,    /// Timer does not move between CPU cores.    Pinned,    /// Timer handler is executed in soft irq context.    Soft,    /// Timer handler is executed in hard irq context.    Hard,    /// Timer expires at the given expiration time.    /// Timer does not move between CPU cores.    AbsolutePinned,    /// Timer expires after the given expiration time interpreted as a duration from now.    /// Timer does not move between CPU cores.    RelativePinned,    /// Timer expires at the given expiration time.    /// Timer handler is executed in soft irq context.    AbsoluteSoft,    /// Timer expires after the given expiration time interpreted as a duration from now.    /// Timer handler is executed in soft irq context.    RelativeSoft,    /// Timer expires at the given expiration time.    /// Timer does not move between CPU cores.    /// Timer handler is executed in soft irq context.    AbsolutePinnedSoft,    /// Timer expires after the given expiration time interpreted as a duration from now.    /// Timer does not move between CPU cores.    /// Timer handler is executed in soft irq context.    RelativePinnedSoft,    /// Timer expires at the given expiration time.    /// Timer handler is executed in hard irq context.    AbsoluteHard,    /// Timer expires after the given expiration time interpreted as a duration from now.    /// Timer handler is executed in hard irq context.    RelativeHard,    /// Timer expires at the given expiration time.    /// Timer does not move between CPU cores.    /// Timer handler is executed in hard irq context.    AbsolutePinnedHard,    /// Timer expires after the given expiration time interpreted as a duration from now.    /// Timer does not move between CPU cores.    /// Timer handler is executed in hard irq context.    RelativePinnedHard,} impl HrTimerMode {    fn into_c(self) -> bindings::hrtimer_mode {        use bindings::*;        match self {            HrTimerMode::Absolute => hrtimer_mode_HRTIMER_MODE_ABS,            HrTimerMode::Relative => hrtimer_mode_HRTIMER_MODE_REL,            HrTimerMode::Pinned => hrtimer_mode_HRTIMER_MODE_PINNED,            HrTimerMode::Soft => hrtimer_mode_HRTIMER_MODE_SOFT,            HrTimerMode::Hard => hrtimer_mode_HRTIMER_MODE_HARD,            HrTimerMode::AbsolutePinned => hrtimer_mode_HRTIMER_MODE_ABS_PINNED,            HrTimerMode::RelativePinned => hrtimer_mode_HRTIMER_MODE_REL_PINNED,            HrTimerMode::AbsoluteSoft => hrtimer_mode_HRTIMER_MODE_ABS_SOFT,            HrTimerMode::RelativeSoft => hrtimer_mode_HRTIMER_MODE_REL_SOFT,            HrTimerMode::AbsolutePinnedSoft => hrtimer_mode_HRTIMER_MODE_ABS_PINNED_SOFT,            HrTimerMode::RelativePinnedSoft => hrtimer_mode_HRTIMER_MODE_REL_PINNED_SOFT,            HrTimerMode::AbsoluteHard => hrtimer_mode_HRTIMER_MODE_ABS_HARD,            HrTimerMode::RelativeHard => hrtimer_mode_HRTIMER_MODE_REL_HARD,            HrTimerMode::AbsolutePinnedHard => hrtimer_mode_HRTIMER_MODE_ABS_PINNED_HARD,            HrTimerMode::RelativePinnedHard => hrtimer_mode_HRTIMER_MODE_REL_PINNED_HARD,        }    }} /// Use to implement the [`HasHrTimer<T>`] trait.////// See [`module`] documentation for an example.////// [`module`]: crate::time::hrtimer#[macro_export]macro_rules! impl_has_hr_timer {    (        impl$({$($generics:tt)*})?            HasHrTimer<$timer_type:ty>            for $self:ty        { self.$field:ident }        $($rest:tt)*    ) => {        // SAFETY: This implementation of `raw_get_timer` only compiles if the        // field has the right type.        unsafe impl$(<$($generics)*>)? $crate::time::hrtimer::HasHrTimer<$timer_type> for $self {             #[inline]            unsafe fn raw_get_timer(                this: *const Self,            ) -> *const $crate::time::hrtimer::HrTimer<$timer_type> {                // SAFETY: The caller promises that the pointer is not dangling.                unsafe { ::core::ptr::addr_of!((*this).$field) }            }             #[inline]

Lines 1–500 of 520.