[PATCH 2/9] rust: hrtimer: add ArcHrTimerHandle::restart

From: Mike Lothian

Date: Wed Aug 26 2026 - 12:32:30 EST


Restarting an already-started timer through the safe API means dropping
its handle and calling `HrTimerPointer::start()` again. Dropping the
handle cancels, and cancelling blocks until a running callback returns,
so this is unavailable to any caller that cannot sleep -- a driver
re-arming its timer from a callback invoked with interrupts disabled,
say. Such drivers fall back to the unsafe `HasHrTimer::start()`
on a raw pointer.

Add `restart()` on the handle. It re-queues the timer in place without
cancelling first. It is safe because the handle already owns the
`Arc` that keeps the timer alive and still cancels it on drop, which
is exactly what `HasHrTimer::start()` requires of its caller.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Mike Lothian <mike@xxxxxxxxxxxxxx>
---
rust/kernel/time/hrtimer/arc.rs | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

diff --git a/rust/kernel/time/hrtimer/arc.rs b/rust/kernel/time/hrtimer/arc.rs
index 7be82bcb352a..f7cd46dbd3d3 100644
--- a/rust/kernel/time/hrtimer/arc.rs
+++ b/rust/kernel/time/hrtimer/arc.rs
@@ -39,6 +39,29 @@ fn cancel(&mut self) -> bool {
}
}

+impl<T> ArcHrTimerHandle<T>
+where
+ T: HasHrTimer<T>,
+{
+ /// Restart the timer with a new expiry time, without cancelling it first.
+ ///
+ /// If the timer is queued it is removed and re-inserted at the new expiry; if it has already
+ /// expired it is queued again. Unlike dropping the handle and calling
+ /// [`HrTimerPointer::start`] again, this never blocks waiting for a running callback, so it
+ /// can be used from contexts that cannot sleep -- re-arming a timer from a driver callback
+ /// invoked with interrupts disabled, for instance.
+ ///
+ /// This handle keeps its timer alive and still cancels it on drop, so the timer cannot outlive
+ /// the restart.
+ pub fn restart(&self, expires: <<T as HasHrTimer<T>>::TimerMode as HrTimerMode>::Expires) {
+ // SAFETY:
+ // - `self.inner` is a live `Arc<T>` held by this handle, so the pointer is valid.
+ // - The caller cannot leak past the timer's death: this handle owns the `Arc` and cancels
+ // the timer when dropped, which is the requirement `HasHrTimer::start` places on us.
+ unsafe { T::start(Arc::as_ptr(&self.inner), expires) };
+ }
+}
+
impl<T> Drop for ArcHrTimerHandle<T>
where
T: HasHrTimer<T>,