hrtimer: add usage examples to documentation

Add documentation examples showing various ways to use hrtimers:

- Box-allocated timers with shared state in Arc.
- Arc-allocated timers.
- Stack-based timers for scoped usage.
- Mutable stack-based timers with shared state.

Tested-by: Daniel Almeida <daniel.almeida@collabora.com>
Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Link: https://msgid.link/20260219-hrtimer-examples-v6-19-rc1-v2-1-810cc06ca9f6@kernel.org
Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
This commit is contained in:
Andreas Hindborg
2026-02-19 12:57:45 +01:00
parent 67b598db7e
commit ddb1444d33

View File

@@ -66,6 +66,342 @@
//!
//! A `restart` operation on a timer in the **stopped** state is equivalent to a
//! `start` operation.
//!
//! When a type implements both `HrTimerPointer` and `Clone`, it is possible to
//! issue the `start` operation while the timer is in the **started** state. In
//! this case the `start` operation is equivalent to the `restart` operation.
//!
//! # Examples
//!
//! ## Using an intrusive timer living in a [`Box`]
//!
//! ```
//! # use kernel::{
//! # alloc::flags,
//! # impl_has_hr_timer,
//! # prelude::*,
//! # sync::{
//! # atomic::{ordering, Atomic},
//! # completion::Completion,
//! # Arc,
//! # },
//! # time::{
//! # hrtimer::{
//! # RelativeMode, HrTimer, HrTimerCallback, HrTimerPointer,
//! # HrTimerRestart, HrTimerCallbackContext
//! # },
//! # Delta, Monotonic,
//! # },
//! # };
//!
//! #[pin_data]
//! struct Shared {
//! #[pin]
//! flag: Atomic<u64>,
//! #[pin]
//! cond: Completion,
//! }
//!
//! impl Shared {
//! fn new() -> impl PinInit<Self> {
//! pin_init!(Self {
//! flag <- Atomic::new(0),
//! cond <- Completion::new(),
//! })
//! }
//! }
//!
//! #[pin_data]
//! struct BoxIntrusiveHrTimer {
//! #[pin]
//! timer: HrTimer<Self>,
//! shared: Arc<Shared>,
//! }
//!
//! impl BoxIntrusiveHrTimer {
//! fn new() -> impl PinInit<Self, kernel::error::Error> {
//! try_pin_init!(Self {
//! timer <- HrTimer::new(),
//! shared: Arc::pin_init(Shared::new(), flags::GFP_KERNEL)?,
//! })
//! }
//! }
//!
//! impl HrTimerCallback for BoxIntrusiveHrTimer {
//! type Pointer<'a> = Pin<KBox<Self>>;
//!
//! fn run(this: Pin<&mut Self>, _ctx: HrTimerCallbackContext<'_, Self>) -> HrTimerRestart {
//! pr_info!("Timer called\n");
//!
//! let flag = this.shared.flag.fetch_add(1, ordering::Full);
//! this.shared.cond.complete_all();
//!
//! if flag == 4 {
//! HrTimerRestart::NoRestart
//! } else {
//! HrTimerRestart::Restart
//! }
//! }
//! }
//!
//! impl_has_hr_timer! {
//! impl HasHrTimer<Self> for BoxIntrusiveHrTimer {
//! mode: RelativeMode<Monotonic>, field: self.timer
//! }
//! }
//!
//! let has_timer = Box::pin_init(BoxIntrusiveHrTimer::new(), GFP_KERNEL)?;
//! let shared = has_timer.shared.clone();
//! let _handle = has_timer.start(Delta::from_micros(200));
//!
//! while shared.flag.load(ordering::Relaxed) != 5 {
//! shared.cond.wait_for_completion();
//! }
//!
//! pr_info!("Counted to 5\n");
//! # Ok::<(), kernel::error::Error>(())
//! ```
//!
//! ## Using an intrusive timer in an [`Arc`]
//!
//! ```
//! # use kernel::{
//! # alloc::flags,
//! # impl_has_hr_timer,
//! # prelude::*,
//! # sync::{
//! # atomic::{ordering, Atomic},
//! # completion::Completion,
//! # Arc, ArcBorrow,
//! # },
//! # time::{
//! # hrtimer::{
//! # RelativeMode, HrTimer, HrTimerCallback, HrTimerPointer, HrTimerRestart,
//! # HasHrTimer, HrTimerCallbackContext
//! # },
//! # Delta, Monotonic,
//! # },
//! # };
//!
//! #[pin_data]
//! struct ArcIntrusiveHrTimer {
//! #[pin]
//! timer: HrTimer<Self>,
//! #[pin]
//! flag: Atomic<u64>,
//! #[pin]
//! cond: Completion,
//! }
//!
//! impl ArcIntrusiveHrTimer {
//! fn new() -> impl PinInit<Self> {
//! pin_init!(Self {
//! timer <- HrTimer::new(),
//! flag <- Atomic::new(0),
//! cond <- Completion::new(),
//! })
//! }
//! }
//!
//! impl HrTimerCallback for ArcIntrusiveHrTimer {
//! type Pointer<'a> = Arc<Self>;
//!
//! fn run(
//! this: ArcBorrow<'_, Self>,
//! _ctx: HrTimerCallbackContext<'_, Self>,
//! ) -> HrTimerRestart {
//! pr_info!("Timer called\n");
//!
//! let flag = this.flag.fetch_add(1, ordering::Full);
//! this.cond.complete_all();
//!
//! if flag == 4 {
//! HrTimerRestart::NoRestart
//! } else {
//! HrTimerRestart::Restart
//! }
//! }
//! }
//!
//! impl_has_hr_timer! {
//! impl HasHrTimer<Self> for ArcIntrusiveHrTimer {
//! mode: RelativeMode<Monotonic>, field: self.timer
//! }
//! }
//!
//! let has_timer = Arc::pin_init(ArcIntrusiveHrTimer::new(), GFP_KERNEL)?;
//! let _handle = has_timer.clone().start(Delta::from_micros(200));
//!
//! while has_timer.flag.load(ordering::Relaxed) != 5 {
//! has_timer.cond.wait_for_completion();
//! }
//!
//! pr_info!("Counted to 5\n");
//! # Ok::<(), kernel::error::Error>(())
//! ```
//!
//! ## Using a stack-based timer
//!
//! ```
//! # use kernel::{
//! # impl_has_hr_timer,
//! # prelude::*,
//! # sync::{
//! # atomic::{ordering, Atomic},
//! # completion::Completion,
//! # },
//! # time::{
//! # hrtimer::{
//! # ScopedHrTimerPointer, HrTimer, HrTimerCallback, HrTimerPointer, HrTimerRestart,
//! # HasHrTimer, RelativeMode, HrTimerCallbackContext
//! # },
//! # Delta, Monotonic,
//! # },
//! # };
//! # use pin_init::stack_pin_init;
//!
//! #[pin_data]
//! struct IntrusiveHrTimer {
//! #[pin]
//! timer: HrTimer<Self>,
//! #[pin]
//! flag: Atomic<u64>,
//! #[pin]
//! cond: Completion,
//! }
//!
//! impl IntrusiveHrTimer {
//! fn new() -> impl PinInit<Self> {
//! pin_init!(Self {
//! timer <- HrTimer::new(),
//! flag <- Atomic::new(0),
//! cond <- Completion::new(),
//! })
//! }
//! }
//!
//! impl HrTimerCallback for IntrusiveHrTimer {
//! type Pointer<'a> = Pin<&'a Self>;
//!
//! fn run(this: Pin<&Self>, _ctx: HrTimerCallbackContext<'_, Self>) -> HrTimerRestart {
//! pr_info!("Timer called\n");
//!
//! this.flag.store(1, ordering::Release);
//! this.cond.complete_all();
//!
//! HrTimerRestart::NoRestart
//! }
//! }
//!
//! impl_has_hr_timer! {
//! impl HasHrTimer<Self> for IntrusiveHrTimer {
//! mode: RelativeMode<Monotonic>, field: self.timer
//! }
//! }
//!
//! stack_pin_init!( let has_timer = IntrusiveHrTimer::new() );
//! has_timer.as_ref().start_scoped(Delta::from_micros(200), || {
//! while has_timer.flag.load(ordering::Relaxed) != 1 {
//! has_timer.cond.wait_for_completion();
//! }
//! });
//!
//! pr_info!("Flag raised\n");
//! # Ok::<(), kernel::error::Error>(())
//! ```
//!
//! ## Using a mutable stack-based timer
//!
//! ```
//! # use kernel::{
//! # alloc::flags,
//! # impl_has_hr_timer,
//! # prelude::*,
//! # sync::{
//! # atomic::{ordering, Atomic},
//! # completion::Completion,
//! # Arc,
//! # },
//! # time::{
//! # hrtimer::{
//! # ScopedHrTimerPointer, HrTimer, HrTimerCallback, HrTimerPointer, HrTimerRestart,
//! # HasHrTimer, RelativeMode, HrTimerCallbackContext
//! # },
//! # Delta, Monotonic,
//! # },
//! # };
//! # use pin_init::stack_try_pin_init;
//!
//! #[pin_data]
//! struct Shared {
//! #[pin]
//! flag: Atomic<u64>,
//! #[pin]
//! cond: Completion,
//! }
//!
//! impl Shared {
//! fn new() -> impl PinInit<Self> {
//! pin_init!(Self {
//! flag <- Atomic::new(0),
//! cond <- Completion::new(),
//! })
//! }
//! }
//!
//! #[pin_data]
//! struct IntrusiveHrTimer {
//! #[pin]
//! timer: HrTimer<Self>,
//! shared: Arc<Shared>,
//! }
//!
//! impl IntrusiveHrTimer {
//! fn new() -> impl PinInit<Self, kernel::error::Error> {
//! try_pin_init!(Self {
//! timer <- HrTimer::new(),
//! shared: Arc::pin_init(Shared::new(), flags::GFP_KERNEL)?,
//! })
//! }
//! }
//!
//! impl HrTimerCallback for IntrusiveHrTimer {
//! type Pointer<'a> = Pin<&'a mut Self>;
//!
//! fn run(this: Pin<&mut Self>, _ctx: HrTimerCallbackContext<'_, Self>) -> HrTimerRestart {
//! pr_info!("Timer called\n");
//!
//! let flag = this.shared.flag.fetch_add(1, ordering::Full);
//! this.shared.cond.complete_all();
//!
//! if flag == 4 {
//! HrTimerRestart::NoRestart
//! } else {
//! HrTimerRestart::Restart
//! }
//! }
//! }
//!
//! impl_has_hr_timer! {
//! impl HasHrTimer<Self> for IntrusiveHrTimer {
//! mode: RelativeMode<Monotonic>, field: self.timer
//! }
//! }
//!
//! stack_try_pin_init!( let has_timer =? IntrusiveHrTimer::new() );
//! let shared = has_timer.shared.clone();
//!
//! has_timer.as_mut().start_scoped(Delta::from_micros(200), || {
//! while shared.flag.load(ordering::Relaxed) != 5 {
//! shared.cond.wait_for_completion();
//! }
//! });
//!
//! pr_info!("Counted to 5\n");
//! # Ok::<(), kernel::error::Error>(())
//! ```
//!
//! [`Arc`]: kernel::sync::Arc
use super::{ClockSource, Delta, Instant};
use crate::{prelude::*, types::Opaque};