From: Andreas Hindborg <a.hindborg@kernel.org>
To: "Boqun Feng" <boqun@kernel.org>,
"FUJITA Tomonori" <fujita.tomonori@gmail.com>,
"Frederic Weisbecker" <frederic@kernel.org>,
"Lyude Paul" <lyude@redhat.com>,
"Thomas Gleixner" <tglx@kernel.org>,
"Anna-Maria Behnsen" <anna-maria@linutronix.de>,
"John Stultz" <jstultz@google.com>,
"Stephen Boyd" <sboyd@kernel.org>,
"Miguel Ojeda" <ojeda@kernel.org>, "Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>,
"Daniel Almeida" <daniel.almeida@collabora.com>,
"Tamir Duberstein" <tamird@kernel.org>,
"Alexandre Courbot" <acourbot@nvidia.com>,
"Onur Özkan" <work@onurozkan.dev>
Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
Andreas Hindborg <a.hindborg@kernel.org>
Subject: [PATCH v3] rust: hrtimer: add active() method to query timer state
Date: Thu, 05 Nov 2026 11:17:24 +0100 [thread overview]
Message-ID: <20261105-hrtimer-active-v3-1-52636808ccda@kernel.org> (raw)
Add an `active()` method to HrTimer that returns true if the timer is in
the started or running states. This wraps the kernel's hrtimer_active()
function.
Unlike a direct read of `node.expires`, this does not race with a
concurrent start operation. hrtimer_active() reads the timer state inside a
seqcount retry loop and re-reads `timer->base` with READ_ONCE(), and the
core documents that it must not return a false negative. No exclusive
access to the timer is therefore required, and the SAFETY comment reflects
that.
The returned value is still only a snapshot: a concurrent start or an
expiry can change the state right after the call. Callers that need a
stable answer have to serialize against those operations themselves,
exactly as C callers of hrtimer_active() do. This is documented on the
method.
Also add documentation clarifying the definition of an active timer.
Introduce the term `active` as a set of timer states composed of `started`
and `running`.
Reviewed-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
Signed-off-by: Andreas Hindborg <a.hindborg@kernel.org>
---
Changes in v3:
- Rebase on v7.4-rc1.
- Improve documentation.
- Move the note about not requiring exclusive access above the example.
- Name the user of the API below the cut.
- Link to v2: https://msgid.link/20260605-hrtimer-active-v2-1-77d755c81fd7@kernel.org
Changes in v2:
- Mark `active()` `#[inline]` (Gary).
- Use the `[`true`]` intra-doc link in the rustdoc (Miguel).
- Document that `active()` does not require exclusive access to the timer,
and reflect this in the SAFETY comment (Gary).
- Add a doctest example that initializes a timer and asserts it is not
active (Miguel).
- Link to v1: https://msgid.link/20260215-hrtimer-active-v1-1-a754d10492c2@kernel.org
---
The bandwidth throttling timer in the Rust null block driver will call this
function. It is used to arm the timer on request submission if it is not
already armed.
---
rust/kernel/time/hrtimer.rs | 64 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
index a53f7f1341be..45bbe3530f8c 100644
--- a/rust/kernel/time/hrtimer.rs
+++ b/rust/kernel/time/hrtimer.rs
@@ -71,6 +71,8 @@
//! issue the `start` operation while the timer is in the **started** state. In
//! this case the `start` operation is equivalent to the `restart` operation.
//!
+//! A timer is **active** if it is either in the **started** or **running** states.
+//!
//! # Examples
//!
//! ## Using an intrusive timer living in a [`Box`]
@@ -593,6 +595,68 @@ pub fn expires(&self) -> HrTimerInstant<T>
)
}
}
+
+ /// Query the state of the timer.
+ ///
+ /// Returns [`true`] if the timer is in the started or running states.
+ ///
+ /// This method synchronizes internally and does not require exclusive access to the timer.
+ ///
+ /// The returned value is a snapshot. A concurrent start or expiry can change the state of the
+ /// timer right after this method returns, so callers that need the state to be stable must
+ /// serialize against those operations by other means.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # use kernel::{
+ /// # impl_has_hr_timer,
+ /// # prelude::*,
+ /// # time::{
+ /// # hrtimer::{
+ /// # HasHrTimer, HrTimer, HrTimerCallback, HrTimerCallbackContext,
+ /// # HrTimerRestart, RelativeMode,
+ /// # },
+ /// # Monotonic,
+ /// # },
+ /// # };
+ /// # use pin_init::stack_pin_init;
+ /// #[pin_data]
+ /// struct ExampleTimer {
+ /// #[pin]
+ /// timer: HrTimer<Self>,
+ /// }
+ ///
+ /// impl ExampleTimer {
+ /// fn new() -> impl PinInit<Self> {
+ /// pin_init!(Self { timer <- HrTimer::new() })
+ /// }
+ /// }
+ ///
+ /// impl HrTimerCallback for ExampleTimer {
+ /// type Pointer<'a> = Pin<&'a Self>;
+ /// fn run(_this: Pin<&Self>, _ctx: HrTimerCallbackContext<'_, Self>) -> HrTimerRestart {
+ /// HrTimerRestart::NoRestart
+ /// }
+ /// }
+ ///
+ /// impl_has_hr_timer! {
+ /// impl HasHrTimer<Self> for ExampleTimer {
+ /// mode: RelativeMode<Monotonic>, field: self.timer
+ /// }
+ /// }
+ ///
+ /// stack_pin_init!(let has_timer = ExampleTimer::new());
+ /// assert!(!has_timer.timer.active());
+ /// # Ok::<(), kernel::error::Error>(())
+ /// ```
+ #[inline]
+ pub fn active(&self) -> bool {
+ // SAFETY: By type invariant, `self.timer` is valid. `hrtimer_active`
+ // synchronizes internally and is safe to call without exclusive
+ // access to the timer.
+ unsafe { bindings::hrtimer_active(self.timer.get()) }
+ }
}
/// Implemented by pointer types that point to structs that contain a [`HrTimer`].
---
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
change-id: 20260215-hrtimer-active-f183411fe56b
Best regards,
--
Andreas Hindborg <a.hindborg@kernel.org>
next reply other threads:[~2026-11-05 10:17 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 10:17 Andreas Hindborg [this message]
2026-11-05 11:11 ` [PATCH v3] rust: hrtimer: add active() method to query timer state FUJITA Tomonori
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261105-hrtimer-active-v3-1-52636808ccda@kernel.org \
--to=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=aliceryhl@google.com \
--cc=anna-maria@linutronix.de \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun@kernel.org \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=frederic@kernel.org \
--cc=fujita.tomonori@gmail.com \
--cc=gary@garyguo.net \
--cc=jstultz@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=lyude@redhat.com \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=sboyd@kernel.org \
--cc=tamird@kernel.org \
--cc=tglx@kernel.org \
--cc=tmgross@umich.edu \
--cc=work@onurozkan.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.