Skip to content

Commit 8a8afe9

Browse files
author
Andreas Hindborg
committed
rust: hrtimer: introduce hrtimer support
Add support for intrusive use of the hrtimer system. For now, only add support for embedding one timer per Rust struct. The hrtimer Rust API is based on the intrusive style pattern introduced by the Rust workqueue API. Acked-by: Frederic Weisbecker <frederic@kernel.org> Acked-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Benno Lossin <benno.lossin@proton.me> Reviewed-by: Tamir Duberstein <tamird@gmail.com> Reviewed-by: Lyude Paul <lyude@redhat.com> Link: https://lore.kernel.org/r/20250309-hrtimer-v3-v6-12-rc2-v12-1-73586e2bd5f1@kernel.org Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
1 parent a64dcfb commit 8a8afe9

File tree

2 files changed

+353
-0
lines changed

2 files changed

+353
-0
lines changed

rust/kernel/time.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
//! C header: [`include/linux/jiffies.h`](srctree/include/linux/jiffies.h).
99
//! C header: [`include/linux/ktime.h`](srctree/include/linux/ktime.h).
1010
11+
pub mod hrtimer;
12+
1113
/// The number of nanoseconds per millisecond.
1214
pub const NSEC_PER_MSEC: i64 = bindings::NSEC_PER_MSEC as i64;
1315

rust/kernel/time/hrtimer.rs

Lines changed: 351 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,351 @@
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

Comments
 (0)