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

Mike Lothian <[email protected]>
Newsgroups org.kernel.vger.rust-for-linux,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
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 <[email protected]>
---
 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>,
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.