rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 0/7] rust/hrtimer: Various hrtimer + time additions
@ 2025-06-13 23:22 Lyude Paul
  2025-06-13 23:22 ` [PATCH v5 1/7] rust: hrtimer: Document the return value for HrTimerHandle::cancel() Lyude Paul
                   ` (6 more replies)
  0 siblings, 7 replies; 15+ messages in thread
From: Lyude Paul @ 2025-06-13 23:22 UTC (permalink / raw)
  To: rust-for-linux, Andreas Hindborg, linux-kernel
  Cc: Miguel Ojeda, Alex Gaynor, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Alice Ryhl, Trevor Gross,
	Danilo Krummrich

This is a collection of various bindings that I added to hrtimer when I
was originally getting it ready to be used in rvkms. I've mostly been
waiting for Andreas's hrtimer series to go upstream before submitting
these.

All of these are currently being used within rvkms for vblank emulation.

Based on top of Fujita's patch series "rust: time: Convert hrtimer to
use Instant and Delta":

  https://lkml.org/lkml/2025/6/10/1045

Previous versions:
  Version 1: https://lkml.org/lkml/2025/4/2/1474
  Version 2: https://lkml.org/lkml/2025/4/15/1750
  Version 3 (only a revision of one patch): https://lkml.org/lkml/2025/4/15/1780
  Version 4: https://lkml.org/lkml/2025/4/29/1715

Lyude Paul (7):
  rust: hrtimer: Document the return value for HrTimerHandle::cancel()
  rust: hrtimer: Add HrTimerInstant
  rust: hrtimer: Add HrTimer::raw_forward() and forward()
  rust: hrtimer: Add HrTimerCallbackContext and ::forward()
  rust: time: Add Instant::from_nanos()
  rust: hrtimer: Add HrTimer::raw_cb_time()
  rust: hrtimer: Add forward_now() to HrTimer and HrTimerCallbackContext

 rust/kernel/time.rs                 |  21 +++
 rust/kernel/time/hrtimer.rs         | 200 +++++++++++++++++++++++++++-
 rust/kernel/time/hrtimer/arc.rs     |   9 +-
 rust/kernel/time/hrtimer/pin.rs     |   9 +-
 rust/kernel/time/hrtimer/pin_mut.rs |  12 +-
 rust/kernel/time/hrtimer/tbox.rs    |   9 +-
 6 files changed, 252 insertions(+), 8 deletions(-)


base-commit: 61ff71163cf6d869f326a32b3d9afb157a78f734
-- 
2.49.0


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v5 1/7] rust: hrtimer: Document the return value for HrTimerHandle::cancel()
  2025-06-13 23:22 [PATCH v5 0/7] rust/hrtimer: Various hrtimer + time additions Lyude Paul
@ 2025-06-13 23:22 ` Lyude Paul
  2025-06-17 11:35   ` Andreas Hindborg
  2025-06-13 23:22 ` [PATCH v5 2/7] rust: hrtimer: Add HrTimerInstant Lyude Paul
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Lyude Paul @ 2025-06-13 23:22 UTC (permalink / raw)
  To: rust-for-linux, Andreas Hindborg, linux-kernel
  Cc: Boqun Feng, FUJITA Tomonori, Frederic Weisbecker, Thomas Gleixner,
	Anna-Maria Behnsen, John Stultz, Stephen Boyd, Miguel Ojeda,
	Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin,
	Alice Ryhl, Trevor Gross, Danilo Krummrich

Just a drive-by fix I noticed: we don't actually document what the return
value from cancel() does, so do that.

Signed-off-by: Lyude Paul <lyude@redhat.com>

---
V4:
* Reword to "Returns `true` if the timer was running."

Signed-off-by: Lyude Paul <lyude@redhat.com>
---
 rust/kernel/time/hrtimer.rs | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
index 3980a7c5f7dbe..294f257ef5c5a 100644
--- a/rust/kernel/time/hrtimer.rs
+++ b/rust/kernel/time/hrtimer.rs
@@ -324,6 +324,8 @@ pub unsafe trait HrTimerHandle {
     /// 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.
+    ///
+    /// Returns `true` if the timer was running.
     fn cancel(&mut self) -> bool;
 }
 
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v5 2/7] rust: hrtimer: Add HrTimerInstant
  2025-06-13 23:22 [PATCH v5 0/7] rust/hrtimer: Various hrtimer + time additions Lyude Paul
  2025-06-13 23:22 ` [PATCH v5 1/7] rust: hrtimer: Document the return value for HrTimerHandle::cancel() Lyude Paul
@ 2025-06-13 23:22 ` Lyude Paul
  2025-06-17 11:35   ` Andreas Hindborg
  2025-06-13 23:22 ` [PATCH v5 3/7] rust: hrtimer: Add HrTimer::raw_forward() and forward() Lyude Paul
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Lyude Paul @ 2025-06-13 23:22 UTC (permalink / raw)
  To: rust-for-linux, Andreas Hindborg, linux-kernel
  Cc: Boqun Feng, FUJITA Tomonori, Frederic Weisbecker, Thomas Gleixner,
	Anna-Maria Behnsen, John Stultz, Stephen Boyd, Miguel Ojeda,
	Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin,
	Alice Ryhl, Trevor Gross, Danilo Krummrich

Since we want to add HrTimer methods that can accept Instants, we will want
to make sure that for each method we are using the correct Clocksource for
the given HrTimer. This would get a bit overly-verbose, so add a simple
HrTimerInstant type-alias to handle this for us.

Signed-off-by: Lyude Paul <lyude@redhat.com>
---
 rust/kernel/time/hrtimer.rs | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
index 294f257ef5c5a..c775d7abdf5ce 100644
--- a/rust/kernel/time/hrtimer.rs
+++ b/rust/kernel/time/hrtimer.rs
@@ -72,6 +72,11 @@
 use core::marker::PhantomData;
 use pin_init::PinInit;
 
+/// A type-alias to refer to the [`Instant<C>`] for a given `T` from [`HrTimer<T>`].
+///
+/// Where `C` is the [`ClockSource`] of the [`HrTimer`].
+pub type HrTimerInstant<T> = Instant<<<T as HasHrTimer<T>>::TimerMode as HrTimerMode>::Clock>;
+
 /// A timer backed by a C `struct hrtimer`.
 ///
 /// # Invariants
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v5 3/7] rust: hrtimer: Add HrTimer::raw_forward() and forward()
  2025-06-13 23:22 [PATCH v5 0/7] rust/hrtimer: Various hrtimer + time additions Lyude Paul
  2025-06-13 23:22 ` [PATCH v5 1/7] rust: hrtimer: Document the return value for HrTimerHandle::cancel() Lyude Paul
  2025-06-13 23:22 ` [PATCH v5 2/7] rust: hrtimer: Add HrTimerInstant Lyude Paul
@ 2025-06-13 23:22 ` Lyude Paul
  2025-06-17 11:06   ` Andreas Hindborg
  2025-06-13 23:22 ` [PATCH v5 4/7] rust: hrtimer: Add HrTimerCallbackContext and ::forward() Lyude Paul
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Lyude Paul @ 2025-06-13 23:22 UTC (permalink / raw)
  To: rust-for-linux, Andreas Hindborg, linux-kernel
  Cc: Boqun Feng, FUJITA Tomonori, Frederic Weisbecker, Thomas Gleixner,
	Anna-Maria Behnsen, John Stultz, Stephen Boyd, Miguel Ojeda,
	Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin,
	Alice Ryhl, Trevor Gross, Danilo Krummrich

Within the hrtimer API there are quite a number of functions that can only
be safely called from one of two contexts:

* When we have exclusive access to the hrtimer and the timer is not active.
* When we're within the hrtimer's callback context as it is being executed.

This commit adds bindings for hrtimer_forward() for the first such context,
along with HrTimer::raw_forward() for later use in implementing the
hrtimer_forward() in the latter context.

Signed-off-by: Lyude Paul <lyude@redhat.com>

---
V4:
* Fix the safety contract for raw_forward()
* Require Pin<&mut Self>, not &mut self
* Drop incorrect UniquePin example
* Rewrite documentation a bit (re: Andreas)

Signed-off-by: Lyude Paul <lyude@redhat.com>
---
 rust/kernel/time/hrtimer.rs | 48 +++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
index c775d7abdf5ce..6fdd54e3328c5 100644
--- a/rust/kernel/time/hrtimer.rs
+++ b/rust/kernel/time/hrtimer.rs
@@ -168,6 +168,54 @@ pub(crate) unsafe fn raw_cancel(this: *const Self) -> bool {
         // handled on the C side.
         unsafe { bindings::hrtimer_cancel(c_timer_ptr) != 0 }
     }
+
+    /// Forward the timer expiry for a given timer pointer.
+    ///
+    /// # Safety
+    ///
+    /// - `self_ptr` must point to a valid `Self`.
+    /// - The caller must either have exclusive access to the data pointed at by `self_ptr`, or be
+    ///   within the context of the timer callback.
+    #[inline]
+    unsafe fn raw_forward(self_ptr: *mut Self, now: HrTimerInstant<T>, interval: Delta) -> u64
+    where
+        T: HasHrTimer<T>,
+    {
+        // SAFETY:
+        // * The C API requirements for this function are fulfilled by our safety contract.
+        // * `self_ptr` is guaranteed to point to a valid `Self` via our safety contract
+        unsafe {
+            bindings::hrtimer_forward(
+                Self::raw_get(self_ptr),
+                now.into_nanos(),
+                interval.into_nanos(),
+            )
+        }
+    }
+
+    /// Conditionally forward the timer.
+    ///
+    /// If the timer expires after `now`, this function does nothing and returns 0. If the timer
+    /// expired at or before `now`, this function forwards the timer by `interval` until the timer
+    /// expires after `now` and then returns the number of times the timer was forwarded by
+    /// `interval`.
+    ///
+    /// This function is mainly useful for timer types which can provide exclusive access to the
+    /// timer when the timer is not running. For forwarding the timer from within the timer callback
+    /// context, see [`HrTimerCallbackContext::forward()`].
+    ///
+    /// Returns the number of overruns that occurred as a result of the timer expiry change.
+    pub fn forward(self: Pin<&mut Self>, now: HrTimerInstant<T>, interval: Delta) -> u64
+    where
+        T: HasHrTimer<T>,
+    {
+        // SAFETY:
+        // - `raw_forward` does not move `self`.
+        // - Self is a mutable reference and thus always points to a valid `HrTimer`
+        // - The only way that we could hold a mutable reference to `HrTimer<T>` is if we have
+        //   exclusive access to it - fulfilling the requirements of the C API.
+        unsafe { Self::raw_forward(self.get_unchecked_mut(), now, interval) }
+    }
 }
 
 /// Implemented by pointer types that point to structs that contain a [`HrTimer`].
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v5 4/7] rust: hrtimer: Add HrTimerCallbackContext and ::forward()
  2025-06-13 23:22 [PATCH v5 0/7] rust/hrtimer: Various hrtimer + time additions Lyude Paul
                   ` (2 preceding siblings ...)
  2025-06-13 23:22 ` [PATCH v5 3/7] rust: hrtimer: Add HrTimer::raw_forward() and forward() Lyude Paul
@ 2025-06-13 23:22 ` Lyude Paul
  2025-06-17 11:18   ` Andreas Hindborg
  2025-06-13 23:22 ` [PATCH v5 5/7] rust: time: Add Instant::from_nanos() Lyude Paul
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 15+ messages in thread
From: Lyude Paul @ 2025-06-13 23:22 UTC (permalink / raw)
  To: rust-for-linux, Andreas Hindborg, linux-kernel
  Cc: Boqun Feng, FUJITA Tomonori, Frederic Weisbecker, Thomas Gleixner,
	Anna-Maria Behnsen, John Stultz, Stephen Boyd, Miguel Ojeda,
	Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin,
	Alice Ryhl, Trevor Gross, Danilo Krummrich

With Linux's hrtimer API, there's a number of methods that can only be
called in two situations:

* When we have exclusive access to the hrtimer and it is not currently
  active
* When we're within the context of an hrtimer callback context

This commit handles the second situation and implements hrtimer_forward()
support in the context of a timer callback. We do this by introducing a
HrTimerCallbackContext type which is provided to users during the
RawHrTimerCallback::run() callback, and then add a forward() function to
the type.

Signed-off-by: Lyude Paul <lyude@redhat.com>

---
V2:
* Improve SAFETY comments for HrTimerCallbackContext uses (I forgot to
  mention that we're within RawHrTimerCallback::run()
* Split forward into forward() and raw_forward() since we're going to have
  two contexts that we can call forward() from now.
* Clarify contexts in which certain hrtimer methods can be called.
* Make sure that we use a mutable reference for forward() here - just in
  case :).
* Rename interval to duration
V3:
* Rename duration -back- to interval (now that I actually have read
  hrtimer_forward's source, interval does make more sense than duration
  considering the fact we return the number of overruns that occurred
  according to the given interval).
* Rewrite documentation a bit (re: Andreas)

Signed-off-by: Lyude Paul <lyude@redhat.com>
---
 rust/kernel/time/hrtimer.rs         | 62 ++++++++++++++++++++++++++++-
 rust/kernel/time/hrtimer/arc.rs     |  9 ++++-
 rust/kernel/time/hrtimer/pin.rs     |  9 ++++-
 rust/kernel/time/hrtimer/pin_mut.rs | 12 ++++--
 rust/kernel/time/hrtimer/tbox.rs    |  9 ++++-
 5 files changed, 93 insertions(+), 8 deletions(-)

diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
index 6fdd54e3328c5..4a8416fbd187d 100644
--- a/rust/kernel/time/hrtimer.rs
+++ b/rust/kernel/time/hrtimer.rs
@@ -69,7 +69,7 @@
 
 use super::{ClockSource, Delta, Instant};
 use crate::{prelude::*, types::Opaque};
-use core::marker::PhantomData;
+use core::{marker::PhantomData, ptr::NonNull};
 use pin_init::PinInit;
 
 /// A type-alias to refer to the [`Instant<C>`] for a given `T` from [`HrTimer<T>`].
@@ -353,7 +353,10 @@ pub trait HrTimerCallback {
     type Pointer<'a>: RawHrTimerCallback;
 
     /// Called by the timer logic when the timer fires.
-    fn run(this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>) -> HrTimerRestart
+    fn run<T>(
+        this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>,
+        ctx: HrTimerCallbackContext<'_, T>,
+    ) -> HrTimerRestart
     where
         Self: Sized;
 }
@@ -619,6 +622,61 @@ impl<C: ClockSource> HrTimerMode for RelativePinnedHardMode<C> {
     type Expires = Delta;
 }
 
+/// Privileged smart-pointer for a [`HrTimer`] callback context.
+///
+/// Many [`HrTimer`] methods can only be called in two situations:
+///
+/// * When the caller has exclusive access to the `HrTimer` and the `HrTimer` is guaranteed not to
+///   be running.
+/// * From within the context of an `HrTimer`'s callback method.
+///
+/// This type provides access to said methods from within a timer callback context.
+///
+/// # Invariants
+///
+/// * The existence of this type means the caller is currently within the callback for an
+///   [`HrTimer`].
+/// * `self.0` always points to a live instance of [`HrTimer<T>`].
+pub struct HrTimerCallbackContext<'a, T>(NonNull<HrTimer<T>>, PhantomData<&'a ()>);
+
+impl<'a, T> HrTimerCallbackContext<'a, T> {
+    /// Create a new [`HrTimerCallbackContext`].
+    ///
+    /// # Safety
+    ///
+    /// This function relies on the caller being within the context of a timer callback, so it must
+    /// not be used anywhere except for within implementations of [`RawHrTimerCallback::run`]. The
+    /// caller promises that `timer` points to a valid initialized instance of
+    /// [`bindings::hrtimer`].
+    pub(crate) unsafe fn from_raw(timer: *mut HrTimer<T>) -> Self {
+        // SAFETY: The caller guarantees `timer` is a valid pointer to an initialized
+        // `bindings::hrtimer`
+        Self(unsafe { NonNull::new_unchecked(timer) }, PhantomData)
+    }
+
+    /// Conditionally forward the timer.
+    ///
+    /// If the timer expires after `now`, this function does nothing and returns 0. If the timer
+    /// expired at or before `now`, this function forwards the timer by `interval` until the timer
+    /// expires after `now` and then returns the number of times the timer was forwarded by
+    /// `interval`.
+    ///
+    /// This function is mainly useful for timer types which can provide exclusive access to the
+    /// timer when the timer is not running. For forwarding the timer when you have exclusive access
+    /// to the timer, see [`HrTimer::forward()`].
+    ///
+    /// Returns the number of overruns that occurred as a result of the timer expiry change.
+    pub fn forward(&mut self, now: HrTimerInstant<T>, interval: Delta) -> u64
+    where
+        T: HasHrTimer<T>,
+    {
+        // SAFETY:
+        // - We are guaranteed to be within the context of a timer callback by our type invariants
+        // - By our type invariants, `self.0` always points to a valid `HrTimer<T>`
+        unsafe { HrTimer::<T>::raw_forward(self.0.as_ptr(), now, interval) }
+    }
+}
+
 /// Use to implement the [`HasHrTimer<T>`] trait.
 ///
 /// See [`module`] documentation for an example.
diff --git a/rust/kernel/time/hrtimer/arc.rs b/rust/kernel/time/hrtimer/arc.rs
index ed490a7a89503..7be82bcb352ac 100644
--- a/rust/kernel/time/hrtimer/arc.rs
+++ b/rust/kernel/time/hrtimer/arc.rs
@@ -3,6 +3,7 @@
 use super::HasHrTimer;
 use super::HrTimer;
 use super::HrTimerCallback;
+use super::HrTimerCallbackContext;
 use super::HrTimerHandle;
 use super::HrTimerMode;
 use super::HrTimerPointer;
@@ -99,6 +100,12 @@ impl<T> RawHrTimerCallback for Arc<T>
         //    allocation from other `Arc` clones.
         let receiver = unsafe { ArcBorrow::from_raw(data_ptr) };
 
-        T::run(receiver).into_c()
+        // SAFETY:
+        // - By C API contract `timer_ptr` is the pointer that we passed when queuing the timer, so
+        //   it is a valid pointer to a `HrTimer<T>` embedded in a `T`.
+        // - We are within `RawHrTimerCallback::run`
+        let context = unsafe { HrTimerCallbackContext::from_raw(timer_ptr) };
+
+        T::run(receiver, context).into_c()
     }
 }
diff --git a/rust/kernel/time/hrtimer/pin.rs b/rust/kernel/time/hrtimer/pin.rs
index 550aad28d987c..a8c6423f7dfd1 100644
--- a/rust/kernel/time/hrtimer/pin.rs
+++ b/rust/kernel/time/hrtimer/pin.rs
@@ -3,6 +3,7 @@
 use super::HasHrTimer;
 use super::HrTimer;
 use super::HrTimerCallback;
+use super::HrTimerCallbackContext;
 use super::HrTimerHandle;
 use super::HrTimerMode;
 use super::RawHrTimerCallback;
@@ -103,6 +104,12 @@ impl<'a, T> RawHrTimerCallback for Pin<&'a T>
         // here.
         let receiver_pin = unsafe { Pin::new_unchecked(receiver_ref) };
 
-        T::run(receiver_pin).into_c()
+        // SAFETY:
+        // - By C API contract `timer_ptr` is the pointer that we passed when queuing the timer, so
+        //   it is a valid pointer to a `HrTimer<T>` embedded in a `T`.
+        // - We are within `RawHrTimerCallback::run`
+        let context = unsafe { HrTimerCallbackContext::from_raw(timer_ptr) };
+
+        T::run(receiver_pin, context).into_c()
     }
 }
diff --git a/rust/kernel/time/hrtimer/pin_mut.rs b/rust/kernel/time/hrtimer/pin_mut.rs
index bacd3d5d972a3..8da720a0b78fd 100644
--- a/rust/kernel/time/hrtimer/pin_mut.rs
+++ b/rust/kernel/time/hrtimer/pin_mut.rs
@@ -1,8 +1,8 @@
 // SPDX-License-Identifier: GPL-2.0
 
 use super::{
-    HasHrTimer, HrTimer, HrTimerCallback, HrTimerHandle, HrTimerMode, RawHrTimerCallback,
-    UnsafeHrTimerPointer,
+    HasHrTimer, HrTimer, HrTimerCallback, HrTimerCallbackContext, HrTimerHandle, HrTimerMode,
+    RawHrTimerCallback, UnsafeHrTimerPointer,
 };
 use core::{marker::PhantomData, pin::Pin, ptr::NonNull};
 
@@ -107,6 +107,12 @@ impl<'a, T> RawHrTimerCallback for Pin<&'a mut T>
         // here.
         let receiver_pin = unsafe { Pin::new_unchecked(receiver_ref) };
 
-        T::run(receiver_pin).into_c()
+        // SAFETY:
+        // - By C API contract `timer_ptr` is the pointer that we passed when queuing the timer, so
+        //   it is a valid pointer to a `HrTimer<T>` embedded in a `T`.
+        // - We are within `RawHrTimerCallback::run`
+        let context = unsafe { HrTimerCallbackContext::from_raw(timer_ptr) };
+
+        T::run(receiver_pin, context).into_c()
     }
 }
diff --git a/rust/kernel/time/hrtimer/tbox.rs b/rust/kernel/time/hrtimer/tbox.rs
index ec08303315f28..aa1ee31a71953 100644
--- a/rust/kernel/time/hrtimer/tbox.rs
+++ b/rust/kernel/time/hrtimer/tbox.rs
@@ -3,6 +3,7 @@
 use super::HasHrTimer;
 use super::HrTimer;
 use super::HrTimerCallback;
+use super::HrTimerCallbackContext;
 use super::HrTimerHandle;
 use super::HrTimerMode;
 use super::HrTimerPointer;
@@ -119,6 +120,12 @@ impl<T, A> RawHrTimerCallback for Pin<Box<T, A>>
         //   `data_ptr` exist.
         let data_mut_ref = unsafe { Pin::new_unchecked(&mut *data_ptr) };
 
-        T::run(data_mut_ref).into_c()
+        // SAFETY:
+        // - By C API contract `timer_ptr` is the pointer that we passed when queuing the timer, so
+        //   it is a valid pointer to a `HrTimer<T>` embedded in a `T`.
+        // - We are within `RawHrTimerCallback::run`
+        let context = unsafe { HrTimerCallbackContext::from_raw(timer_ptr) };
+
+        T::run(data_mut_ref, context).into_c()
     }
 }
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v5 5/7] rust: time: Add Instant::from_nanos()
  2025-06-13 23:22 [PATCH v5 0/7] rust/hrtimer: Various hrtimer + time additions Lyude Paul
                   ` (3 preceding siblings ...)
  2025-06-13 23:22 ` [PATCH v5 4/7] rust: hrtimer: Add HrTimerCallbackContext and ::forward() Lyude Paul
@ 2025-06-13 23:22 ` Lyude Paul
  2025-06-13 23:22 ` [PATCH v5 6/7] rust: hrtimer: Add HrTimer::raw_cb_time() Lyude Paul
  2025-06-13 23:22 ` [PATCH v5 7/7] rust: hrtimer: Add forward_now() to HrTimer and HrTimerCallbackContext Lyude Paul
  6 siblings, 0 replies; 15+ messages in thread
From: Lyude Paul @ 2025-06-13 23:22 UTC (permalink / raw)
  To: rust-for-linux, Andreas Hindborg, linux-kernel
  Cc: Boqun Feng, FUJITA Tomonori, Frederic Weisbecker, Thomas Gleixner,
	Anna-Maria Behnsen, John Stultz, Stephen Boyd, Miguel Ojeda,
	Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin,
	Alice Ryhl, Trevor Gross, Danilo Krummrich

For implementing Rust bindings which can return a point in time.

Signed-off-by: Lyude Paul <lyude@redhat.com>

---
V4:
* Turn from_nanos() into an unsafe function in order to ensure that we
  uphold the invariants of Instant
V5:
* Add debug_assert!() to from_nanos

Signed-off-by: Lyude Paul <lyude@redhat.com>
---
 rust/kernel/time.rs | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
index 70bd3be0facc0..eed77297d58a6 100644
--- a/rust/kernel/time.rs
+++ b/rust/kernel/time.rs
@@ -199,6 +199,28 @@ pub fn elapsed(&self) -> Delta {
     pub(crate) fn into_nanos(self) -> i64 {
         self.inner
     }
+
+    /// Create an [`Instant`] from a time duration specified in nano seconds.
+    ///
+    /// # Panics
+    ///
+    /// On debug builds, this function will panic if `nanos` violates our safety contract.
+    ///
+    /// # Safety
+    ///
+    /// The caller promises that `nanos` is in the range from 0 to `KTIME_MAX`.
+    #[expect(unused)]
+    #[inline]
+    pub(crate) unsafe fn from_nanos(nanos: i64) -> Self {
+        debug_assert!(nanos >= 0);
+
+        // INVARIANT: Our safety contract ensures that `nanos` is in the range from 0 to
+        // `KTIME_MAX`.
+        Self {
+            inner: nanos as bindings::ktime_t,
+            _c: PhantomData,
+        }
+    }
 }
 
 impl<C: ClockSource> core::ops::Sub for Instant<C> {
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v5 6/7] rust: hrtimer: Add HrTimer::raw_cb_time()
  2025-06-13 23:22 [PATCH v5 0/7] rust/hrtimer: Various hrtimer + time additions Lyude Paul
                   ` (4 preceding siblings ...)
  2025-06-13 23:22 ` [PATCH v5 5/7] rust: time: Add Instant::from_nanos() Lyude Paul
@ 2025-06-13 23:22 ` Lyude Paul
  2025-06-17 11:30   ` Andreas Hindborg
  2025-06-13 23:22 ` [PATCH v5 7/7] rust: hrtimer: Add forward_now() to HrTimer and HrTimerCallbackContext Lyude Paul
  6 siblings, 1 reply; 15+ messages in thread
From: Lyude Paul @ 2025-06-13 23:22 UTC (permalink / raw)
  To: rust-for-linux, Andreas Hindborg, linux-kernel
  Cc: Boqun Feng, FUJITA Tomonori, Frederic Weisbecker, Thomas Gleixner,
	Anna-Maria Behnsen, John Stultz, Stephen Boyd, Miguel Ojeda,
	Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin,
	Alice Ryhl, Trevor Gross, Danilo Krummrich

This is a simple private unsafe wrapper for retrieving the current time
according to the hrtimer_clock_base struct for a given timer. This will be
used for implementing functions such as forward_now(), which rely on
retrieving the current time from the hrtimer's clock base.

Signed-off-by: Lyude Paul <lyude@redhat.com>

---
V2:
- Convert safety comment to invariant comment in from_raw()
- Add raw_clock_base() and implement clock_base() on HrTimer<T> as well

V4:
- Drop HrTimerClockBase entirely, reword commit as this is now about adding
  raw_cb_time()

Signed-off-by: Lyude Paul <lyude@redhat.com>
---
 rust/kernel/time.rs         |  1 -
 rust/kernel/time/hrtimer.rs | 27 +++++++++++++++++++++++++++
 2 files changed, 27 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
index eed77297d58a6..27ee78070d72e 100644
--- a/rust/kernel/time.rs
+++ b/rust/kernel/time.rs
@@ -209,7 +209,6 @@ pub(crate) fn into_nanos(self) -> i64 {
     /// # Safety
     ///
     /// The caller promises that `nanos` is in the range from 0 to `KTIME_MAX`.
-    #[expect(unused)]
     #[inline]
     pub(crate) unsafe fn from_nanos(nanos: i64) -> Self {
         debug_assert!(nanos >= 0);
diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
index 4a8416fbd187d..79d86e1099a1e 100644
--- a/rust/kernel/time/hrtimer.rs
+++ b/rust/kernel/time/hrtimer.rs
@@ -193,6 +193,33 @@ unsafe fn raw_forward(self_ptr: *mut Self, now: HrTimerInstant<T>, interval: Del
         }
     }
 
+    /// Retrieve the current time according to the `struct hrtimer_clock_base` for `self_ptr`.
+    ///
+    /// # Safety
+    ///
+    /// - `self_ptr` must point to a valid `Self`.
+    /// - The caller must ensure that the `hrtimer_clock_base` cannot possibly change in the context
+    ///   this function is being called in. This means either exclusive access to `self_ptr` is
+    ///   required, or we must be from within the timer callback context of `self_ptr`.
+    #[expect(unused)]
+    unsafe fn raw_cb_time(self_ptr: *const Self) -> HrTimerInstant<T>
+    where
+        T: HasHrTimer<T>,
+    {
+        // SAFETY: We're guaranteed `self_ptr` points to a valid `Self` by our safety contract.
+        let clock_base = unsafe { (*Self::raw_get(self_ptr)).base };
+
+        // SAFETY: The C API guarantees that `get_time` is initialized to a valid function pointer
+        // for as long as we expose hrtimers to users.
+        let get_time_fn = unsafe { (*clock_base).get_time.unwrap_unchecked() };
+
+        // SAFETY:
+        // - get_time_fn() returns a ktime_t, so we're guaranteed its return value is between `0`
+        //   and `KTIME_MAX`.
+        // - get_time_fn() itself has no special requirements.
+        unsafe { Instant::from_nanos(get_time_fn()) }
+    }
+
     /// Conditionally forward the timer.
     ///
     /// If the timer expires after `now`, this function does nothing and returns 0. If the timer
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v5 7/7] rust: hrtimer: Add forward_now() to HrTimer and HrTimerCallbackContext
  2025-06-13 23:22 [PATCH v5 0/7] rust/hrtimer: Various hrtimer + time additions Lyude Paul
                   ` (5 preceding siblings ...)
  2025-06-13 23:22 ` [PATCH v5 6/7] rust: hrtimer: Add HrTimer::raw_cb_time() Lyude Paul
@ 2025-06-13 23:22 ` Lyude Paul
  2025-06-14  1:58   ` FUJITA Tomonori
  2025-06-17 11:34   ` Andreas Hindborg
  6 siblings, 2 replies; 15+ messages in thread
From: Lyude Paul @ 2025-06-13 23:22 UTC (permalink / raw)
  To: rust-for-linux, Andreas Hindborg, linux-kernel
  Cc: Boqun Feng, FUJITA Tomonori, Frederic Weisbecker, Thomas Gleixner,
	Anna-Maria Behnsen, John Stultz, Stephen Boyd, Miguel Ojeda,
	Alex Gaynor, Gary Guo, Björn Roy Baron, Benno Lossin,
	Alice Ryhl, Trevor Gross, Danilo Krummrich

Using the HrTimer::raw_time_cb() function, we can now add an equivalent to
hrtimer_forward_now() to both HrTimer and HrTimerCallbackContext.

Signed-off-by: Lyude Paul <lyude@redhat.com>

---
V2:
* Change from Ktime to Delta
* Make sure that forward_now() takes a mutable reference to the timer
  struct
* Reword this to point out that we're adding forward_now() to both callback
  context and mutable timer reference
* Rename interval to duration

V4:
* Fix rust documentation for HrTimerCallbackContext (forgot to update both
  forward_now() declarations)
* Use Pin<&mut Self> for context-less forward.

Signed-off-by: Lyude Paul <lyude@redhat.com>
---
 rust/kernel/time/hrtimer.rs | 58 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 57 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
index 79d86e1099a1e..0908359b0550a 100644
--- a/rust/kernel/time/hrtimer.rs
+++ b/rust/kernel/time/hrtimer.rs
@@ -201,7 +201,6 @@ unsafe fn raw_forward(self_ptr: *mut Self, now: HrTimerInstant<T>, interval: Del
     /// - The caller must ensure that the `hrtimer_clock_base` cannot possibly change in the context
     ///   this function is being called in. This means either exclusive access to `self_ptr` is
     ///   required, or we must be from within the timer callback context of `self_ptr`.
-    #[expect(unused)]
     unsafe fn raw_cb_time(self_ptr: *const Self) -> HrTimerInstant<T>
     where
         T: HasHrTimer<T>,
@@ -243,6 +242,44 @@ pub fn forward(self: Pin<&mut Self>, now: HrTimerInstant<T>, interval: Delta) ->
         //   exclusive access to it - fulfilling the requirements of the C API.
         unsafe { Self::raw_forward(self.get_unchecked_mut(), now, interval) }
     }
+
+    /// Conditionally forward the timer.
+    ///
+    /// This is a variant of [`forward()`](Self::forward) that uses an interval after the current
+    /// time of the base clock for the [`HrTimer`].
+    pub fn forward_now(self: Pin<&mut Self>, interval: Delta) -> u64
+    where
+        T: HasHrTimer<T>,
+    {
+        // SAFETY: `self` is a mutable reference, guaranteeing it is both a valid pointer to Self
+        // and that we also have exclusive access to `self`.
+        let now = unsafe { Self::raw_cb_time(&*self.as_ref()) };
+
+        self.forward(now, interval)
+    }
+
+    /// Return the time expiry for this [`HrTimer`].
+    ///
+    /// This value should only be used as a snapshot, as the actual expiry time could change after
+    /// this function is called.
+    pub fn expires(&self) -> HrTimerInstant<T>
+    where
+        T: HasHrTimer<T>,
+    {
+        // SAFETY: `self` is an immutable reference and thus always points to a valid `HrTimer`.
+        let c_timer_ptr = unsafe { HrTimer::raw_get(self) };
+
+        // SAFETY:
+        // - `node.expires` is a ktime_t, so it must be within the range of `0` to `KTIME_MAX`.
+        // - There's no actual locking here, a racy read is fine and expected
+        unsafe {
+            Instant::from_nanos(
+                // This `read_volatile` is intended to correspond to a READ_ONCE call.
+                // FIXME(read_once): Replace with `read_once` when available on the Rust side.
+                core::ptr::read_volatile(&raw const ((*c_timer_ptr).node.expires)),
+            )
+        }
+    }
 }
 
 /// Implemented by pointer types that point to structs that contain a [`HrTimer`].
@@ -702,6 +739,25 @@ pub fn forward(&mut self, now: HrTimerInstant<T>, interval: Delta) -> u64
         // - By our type invariants, `self.0` always points to a valid `HrTimer<T>`
         unsafe { HrTimer::<T>::raw_forward(self.0.as_ptr(), now, interval) }
     }
+
+    /// Conditionally forward the timer.
+    ///
+    /// This is a variant of [`HrTimerCallbackContext::forward()`] that uses an interval after the
+    /// current time of the base clock for the [`HrTimer`].
+    pub fn forward_now(&mut self, duration: Delta) -> u64
+    where
+        T: HasHrTimer<T>,
+    {
+        self.forward(
+            // SAFETY:
+            // - We're guaranteed `self.0` points to a valid `HrTimer<T>` instance by type
+            //   invariants.
+            // - We're guaranteed to be within the context of the timer callback by our type
+            //   invariants.
+            unsafe { HrTimer::<T>::raw_cb_time(self.0.as_ptr()) },
+            duration,
+        )
+    }
 }
 
 /// Use to implement the [`HasHrTimer<T>`] trait.
-- 
2.49.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 7/7] rust: hrtimer: Add forward_now() to HrTimer and HrTimerCallbackContext
  2025-06-13 23:22 ` [PATCH v5 7/7] rust: hrtimer: Add forward_now() to HrTimer and HrTimerCallbackContext Lyude Paul
@ 2025-06-14  1:58   ` FUJITA Tomonori
  2025-06-17 11:34   ` Andreas Hindborg
  1 sibling, 0 replies; 15+ messages in thread
From: FUJITA Tomonori @ 2025-06-14  1:58 UTC (permalink / raw)
  To: lyude
  Cc: rust-for-linux, a.hindborg, linux-kernel, boqun.feng,
	fujita.tomonori, frederic, tglx, anna-maria, jstultz, sboyd,
	ojeda, alex.gaynor, gary, bjorn3_gh, lossin, aliceryhl, tmgross,
	dakr

On Fri, 13 Jun 2025 19:22:28 -0400
Lyude Paul <lyude@redhat.com> wrote:

> Using the HrTimer::raw_time_cb() function, we can now add an equivalent to
> hrtimer_forward_now() to both HrTimer and HrTimerCallbackContext.
> 
> Signed-off-by: Lyude Paul <lyude@redhat.com>
> 
> ---
> V2:
> * Change from Ktime to Delta
> * Make sure that forward_now() takes a mutable reference to the timer
>   struct
> * Reword this to point out that we're adding forward_now() to both callback
>   context and mutable timer reference
> * Rename interval to duration
> 
> V4:
> * Fix rust documentation for HrTimerCallbackContext (forgot to update both
>   forward_now() declarations)
> * Use Pin<&mut Self> for context-less forward.
> 
> Signed-off-by: Lyude Paul <lyude@redhat.com>
> ---
>  rust/kernel/time/hrtimer.rs | 58 ++++++++++++++++++++++++++++++++++++-
>  1 file changed, 57 insertions(+), 1 deletion(-)
> 
> diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
> index 79d86e1099a1e..0908359b0550a 100644
> --- a/rust/kernel/time/hrtimer.rs
> +++ b/rust/kernel/time/hrtimer.rs
> @@ -201,7 +201,6 @@ unsafe fn raw_forward(self_ptr: *mut Self, now: HrTimerInstant<T>, interval: Del
>      /// - The caller must ensure that the `hrtimer_clock_base` cannot possibly change in the context
>      ///   this function is being called in. This means either exclusive access to `self_ptr` is
>      ///   required, or we must be from within the timer callback context of `self_ptr`.
> -    #[expect(unused)]
>      unsafe fn raw_cb_time(self_ptr: *const Self) -> HrTimerInstant<T>
>      where
>          T: HasHrTimer<T>,
> @@ -243,6 +242,44 @@ pub fn forward(self: Pin<&mut Self>, now: HrTimerInstant<T>, interval: Delta) ->
>          //   exclusive access to it - fulfilling the requirements of the C API.
>          unsafe { Self::raw_forward(self.get_unchecked_mut(), now, interval) }
>      }
> +
> +    /// Conditionally forward the timer.
> +    ///
> +    /// This is a variant of [`forward()`](Self::forward) that uses an interval after the current
> +    /// time of the base clock for the [`HrTimer`].
> +    pub fn forward_now(self: Pin<&mut Self>, interval: Delta) -> u64
> +    where
> +        T: HasHrTimer<T>,
> +    {
> +        // SAFETY: `self` is a mutable reference, guaranteeing it is both a valid pointer to Self
> +        // and that we also have exclusive access to `self`.
> +        let now = unsafe { Self::raw_cb_time(&*self.as_ref()) };

To the current time of the clock for the hrtimer, would it be possible
to write it like the following instead?

let now: Instant<<T::TimerMode as HrTimerMode>::Clock> = Instant::now();

Then we can drop #5 and #6 patches and remove some unsafe code.


By the way, where can I find the latest rvkms code that uses this
patchset?

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 3/7] rust: hrtimer: Add HrTimer::raw_forward() and forward()
  2025-06-13 23:22 ` [PATCH v5 3/7] rust: hrtimer: Add HrTimer::raw_forward() and forward() Lyude Paul
@ 2025-06-17 11:06   ` Andreas Hindborg
  0 siblings, 0 replies; 15+ messages in thread
From: Andreas Hindborg @ 2025-06-17 11:06 UTC (permalink / raw)
  To: Lyude Paul
  Cc: rust-for-linux, linux-kernel, Boqun Feng, FUJITA Tomonori,
	Frederic Weisbecker, Thomas Gleixner, Anna-Maria Behnsen,
	John Stultz, Stephen Boyd, Miguel Ojeda, Alex Gaynor, Gary Guo,
	Björn Roy Baron, Benno Lossin, Alice Ryhl, Trevor Gross,
	Danilo Krummrich

"Lyude Paul" <lyude@redhat.com> writes:

> Within the hrtimer API there are quite a number of functions that can only
> be safely called from one of two contexts:
>
> * When we have exclusive access to the hrtimer and the timer is not active.
> * When we're within the hrtimer's callback context as it is being executed.
>
> This commit adds bindings for hrtimer_forward() for the first such context,
> along with HrTimer::raw_forward() for later use in implementing the
> hrtimer_forward() in the latter context.
>
> Signed-off-by: Lyude Paul <lyude@redhat.com>
>
> ---
> V4:
> * Fix the safety contract for raw_forward()
> * Require Pin<&mut Self>, not &mut self
> * Drop incorrect UniquePin example
> * Rewrite documentation a bit (re: Andreas)
>
> Signed-off-by: Lyude Paul <lyude@redhat.com>
> ---
>  rust/kernel/time/hrtimer.rs | 48 +++++++++++++++++++++++++++++++++++++
>  1 file changed, 48 insertions(+)
>
> diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
> index c775d7abdf5ce..6fdd54e3328c5 100644
> --- a/rust/kernel/time/hrtimer.rs
> +++ b/rust/kernel/time/hrtimer.rs
> @@ -168,6 +168,54 @@ pub(crate) unsafe fn raw_cancel(this: *const Self) -> bool {
>          // handled on the C side.
>          unsafe { bindings::hrtimer_cancel(c_timer_ptr) != 0 }
>      }
> +
> +    /// Forward the timer expiry for a given timer pointer.
> +    ///
> +    /// # Safety
> +    ///
> +    /// - `self_ptr` must point to a valid `Self`.
> +    /// - The caller must either have exclusive access to the data pointed at by `self_ptr`, or be
> +    ///   within the context of the timer callback.
> +    #[inline]
> +    unsafe fn raw_forward(self_ptr: *mut Self, now: HrTimerInstant<T>, interval: Delta) -> u64
> +    where
> +        T: HasHrTimer<T>,
> +    {
> +        // SAFETY:
> +        // * The C API requirements for this function are fulfilled by our safety contract.
> +        // * `self_ptr` is guaranteed to point to a valid `Self` via our safety contract
> +        unsafe {
> +            bindings::hrtimer_forward(
> +                Self::raw_get(self_ptr),
> +                now.into_nanos(),
> +                interval.into_nanos(),
> +            )
> +        }
> +    }
> +
> +    /// Conditionally forward the timer.
> +    ///
> +    /// If the timer expires after `now`, this function does nothing and returns 0. If the timer
> +    /// expired at or before `now`, this function forwards the timer by `interval` until the timer
> +    /// expires after `now` and then returns the number of times the timer was forwarded by
> +    /// `interval`.
> +    ///
> +    /// This function is mainly useful for timer types which can provide exclusive access to the
> +    /// timer when the timer is not running. For forwarding the timer from within the timer callback
> +    /// context, see [`HrTimerCallbackContext::forward()`].

I think rustdoc is going to complain about this link being broken. Can
you add the last sentence when add the target of the link?


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 4/7] rust: hrtimer: Add HrTimerCallbackContext and ::forward()
  2025-06-13 23:22 ` [PATCH v5 4/7] rust: hrtimer: Add HrTimerCallbackContext and ::forward() Lyude Paul
@ 2025-06-17 11:18   ` Andreas Hindborg
  0 siblings, 0 replies; 15+ messages in thread
From: Andreas Hindborg @ 2025-06-17 11:18 UTC (permalink / raw)
  To: Lyude Paul
  Cc: rust-for-linux, linux-kernel, Boqun Feng, FUJITA Tomonori,
	Frederic Weisbecker, Thomas Gleixner, Anna-Maria Behnsen,
	John Stultz, Stephen Boyd, Miguel Ojeda, Alex Gaynor, Gary Guo,
	=?utf-8?Q?Bj=C3=B6rn?= Roy Baron, Benno Lossin, Alice Ryhl,
	Trevor Gross, Danilo Krummrich

"Lyude Paul" <lyude@redhat.com> writes:

> With Linux's hrtimer API, there's a number of methods that can only be
> called in two situations:
>
> * When we have exclusive access to the hrtimer and it is not currently
>   active
> * When we're within the context of an hrtimer callback context
>
> This commit handles the second situation and implements hrtimer_forward()
> support in the context of a timer callback. We do this by introducing a
> HrTimerCallbackContext type which is provided to users during the
> RawHrTimerCallback::run() callback, and then add a forward() function to
> the type.
>
> Signed-off-by: Lyude Paul <lyude@redhat.com>
>
> ---
> V2:
> * Improve SAFETY comments for HrTimerCallbackContext uses (I forgot to
>   mention that we're within RawHrTimerCallback::run()
> * Split forward into forward() and raw_forward() since we're going to have
>   two contexts that we can call forward() from now.
> * Clarify contexts in which certain hrtimer methods can be called.
> * Make sure that we use a mutable reference for forward() here - just in
>   case :).
> * Rename interval to duration
> V3:
> * Rename duration -back- to interval (now that I actually have read
>   hrtimer_forward's source, interval does make more sense than duration
>   considering the fact we return the number of overruns that occurred
>   according to the given interval).
> * Rewrite documentation a bit (re: Andreas)
>
> Signed-off-by: Lyude Paul <lyude@redhat.com>
> ---
>  rust/kernel/time/hrtimer.rs         | 62 ++++++++++++++++++++++++++++-
>  rust/kernel/time/hrtimer/arc.rs     |  9 ++++-
>  rust/kernel/time/hrtimer/pin.rs     |  9 ++++-
>  rust/kernel/time/hrtimer/pin_mut.rs | 12 ++++--
>  rust/kernel/time/hrtimer/tbox.rs    |  9 ++++-
>  5 files changed, 93 insertions(+), 8 deletions(-)
>
> diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
> index 6fdd54e3328c5..4a8416fbd187d 100644
> --- a/rust/kernel/time/hrtimer.rs
> +++ b/rust/kernel/time/hrtimer.rs
> @@ -69,7 +69,7 @@
>
>  use super::{ClockSource, Delta, Instant};
>  use crate::{prelude::*, types::Opaque};
> -use core::marker::PhantomData;
> +use core::{marker::PhantomData, ptr::NonNull};
>  use pin_init::PinInit;
>
>  /// A type-alias to refer to the [`Instant<C>`] for a given `T` from [`HrTimer<T>`].
> @@ -353,7 +353,10 @@ pub trait HrTimerCallback {
>      type Pointer<'a>: RawHrTimerCallback;
>
>      /// Called by the timer logic when the timer fires.
> -    fn run(this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>) -> HrTimerRestart
> +    fn run<T>(
> +        this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>,
> +        ctx: HrTimerCallbackContext<'_, T>,
> +    ) -> HrTimerRestart
>      where
>          Self: Sized;
>  }
> @@ -619,6 +622,61 @@ impl<C: ClockSource> HrTimerMode for RelativePinnedHardMode<C> {
>      type Expires = Delta;
>  }
>
> +/// Privileged smart-pointer for a [`HrTimer`] callback context.
> +///
> +/// Many [`HrTimer`] methods can only be called in two situations:
> +///
> +/// * When the caller has exclusive access to the `HrTimer` and the `HrTimer` is guaranteed not to
> +///   be running.
> +/// * From within the context of an `HrTimer`'s callback method.
> +///
> +/// This type provides access to said methods from within a timer callback context.
> +///
> +/// # Invariants
> +///
> +/// * The existence of this type means the caller is currently within the callback for an
> +///   [`HrTimer`].
> +/// * `self.0` always points to a live instance of [`HrTimer<T>`].
> +pub struct HrTimerCallbackContext<'a, T>(NonNull<HrTimer<T>>, PhantomData<&'a ()>);
> +
> +impl<'a, T> HrTimerCallbackContext<'a, T> {
> +    /// Create a new [`HrTimerCallbackContext`].
> +    ///
> +    /// # Safety
> +    ///
> +    /// This function relies on the caller being within the context of a timer callback, so it must
> +    /// not be used anywhere except for within implementations of [`RawHrTimerCallback::run`]. The
> +    /// caller promises that `timer` points to a valid initialized instance of
> +    /// [`bindings::hrtimer`].

The lifetime of the returned value is unbounded, so I think we need to add:

  The returned `Self` must not outlive the function context of
  `RawHrTimerCallback::run` where this function is called.

Or something to that effect. What do you think?

> +    pub(crate) unsafe fn from_raw(timer: *mut HrTimer<T>) -> Self {
> +        // SAFETY: The caller guarantees `timer` is a valid pointer to an initialized
> +        // `bindings::hrtimer`

We need to have an `# Invariant` section here.

> +        Self(unsafe { NonNull::new_unchecked(timer) }, PhantomData)
> +    }
> +
> +    /// Conditionally forward the timer.
> +    ///
> +    /// If the timer expires after `now`, this function does nothing and returns 0. If the timer
> +    /// expired at or before `now`, this function forwards the timer by `interval` until the timer
> +    /// expires after `now` and then returns the number of times the timer was forwarded by
> +    /// `interval`.
> +    ///
> +    /// This function is mainly useful for timer types which can provide exclusive access to the
> +    /// timer when the timer is not running. For forwarding the timer when you have exclusive access
> +    /// to the timer, see [`HrTimer::forward()`].
> +    ///
> +    /// Returns the number of overruns that occurred as a result of the timer expiry change.

Maybe we should just drop a link to `HrTimer::forward` for the docs
here? Or are we OK duplicating these docs?


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 6/7] rust: hrtimer: Add HrTimer::raw_cb_time()
  2025-06-13 23:22 ` [PATCH v5 6/7] rust: hrtimer: Add HrTimer::raw_cb_time() Lyude Paul
@ 2025-06-17 11:30   ` Andreas Hindborg
  0 siblings, 0 replies; 15+ messages in thread
From: Andreas Hindborg @ 2025-06-17 11:30 UTC (permalink / raw)
  To: Lyude Paul
  Cc: rust-for-linux, linux-kernel, Boqun Feng, FUJITA Tomonori,
	Frederic Weisbecker, Thomas Gleixner, Anna-Maria Behnsen,
	John Stultz, Stephen Boyd, Miguel Ojeda, Alex Gaynor, Gary Guo,
	Björn Roy Baron, Benno Lossin, Alice Ryhl, Trevor Gross,
	Danilo Krummrich

"Lyude Paul" <lyude@redhat.com> writes:

> This is a simple private unsafe wrapper for retrieving the current time
> according to the hrtimer_clock_base struct for a given timer. This will be
> used for implementing functions such as forward_now(), which rely on
> retrieving the current time from the hrtimer's clock base.
>
> Signed-off-by: Lyude Paul <lyude@redhat.com>
>
> ---
> V2:
> - Convert safety comment to invariant comment in from_raw()
> - Add raw_clock_base() and implement clock_base() on HrTimer<T> as well
>
> V4:
> - Drop HrTimerClockBase entirely, reword commit as this is now about adding
>   raw_cb_time()
>
> Signed-off-by: Lyude Paul <lyude@redhat.com>
> ---
>  rust/kernel/time.rs         |  1 -
>  rust/kernel/time/hrtimer.rs | 27 +++++++++++++++++++++++++++
>  2 files changed, 27 insertions(+), 1 deletion(-)
>
> diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
> index eed77297d58a6..27ee78070d72e 100644
> --- a/rust/kernel/time.rs
> +++ b/rust/kernel/time.rs
> @@ -209,7 +209,6 @@ pub(crate) fn into_nanos(self) -> i64 {
>      /// # Safety
>      ///
>      /// The caller promises that `nanos` is in the range from 0 to `KTIME_MAX`.
> -    #[expect(unused)]
>      #[inline]
>      pub(crate) unsafe fn from_nanos(nanos: i64) -> Self {
>          debug_assert!(nanos >= 0);
> diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
> index 4a8416fbd187d..79d86e1099a1e 100644
> --- a/rust/kernel/time/hrtimer.rs
> +++ b/rust/kernel/time/hrtimer.rs
> @@ -193,6 +193,33 @@ unsafe fn raw_forward(self_ptr: *mut Self, now: HrTimerInstant<T>, interval: Del
>          }
>      }
>
> +    /// Retrieve the current time according to the `struct hrtimer_clock_base` for `self_ptr`.
> +    ///
> +    /// # Safety
> +    ///
> +    /// - `self_ptr` must point to a valid `Self`.
> +    /// - The caller must ensure that the `hrtimer_clock_base` cannot possibly change in the context
> +    ///   this function is being called in. This means either exclusive access to `self_ptr` is
> +    ///   required, or we must be from within the timer callback context of `self_ptr`.
> +    #[expect(unused)]
> +    unsafe fn raw_cb_time(self_ptr: *const Self) -> HrTimerInstant<T>

Can we call it `raw_clock_base_time`?

> +    where
> +        T: HasHrTimer<T>,
> +    {
> +        // SAFETY: We're guaranteed `self_ptr` points to a valid `Self` by our safety contract.
> +        let clock_base = unsafe { (*Self::raw_get(self_ptr)).base };
> +
> +        // SAFETY: The C API guarantees that `get_time` is initialized to a valid function pointer
> +        // for as long as we expose hrtimers to users.
> +        let get_time_fn = unsafe { (*clock_base).get_time.unwrap_unchecked() };
> +
> +        // SAFETY:
> +        // - get_time_fn() returns a ktime_t, so we're guaranteed its return value is between `0`
> +        //   and `KTIME_MAX`.
> +        // - get_time_fn() itself has no special requirements.
> +        unsafe { Instant::from_nanos(get_time_fn()) }
> +    }
> +

How does this differ from Instant<C>::now()? Could we do this statically
by going through `<<T as HasHrTimer<T>>::TimerMode as HrTimerMode>::Clock`?


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 7/7] rust: hrtimer: Add forward_now() to HrTimer and HrTimerCallbackContext
  2025-06-13 23:22 ` [PATCH v5 7/7] rust: hrtimer: Add forward_now() to HrTimer and HrTimerCallbackContext Lyude Paul
  2025-06-14  1:58   ` FUJITA Tomonori
@ 2025-06-17 11:34   ` Andreas Hindborg
  1 sibling, 0 replies; 15+ messages in thread
From: Andreas Hindborg @ 2025-06-17 11:34 UTC (permalink / raw)
  To: Lyude Paul
  Cc: rust-for-linux, linux-kernel, Boqun Feng, FUJITA Tomonori,
	Frederic Weisbecker, Thomas Gleixner, Anna-Maria Behnsen,
	John Stultz, Stephen Boyd, Miguel Ojeda, Alex Gaynor, Gary Guo,
	Björn Roy Baron, Benno Lossin, Alice Ryhl, Trevor Gross,
	Danilo Krummrich

"Lyude Paul" <lyude@redhat.com> writes:

> Using the HrTimer::raw_time_cb() function, we can now add an equivalent to

You called it `raw_cb_time`.

> hrtimer_forward_now() to both HrTimer and HrTimerCallbackContext.
>
> Signed-off-by: Lyude Paul <lyude@redhat.com>
>
> ---
> V2:
> * Change from Ktime to Delta
> * Make sure that forward_now() takes a mutable reference to the timer
>   struct
> * Reword this to point out that we're adding forward_now() to both callback
>   context and mutable timer reference
> * Rename interval to duration
>
> V4:
> * Fix rust documentation for HrTimerCallbackContext (forgot to update both
>   forward_now() declarations)
> * Use Pin<&mut Self> for context-less forward.
>
> Signed-off-by: Lyude Paul <lyude@redhat.com>
> ---
>  rust/kernel/time/hrtimer.rs | 58 ++++++++++++++++++++++++++++++++++++-
>  1 file changed, 57 insertions(+), 1 deletion(-)
>
> diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
> index 79d86e1099a1e..0908359b0550a 100644
> --- a/rust/kernel/time/hrtimer.rs
> +++ b/rust/kernel/time/hrtimer.rs
> @@ -201,7 +201,6 @@ unsafe fn raw_forward(self_ptr: *mut Self, now: HrTimerInstant<T>, interval: Del
>      /// - The caller must ensure that the `hrtimer_clock_base` cannot possibly change in the context
>      ///   this function is being called in. This means either exclusive access to `self_ptr` is
>      ///   required, or we must be from within the timer callback context of `self_ptr`.
> -    #[expect(unused)]
>      unsafe fn raw_cb_time(self_ptr: *const Self) -> HrTimerInstant<T>
>      where
>          T: HasHrTimer<T>,
> @@ -243,6 +242,44 @@ pub fn forward(self: Pin<&mut Self>, now: HrTimerInstant<T>, interval: Delta) ->
>          //   exclusive access to it - fulfilling the requirements of the C API.
>          unsafe { Self::raw_forward(self.get_unchecked_mut(), now, interval) }
>      }
> +
> +    /// Conditionally forward the timer.
> +    ///
> +    /// This is a variant of [`forward()`](Self::forward) that uses an interval after the current
> +    /// time of the base clock for the [`HrTimer`].
> +    pub fn forward_now(self: Pin<&mut Self>, interval: Delta) -> u64
> +    where
> +        T: HasHrTimer<T>,
> +    {
> +        // SAFETY: `self` is a mutable reference, guaranteeing it is both a valid pointer to Self
> +        // and that we also have exclusive access to `self`.
> +        let now = unsafe { Self::raw_cb_time(&*self.as_ref()) };
> +
> +        self.forward(now, interval)
> +    }
> +
> +    /// Return the time expiry for this [`HrTimer`].
> +    ///
> +    /// This value should only be used as a snapshot, as the actual expiry time could change after
> +    /// this function is called.
> +    pub fn expires(&self) -> HrTimerInstant<T>

Commit message does not mention this method.


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 1/7] rust: hrtimer: Document the return value for HrTimerHandle::cancel()
  2025-06-13 23:22 ` [PATCH v5 1/7] rust: hrtimer: Document the return value for HrTimerHandle::cancel() Lyude Paul
@ 2025-06-17 11:35   ` Andreas Hindborg
  0 siblings, 0 replies; 15+ messages in thread
From: Andreas Hindborg @ 2025-06-17 11:35 UTC (permalink / raw)
  To: Lyude Paul
  Cc: rust-for-linux, linux-kernel, Boqun Feng, FUJITA Tomonori,
	Frederic Weisbecker, Thomas Gleixner, Anna-Maria Behnsen,
	John Stultz, Stephen Boyd, Miguel Ojeda, Alex Gaynor, Gary Guo,
	Björn Roy Baron, Benno Lossin, Alice Ryhl, Trevor Gross,
	Danilo Krummrich

"Lyude Paul" <lyude@redhat.com> writes:

> Just a drive-by fix I noticed: we don't actually document what the return
> value from cancel() does, so do that.
>
> Signed-off-by: Lyude Paul <lyude@redhat.com>

Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>


Best regards,
Andreas Hindborg



^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v5 2/7] rust: hrtimer: Add HrTimerInstant
  2025-06-13 23:22 ` [PATCH v5 2/7] rust: hrtimer: Add HrTimerInstant Lyude Paul
@ 2025-06-17 11:35   ` Andreas Hindborg
  0 siblings, 0 replies; 15+ messages in thread
From: Andreas Hindborg @ 2025-06-17 11:35 UTC (permalink / raw)
  To: Lyude Paul
  Cc: rust-for-linux, linux-kernel, Boqun Feng, FUJITA Tomonori,
	Frederic Weisbecker, Thomas Gleixner, Anna-Maria Behnsen,
	John Stultz, Stephen Boyd, Miguel Ojeda, Alex Gaynor, Gary Guo,
	Björn Roy Baron, Benno Lossin, Alice Ryhl, Trevor Gross,
	Danilo Krummrich

"Lyude Paul" <lyude@redhat.com> writes:

> Since we want to add HrTimer methods that can accept Instants, we will want
> to make sure that for each method we are using the correct Clocksource for
> the given HrTimer. This would get a bit overly-verbose, so add a simple
> HrTimerInstant type-alias to handle this for us.
>
> Signed-off-by: Lyude Paul <lyude@redhat.com>

Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>


Best regards,
Andreas Hindborg




^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2025-06-17 11:43 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-13 23:22 [PATCH v5 0/7] rust/hrtimer: Various hrtimer + time additions Lyude Paul
2025-06-13 23:22 ` [PATCH v5 1/7] rust: hrtimer: Document the return value for HrTimerHandle::cancel() Lyude Paul
2025-06-17 11:35   ` Andreas Hindborg
2025-06-13 23:22 ` [PATCH v5 2/7] rust: hrtimer: Add HrTimerInstant Lyude Paul
2025-06-17 11:35   ` Andreas Hindborg
2025-06-13 23:22 ` [PATCH v5 3/7] rust: hrtimer: Add HrTimer::raw_forward() and forward() Lyude Paul
2025-06-17 11:06   ` Andreas Hindborg
2025-06-13 23:22 ` [PATCH v5 4/7] rust: hrtimer: Add HrTimerCallbackContext and ::forward() Lyude Paul
2025-06-17 11:18   ` Andreas Hindborg
2025-06-13 23:22 ` [PATCH v5 5/7] rust: time: Add Instant::from_nanos() Lyude Paul
2025-06-13 23:22 ` [PATCH v5 6/7] rust: hrtimer: Add HrTimer::raw_cb_time() Lyude Paul
2025-06-17 11:30   ` Andreas Hindborg
2025-06-13 23:22 ` [PATCH v5 7/7] rust: hrtimer: Add forward_now() to HrTimer and HrTimerCallbackContext Lyude Paul
2025-06-14  1:58   ` FUJITA Tomonori
2025-06-17 11:34   ` Andreas Hindborg

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).