6969
7070use super :: { ClockSource , Delta , Instant } ;
7171use crate :: { prelude:: * , types:: Opaque } ;
72- use core:: marker:: PhantomData ;
72+ use core:: { marker:: PhantomData , ptr :: NonNull } ;
7373use pin_init:: PinInit ;
7474
75+ /// A type-alias to refer to the [`Instant<C>`] for a given `T` from [`HrTimer<T>`].
76+ ///
77+ /// Where `C` is the [`ClockSource`] of the [`HrTimer`].
78+ pub type HrTimerInstant < T > = Instant < <<T as HasHrTimer < T > >:: TimerMode as HrTimerMode >:: Clock > ;
79+
7580/// A timer backed by a C `struct hrtimer`.
7681///
7782/// # Invariants
@@ -163,6 +168,84 @@ impl<T> HrTimer<T> {
163168 // handled on the C side.
164169 unsafe { bindings:: hrtimer_cancel ( c_timer_ptr) != 0 }
165170 }
171+
172+ /// Forward the timer expiry for a given timer pointer.
173+ ///
174+ /// # Safety
175+ ///
176+ /// - `self_ptr` must point to a valid `Self`.
177+ /// - The caller must either have exclusive access to the data pointed at by `self_ptr`, or be
178+ /// within the context of the timer callback.
179+ #[ inline]
180+ unsafe fn raw_forward ( self_ptr : * mut Self , now : HrTimerInstant < T > , interval : Delta ) -> u64
181+ where
182+ T : HasHrTimer < T > ,
183+ {
184+ // SAFETY:
185+ // * The C API requirements for this function are fulfilled by our safety contract.
186+ // * `self_ptr` is guaranteed to point to a valid `Self` via our safety contract
187+ unsafe {
188+ bindings:: hrtimer_forward ( Self :: raw_get ( self_ptr) , now. as_nanos ( ) , interval. as_nanos ( ) )
189+ }
190+ }
191+
192+ /// Conditionally forward the timer.
193+ ///
194+ /// If the timer expires after `now`, this function does nothing and returns 0. If the timer
195+ /// expired at or before `now`, this function forwards the timer by `interval` until the timer
196+ /// expires after `now` and then returns the number of times the timer was forwarded by
197+ /// `interval`.
198+ ///
199+ /// This function is mainly useful for timer types which can provide exclusive access to the
200+ /// timer when the timer is not running. For forwarding the timer from within the timer callback
201+ /// context, see [`HrTimerCallbackContext::forward()`].
202+ ///
203+ /// Returns the number of overruns that occurred as a result of the timer expiry change.
204+ pub fn forward ( self : Pin < & mut Self > , now : HrTimerInstant < T > , interval : Delta ) -> u64
205+ where
206+ T : HasHrTimer < T > ,
207+ {
208+ // SAFETY: `raw_forward` does not move `Self`
209+ let this = unsafe { self . get_unchecked_mut ( ) } ;
210+
211+ // SAFETY: By existence of `Pin<&mut Self>`, the pointer passed to `raw_forward` points to a
212+ // valid `Self` that we have exclusive access to.
213+ unsafe { Self :: raw_forward ( this, now, interval) }
214+ }
215+
216+ /// Conditionally forward the timer.
217+ ///
218+ /// This is a variant of [`forward()`](Self::forward) that uses an interval after the current
219+ /// time of the base clock for the [`HrTimer`].
220+ pub fn forward_now ( self : Pin < & mut Self > , interval : Delta ) -> u64
221+ where
222+ T : HasHrTimer < T > ,
223+ {
224+ self . forward ( HrTimerInstant :: < T > :: now ( ) , interval)
225+ }
226+
227+ /// Return the time expiry for this [`HrTimer`].
228+ ///
229+ /// This value should only be used as a snapshot, as the actual expiry time could change after
230+ /// this function is called.
231+ pub fn expires ( & self ) -> HrTimerInstant < T >
232+ where
233+ T : HasHrTimer < T > ,
234+ {
235+ // SAFETY: `self` is an immutable reference and thus always points to a valid `HrTimer`.
236+ let c_timer_ptr = unsafe { HrTimer :: raw_get ( self ) } ;
237+
238+ // SAFETY:
239+ // - Timers cannot have negative ktime_t values as their expiration time.
240+ // - There's no actual locking here, a racy read is fine and expected
241+ unsafe {
242+ Instant :: from_ktime (
243+ // This `read_volatile` is intended to correspond to a READ_ONCE call.
244+ // FIXME(read_once): Replace with `read_once` when available on the Rust side.
245+ core:: ptr:: read_volatile ( & raw const ( ( * c_timer_ptr) . node . expires ) ) ,
246+ )
247+ }
248+ }
166249}
167250
168251/// Implemented by pointer types that point to structs that contain a [`HrTimer`].
@@ -300,9 +383,13 @@ pub trait HrTimerCallback {
300383 type Pointer < ' a > : RawHrTimerCallback ;
301384
302385 /// Called by the timer logic when the timer fires.
303- fn run ( this : <Self :: Pointer < ' _ > as RawHrTimerCallback >:: CallbackTarget < ' _ > ) -> HrTimerRestart
386+ fn run (
387+ this : <Self :: Pointer < ' _ > as RawHrTimerCallback >:: CallbackTarget < ' _ > ,
388+ ctx : HrTimerCallbackContext < ' _ , Self > ,
389+ ) -> HrTimerRestart
304390 where
305- Self : Sized ;
391+ Self : Sized ,
392+ Self : HasHrTimer < Self > ;
306393}
307394
308395/// A handle representing a potentially running timer.
@@ -324,6 +411,8 @@ pub unsafe trait HrTimerHandle {
324411 /// Note that the timer might be started by a concurrent start operation. If
325412 /// so, the timer might not be in the **stopped** state when this function
326413 /// returns.
414+ ///
415+ /// Returns `true` if the timer was running.
327416 fn cancel ( & mut self ) -> bool ;
328417}
329418
@@ -585,6 +674,63 @@ impl<C: ClockSource> HrTimerMode for RelativePinnedHardMode<C> {
585674 type Expires = Delta ;
586675}
587676
677+ /// Privileged smart-pointer for a [`HrTimer`] callback context.
678+ ///
679+ /// Many [`HrTimer`] methods can only be called in two situations:
680+ ///
681+ /// * When the caller has exclusive access to the `HrTimer` and the `HrTimer` is guaranteed not to
682+ /// be running.
683+ /// * From within the context of an `HrTimer`'s callback method.
684+ ///
685+ /// This type provides access to said methods from within a timer callback context.
686+ ///
687+ /// # Invariants
688+ ///
689+ /// * The existence of this type means the caller is currently within the callback for an
690+ /// [`HrTimer`].
691+ /// * `self.0` always points to a live instance of [`HrTimer<T>`].
692+ pub struct HrTimerCallbackContext < ' a , T : HasHrTimer < T > > ( NonNull < HrTimer < T > > , PhantomData < & ' a ( ) > ) ;
693+
694+ impl < ' a , T : HasHrTimer < T > > HrTimerCallbackContext < ' a , T > {
695+ /// Create a new [`HrTimerCallbackContext`].
696+ ///
697+ /// # Safety
698+ ///
699+ /// This function relies on the caller being within the context of a timer callback, so it must
700+ /// not be used anywhere except for within implementations of [`RawHrTimerCallback::run`]. The
701+ /// caller promises that `timer` points to a valid initialized instance of
702+ /// [`bindings::hrtimer`].
703+ ///
704+ /// The returned `Self` must not outlive the function context of [`RawHrTimerCallback::run`]
705+ /// where this function is called.
706+ pub ( crate ) unsafe fn from_raw ( timer : * mut HrTimer < T > ) -> Self {
707+ // SAFETY: The caller guarantees `timer` is a valid pointer to an initialized
708+ // `bindings::hrtimer`
709+ // INVARIANT: Our safety contract ensures that we're within the context of a timer callback
710+ // and that `timer` points to a live instance of `HrTimer<T>`.
711+ Self ( unsafe { NonNull :: new_unchecked ( timer) } , PhantomData )
712+ }
713+
714+ /// Conditionally forward the timer.
715+ ///
716+ /// This function is identical to [`HrTimer::forward()`] except that it may only be used from
717+ /// within the context of a [`HrTimer`] callback.
718+ pub fn forward ( & mut self , now : HrTimerInstant < T > , interval : Delta ) -> u64 {
719+ // SAFETY:
720+ // - We are guaranteed to be within the context of a timer callback by our type invariants
721+ // - By our type invariants, `self.0` always points to a valid `HrTimer<T>`
722+ unsafe { HrTimer :: < T > :: raw_forward ( self . 0 . as_ptr ( ) , now, interval) }
723+ }
724+
725+ /// Conditionally forward the timer.
726+ ///
727+ /// This is a variant of [`HrTimerCallbackContext::forward()`] that uses an interval after the
728+ /// current time of the base clock for the [`HrTimer`].
729+ pub fn forward_now ( & mut self , duration : Delta ) -> u64 {
730+ self . forward ( HrTimerInstant :: < T > :: now ( ) , duration)
731+ }
732+ }
733+
588734/// Use to implement the [`HasHrTimer<T>`] trait.
589735///
590736/// See [`module`] documentation for an example.
0 commit comments