Skip to content

Commit 4b07f88

Browse files
Andreas Hindborgfbq
authored andcommitted
rust: hrtimer: introduce hrtimer support
This patch adds support for intrusive use of the hrtimer system. For now, only one timer can be embedded in a Rust struct. The hrtimer Rust API is based on the intrusive style pattern introduced by the Rust workqueue API. Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org> Link: https://lore.kernel.org/r/20250224-hrtimer-v3-v6-12-rc2-v9-1-5bd3bf0ce6cc@kernel.org
1 parent beeb78d commit 4b07f88

File tree

3 files changed

+363
-0
lines changed

3 files changed

+363
-0
lines changed

kernel/time/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,16 @@ config CLOCKSOURCE_WATCHDOG_MAX_SKEW_US
211211

212212
endmenu
213213
endif
214+
215+
config RUST_HRTIMER
216+
bool "Enable Rust hrtimer API"
217+
depends on RUST
218+
default y
219+
help
220+
This option allows exclusion of the Rust hrtimer API from the build.
221+
This allows testing out changes to the C API without having to update
222+
the Rust abstractions during initial development.
223+
224+
Say Y if you wish to build the Rust hrtimer API.
225+
226+
Say N if you wish to exclude the Rust hrtimer API from the build.

rust/kernel/time.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
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+
#[cfg(CONFIG_RUST_HRTIMER)]
12+
pub mod hrtimer;
13+
1114
/// The number of nanoseconds per millisecond.
1215
pub const NSEC_PER_MSEC: i64 = bindings::NSEC_PER_MSEC as i64;
1316

rust/kernel/time/hrtimer.rs

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

Comments
 (0)