[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>,