2025-03-09 15:18:52 +00:00
|
|
|
// 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.
|
|
|
|
|
2025-06-10 13:28:21 +00:00
|
|
|
use super::{ClockSource, Delta, Instant};
|
2025-04-23 19:28:51 +00:00
|
|
|
use crate::{prelude::*, types::Opaque};
|
2025-03-09 15:18:52 +00:00
|
|
|
use core::marker::PhantomData;
|
2025-03-25 21:33:11 +00:00
|
|
|
use pin_init::PinInit;
|
2025-03-09 15:18:52 +00:00
|
|
|
|
2025-04-23 19:28:51 +00:00
|
|
|
/// A Rust wrapper around a `ktime_t`.
|
|
|
|
// NOTE: Ktime is going to be removed when hrtimer is converted to Instant/Delta.
|
|
|
|
#[repr(transparent)]
|
|
|
|
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
|
|
|
|
pub struct Ktime {
|
|
|
|
inner: bindings::ktime_t,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Ktime {
|
|
|
|
/// Returns the number of nanoseconds.
|
|
|
|
#[inline]
|
|
|
|
pub fn to_ns(self) -> i64 {
|
|
|
|
self.inner
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-03-09 15:18:52 +00:00
|
|
|
/// 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>,
|
2025-06-10 13:28:20 +00:00
|
|
|
mode: bindings::hrtimer_mode,
|
2025-03-09 15:18:52 +00:00
|
|
|
_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.
|
2025-06-10 13:28:20 +00:00
|
|
|
pub fn new<U: ClockSource, M: HrTimerMode>() -> impl PinInit<Self>
|
2025-03-09 15:18:52 +00:00
|
|
|
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),
|
2025-06-10 09:32:54 +00:00
|
|
|
U::ID,
|
2025-06-10 13:28:20 +00:00
|
|
|
M::C_MODE,
|
2025-03-09 15:18:52 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}),
|
2025-06-10 13:28:20 +00:00
|
|
|
mode: M::C_MODE,
|
2025-03-09 15:18:52 +00:00
|
|
|
_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;
|
|
|
|
}
|
|
|
|
|
2025-03-09 15:18:56 +00:00
|
|
|
/// 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;
|
|
|
|
}
|
|
|
|
|
2025-03-09 15:18:57 +00:00
|
|
|
/// 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 T
|
|
|
|
where
|
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-03-09 15:18:52 +00:00
|
|
|
/// 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.
|
2025-03-09 15:18:55 +00:00
|
|
|
fn run(this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>) -> HrTimerRestart
|
2025-03-09 15:18:52 +00:00
|
|
|
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,
|
2025-06-10 13:28:20 +00:00
|
|
|
(*Self::raw_get_timer(this)).mode,
|
2025-03-09 15:18:52 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-03-09 15:18:55 +00:00
|
|
|
/// Restart policy for timers.
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
|
|
|
#[repr(u32)]
|
|
|
|
pub enum HrTimerRestart {
|
|
|
|
/// Timer should not be restarted.
|
rust: workaround `bindgen` issue with forward references to `enum` types
`bindgen` currently generates the wrong type for an `enum` when there
is a forward reference to it. For instance:
enum E;
enum E { A };
generates:
pub const E_A: E = 0;
pub type E = i32;
instead of the expected:
pub const E_A: E = 0;
pub type E = ffi::c_uint;
The issue was reported to upstream `bindgen` [1].
Now, both GCC and Clang support silently these forward references to
`enum` types, unless `-Wpedantic` is passed, and it turns out that some
headers in the kernel depend on them.
Thus, depending on how the headers are included, which in turn may depend
on the kernel configuration or the architecture, we may get a different
type on the Rust side for a given C `enum`.
That can be quite confusing, to say the least, especially since
developers may only notice issues when building for other architectures
like in [2]. In particular, they may end up forcing a cast and adding
an `#[allow(clippy::unnecessary_cast)]` like it was done in commit
94e05a66ea3e ("rust: hrtimer: allow timer restart from timer handler"),
which isn't great.
Instead, let's have a section at the top of our `bindings_helper.h` that
`#include`s the headers with the affected types -- hopefully there are
not many cases and there is a single ordering that covers all cases.
This allows us to remove the cast and the `#[allow]`, thus keeping the
correct code in the source files. When the issue gets resolved in upstream
`bindgen` (and we update our minimum `bindgen` version), we can easily
remove this section at the top.
Link: https://github.com/rust-lang/rust-bindgen/issues/3179 [1]
Link: https://lore.kernel.org/rust-for-linux/87tt7md1s6.fsf@kernel.org/ [2]
Acked-by: Andreas Hindborg <a.hindborg@kernel.org>
Link: https://lore.kernel.org/r/20250325184309.97170-1-ojeda@kernel.org
[ Added extra paragraph on the comment to clarify that the workaround may
not be possible in some cases. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2025-03-25 18:43:09 +00:00
|
|
|
NoRestart = bindings::hrtimer_restart_HRTIMER_NORESTART,
|
2025-03-09 15:18:55 +00:00
|
|
|
/// Timer should be restarted.
|
rust: workaround `bindgen` issue with forward references to `enum` types
`bindgen` currently generates the wrong type for an `enum` when there
is a forward reference to it. For instance:
enum E;
enum E { A };
generates:
pub const E_A: E = 0;
pub type E = i32;
instead of the expected:
pub const E_A: E = 0;
pub type E = ffi::c_uint;
The issue was reported to upstream `bindgen` [1].
Now, both GCC and Clang support silently these forward references to
`enum` types, unless `-Wpedantic` is passed, and it turns out that some
headers in the kernel depend on them.
Thus, depending on how the headers are included, which in turn may depend
on the kernel configuration or the architecture, we may get a different
type on the Rust side for a given C `enum`.
That can be quite confusing, to say the least, especially since
developers may only notice issues when building for other architectures
like in [2]. In particular, they may end up forcing a cast and adding
an `#[allow(clippy::unnecessary_cast)]` like it was done in commit
94e05a66ea3e ("rust: hrtimer: allow timer restart from timer handler"),
which isn't great.
Instead, let's have a section at the top of our `bindings_helper.h` that
`#include`s the headers with the affected types -- hopefully there are
not many cases and there is a single ordering that covers all cases.
This allows us to remove the cast and the `#[allow]`, thus keeping the
correct code in the source files. When the issue gets resolved in upstream
`bindgen` (and we update our minimum `bindgen` version), we can easily
remove this section at the top.
Link: https://github.com/rust-lang/rust-bindgen/issues/3179 [1]
Link: https://lore.kernel.org/rust-for-linux/87tt7md1s6.fsf@kernel.org/ [2]
Acked-by: Andreas Hindborg <a.hindborg@kernel.org>
Link: https://lore.kernel.org/r/20250325184309.97170-1-ojeda@kernel.org
[ Added extra paragraph on the comment to clarify that the workaround may
not be possible in some cases. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2025-03-25 18:43:09 +00:00
|
|
|
Restart = bindings::hrtimer_restart_HRTIMER_RESTART,
|
2025-03-09 15:18:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl HrTimerRestart {
|
|
|
|
fn into_c(self) -> bindings::hrtimer_restart {
|
|
|
|
self as bindings::hrtimer_restart
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-06-10 13:28:21 +00:00
|
|
|
/// Time representations that can be used as expiration values in [`HrTimer`].
|
|
|
|
pub trait HrTimerExpires {
|
|
|
|
/// Converts the expiration time into a nanosecond representation.
|
|
|
|
///
|
|
|
|
/// This value corresponds to a raw ktime_t value, suitable for passing to kernel
|
|
|
|
/// timer functions. The interpretation (absolute vs relative) depends on the
|
|
|
|
/// associated [HrTimerMode] in use.
|
|
|
|
fn as_nanos(&self) -> i64;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<C: ClockSource> HrTimerExpires for Instant<C> {
|
|
|
|
#[inline]
|
|
|
|
fn as_nanos(&self) -> i64 {
|
|
|
|
Instant::<C>::as_nanos(self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl HrTimerExpires for Delta {
|
|
|
|
#[inline]
|
|
|
|
fn as_nanos(&self) -> i64 {
|
|
|
|
Delta::as_nanos(*self)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-03-09 15:19:02 +00:00
|
|
|
/// Operational mode of [`HrTimer`].
|
2025-06-10 13:28:20 +00:00
|
|
|
pub trait HrTimerMode {
|
|
|
|
/// The C representation of hrtimer mode.
|
|
|
|
const C_MODE: bindings::hrtimer_mode;
|
2025-06-10 13:28:21 +00:00
|
|
|
|
|
|
|
/// Type representing the clock source.
|
|
|
|
type Clock: ClockSource;
|
|
|
|
|
|
|
|
/// Type representing the expiration specification (absolute or relative time).
|
|
|
|
type Expires: HrTimerExpires;
|
2025-03-09 15:19:02 +00:00
|
|
|
}
|
|
|
|
|
2025-06-10 13:28:20 +00:00
|
|
|
/// Timer that expires at a fixed point in time.
|
2025-06-10 13:28:21 +00:00
|
|
|
pub struct AbsoluteMode<C: ClockSource>(PhantomData<C>);
|
2025-06-10 13:28:20 +00:00
|
|
|
|
2025-06-10 13:28:21 +00:00
|
|
|
impl<C: ClockSource> HrTimerMode for AbsoluteMode<C> {
|
2025-06-10 13:28:20 +00:00
|
|
|
const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS;
|
2025-06-10 13:28:21 +00:00
|
|
|
|
|
|
|
type Clock = C;
|
|
|
|
type Expires = Instant<C>;
|
2025-06-10 13:28:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Timer that expires after a delay from now.
|
2025-06-10 13:28:21 +00:00
|
|
|
pub struct RelativeMode<C: ClockSource>(PhantomData<C>);
|
2025-06-10 13:28:20 +00:00
|
|
|
|
2025-06-10 13:28:21 +00:00
|
|
|
impl<C: ClockSource> HrTimerMode for RelativeMode<C> {
|
2025-06-10 13:28:20 +00:00
|
|
|
const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL;
|
2025-06-10 13:28:21 +00:00
|
|
|
|
|
|
|
type Clock = C;
|
|
|
|
type Expires = Delta;
|
2025-06-10 13:28:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Timer with absolute expiration time, pinned to its current CPU.
|
2025-06-10 13:28:21 +00:00
|
|
|
pub struct AbsolutePinnedMode<C: ClockSource>(PhantomData<C>);
|
|
|
|
impl<C: ClockSource> HrTimerMode for AbsolutePinnedMode<C> {
|
2025-06-10 13:28:20 +00:00
|
|
|
const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS_PINNED;
|
2025-06-10 13:28:21 +00:00
|
|
|
|
|
|
|
type Clock = C;
|
|
|
|
type Expires = Instant<C>;
|
2025-06-10 13:28:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Timer with relative expiration time, pinned to its current CPU.
|
2025-06-10 13:28:21 +00:00
|
|
|
pub struct RelativePinnedMode<C: ClockSource>(PhantomData<C>);
|
|
|
|
impl<C: ClockSource> HrTimerMode for RelativePinnedMode<C> {
|
2025-06-10 13:28:20 +00:00
|
|
|
const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL_PINNED;
|
2025-06-10 13:28:21 +00:00
|
|
|
|
|
|
|
type Clock = C;
|
|
|
|
type Expires = Delta;
|
2025-06-10 13:28:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Timer with absolute expiration, handled in soft irq context.
|
2025-06-10 13:28:21 +00:00
|
|
|
pub struct AbsoluteSoftMode<C: ClockSource>(PhantomData<C>);
|
|
|
|
impl<C: ClockSource> HrTimerMode for AbsoluteSoftMode<C> {
|
2025-06-10 13:28:20 +00:00
|
|
|
const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS_SOFT;
|
2025-06-10 13:28:21 +00:00
|
|
|
|
|
|
|
type Clock = C;
|
|
|
|
type Expires = Instant<C>;
|
2025-06-10 13:28:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Timer with relative expiration, handled in soft irq context.
|
2025-06-10 13:28:21 +00:00
|
|
|
pub struct RelativeSoftMode<C: ClockSource>(PhantomData<C>);
|
|
|
|
impl<C: ClockSource> HrTimerMode for RelativeSoftMode<C> {
|
2025-06-10 13:28:20 +00:00
|
|
|
const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL_SOFT;
|
2025-06-10 13:28:21 +00:00
|
|
|
|
|
|
|
type Clock = C;
|
|
|
|
type Expires = Delta;
|
2025-06-10 13:28:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Timer with absolute expiration, pinned to CPU and handled in soft irq context.
|
2025-06-10 13:28:21 +00:00
|
|
|
pub struct AbsolutePinnedSoftMode<C: ClockSource>(PhantomData<C>);
|
|
|
|
impl<C: ClockSource> HrTimerMode for AbsolutePinnedSoftMode<C> {
|
2025-06-10 13:28:20 +00:00
|
|
|
const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS_PINNED_SOFT;
|
|
|
|
|
2025-06-10 13:28:21 +00:00
|
|
|
type Clock = C;
|
|
|
|
type Expires = Instant<C>;
|
|
|
|
}
|
2025-06-10 13:28:20 +00:00
|
|
|
|
2025-06-10 13:28:21 +00:00
|
|
|
/// Timer with absolute expiration, pinned to CPU and handled in soft irq context.
|
|
|
|
pub struct RelativePinnedSoftMode<C: ClockSource>(PhantomData<C>);
|
|
|
|
impl<C: ClockSource> HrTimerMode for RelativePinnedSoftMode<C> {
|
2025-06-10 13:28:20 +00:00
|
|
|
const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL_PINNED_SOFT;
|
2025-06-10 13:28:21 +00:00
|
|
|
|
|
|
|
type Clock = C;
|
|
|
|
type Expires = Delta;
|
2025-06-10 13:28:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Timer with absolute expiration, handled in hard irq context.
|
2025-06-10 13:28:21 +00:00
|
|
|
pub struct AbsoluteHardMode<C: ClockSource>(PhantomData<C>);
|
|
|
|
impl<C: ClockSource> HrTimerMode for AbsoluteHardMode<C> {
|
2025-06-10 13:28:20 +00:00
|
|
|
const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS_HARD;
|
2025-06-10 13:28:21 +00:00
|
|
|
|
|
|
|
type Clock = C;
|
|
|
|
type Expires = Instant<C>;
|
2025-06-10 13:28:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Timer with relative expiration, handled in hard irq context.
|
2025-06-10 13:28:21 +00:00
|
|
|
pub struct RelativeHardMode<C: ClockSource>(PhantomData<C>);
|
|
|
|
impl<C: ClockSource> HrTimerMode for RelativeHardMode<C> {
|
2025-06-10 13:28:20 +00:00
|
|
|
const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL_HARD;
|
2025-06-10 13:28:21 +00:00
|
|
|
|
|
|
|
type Clock = C;
|
|
|
|
type Expires = Delta;
|
2025-06-10 13:28:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Timer with absolute expiration, pinned to CPU and handled in hard irq context.
|
2025-06-10 13:28:21 +00:00
|
|
|
pub struct AbsolutePinnedHardMode<C: ClockSource>(PhantomData<C>);
|
|
|
|
impl<C: ClockSource> HrTimerMode for AbsolutePinnedHardMode<C> {
|
2025-06-10 13:28:20 +00:00
|
|
|
const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS_PINNED_HARD;
|
2025-06-10 13:28:21 +00:00
|
|
|
|
|
|
|
type Clock = C;
|
|
|
|
type Expires = Instant<C>;
|
2025-06-10 13:28:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Timer with relative expiration, pinned to CPU and handled in hard irq context.
|
2025-06-10 13:28:21 +00:00
|
|
|
pub struct RelativePinnedHardMode<C: ClockSource>(PhantomData<C>);
|
|
|
|
impl<C: ClockSource> HrTimerMode for RelativePinnedHardMode<C> {
|
2025-06-10 13:28:20 +00:00
|
|
|
const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL_PINNED_HARD;
|
2025-06-10 13:28:21 +00:00
|
|
|
|
|
|
|
type Clock = C;
|
|
|
|
type Expires = Delta;
|
2025-03-09 15:19:02 +00:00
|
|
|
}
|
|
|
|
|
2025-03-09 15:18:52 +00:00
|
|
|
/// 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]
|
|
|
|
unsafe fn timer_container_of(
|
|
|
|
ptr: *mut $crate::time::hrtimer::HrTimer<$timer_type>,
|
|
|
|
) -> *mut Self {
|
|
|
|
// SAFETY: As per the safety requirement of this function, `ptr`
|
|
|
|
// is pointing inside a `$timer_type`.
|
2025-06-06 02:05:05 +00:00
|
|
|
unsafe { ::kernel::container_of!(ptr, $timer_type, $field) }
|
2025-03-09 15:18:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2025-03-09 15:18:54 +00:00
|
|
|
|
|
|
|
mod arc;
|
|
|
|
pub use arc::ArcHrTimerHandle;
|
2025-03-09 15:18:58 +00:00
|
|
|
mod pin;
|
|
|
|
pub use pin::PinHrTimerHandle;
|
2025-03-09 15:18:59 +00:00
|
|
|
mod pin_mut;
|
|
|
|
pub use pin_mut::PinMutHrTimerHandle;
|
2025-03-09 15:19:01 +00:00
|
|
|
// `box` is a reserved keyword, so prefix with `t` for timer
|
|
|
|
mod tbox;
|
|
|
|
pub use tbox::BoxHrTimerHandle;
|