|
69 | 69 |
|
70 | 70 | use super::{ClockSource, Delta, Instant}; |
71 | 71 | use crate::{prelude::*, types::Opaque}; |
72 | | -use core::marker::PhantomData; |
| 72 | +use core::{marker::PhantomData, ptr::NonNull}; |
73 | 73 | use pin_init::PinInit; |
74 | 74 |
|
75 | 75 | /// A type-alias to refer to the [`Instant<C>`] for a given `T` from [`HrTimer<T>`]. |
@@ -196,6 +196,10 @@ impl<T> HrTimer<T> { |
196 | 196 | /// expires after `now` and then returns the number of times the timer was forwarded by |
197 | 197 | /// `interval`. |
198 | 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 | + /// |
199 | 203 | /// Returns the number of overruns that occurred as a result of the timer expiry change. |
200 | 204 | pub fn forward(self: Pin<&mut Self>, now: HrTimerInstant<T>, interval: Delta) -> u64 |
201 | 205 | where |
@@ -345,9 +349,13 @@ pub trait HrTimerCallback { |
345 | 349 | type Pointer<'a>: RawHrTimerCallback; |
346 | 350 |
|
347 | 351 | /// Called by the timer logic when the timer fires. |
348 | | - fn run(this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>) -> HrTimerRestart |
| 352 | + fn run( |
| 353 | + this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>, |
| 354 | + ctx: HrTimerCallbackContext<'_, Self>, |
| 355 | + ) -> HrTimerRestart |
349 | 356 | where |
350 | | - Self: Sized; |
| 357 | + Self: Sized, |
| 358 | + Self: HasHrTimer<Self>; |
351 | 359 | } |
352 | 360 |
|
353 | 361 | /// A handle representing a potentially running timer. |
@@ -632,6 +640,55 @@ impl<C: ClockSource> HrTimerMode for RelativePinnedHardMode<C> { |
632 | 640 | type Expires = Delta; |
633 | 641 | } |
634 | 642 |
|
| 643 | +/// Privileged smart-pointer for a [`HrTimer`] callback context. |
| 644 | +/// |
| 645 | +/// Many [`HrTimer`] methods can only be called in two situations: |
| 646 | +/// |
| 647 | +/// * When the caller has exclusive access to the `HrTimer` and the `HrTimer` is guaranteed not to |
| 648 | +/// be running. |
| 649 | +/// * From within the context of an `HrTimer`'s callback method. |
| 650 | +/// |
| 651 | +/// This type provides access to said methods from within a timer callback context. |
| 652 | +/// |
| 653 | +/// # Invariants |
| 654 | +/// |
| 655 | +/// * The existence of this type means the caller is currently within the callback for an |
| 656 | +/// [`HrTimer`]. |
| 657 | +/// * `self.0` always points to a live instance of [`HrTimer<T>`]. |
| 658 | +pub struct HrTimerCallbackContext<'a, T: HasHrTimer<T>>(NonNull<HrTimer<T>>, PhantomData<&'a ()>); |
| 659 | + |
| 660 | +impl<'a, T: HasHrTimer<T>> HrTimerCallbackContext<'a, T> { |
| 661 | + /// Create a new [`HrTimerCallbackContext`]. |
| 662 | + /// |
| 663 | + /// # Safety |
| 664 | + /// |
| 665 | + /// This function relies on the caller being within the context of a timer callback, so it must |
| 666 | + /// not be used anywhere except for within implementations of [`RawHrTimerCallback::run`]. The |
| 667 | + /// caller promises that `timer` points to a valid initialized instance of |
| 668 | + /// [`bindings::hrtimer`]. |
| 669 | + /// |
| 670 | + /// The returned `Self` must not outlive the function context of [`RawHrTimerCallback::run`] |
| 671 | + /// where this function is called. |
| 672 | + pub(crate) unsafe fn from_raw(timer: *mut HrTimer<T>) -> Self { |
| 673 | + // SAFETY: The caller guarantees `timer` is a valid pointer to an initialized |
| 674 | + // `bindings::hrtimer` |
| 675 | + // INVARIANT: Our safety contract ensures that we're within the context of a timer callback |
| 676 | + // and that `timer` points to a live instance of `HrTimer<T>`. |
| 677 | + Self(unsafe { NonNull::new_unchecked(timer) }, PhantomData) |
| 678 | + } |
| 679 | + |
| 680 | + /// Conditionally forward the timer. |
| 681 | + /// |
| 682 | + /// This function is identical to [`HrTimer::forward()`] except that it may only be used from |
| 683 | + /// within the context of a [`HrTimer`] callback. |
| 684 | + pub fn forward(&mut self, now: HrTimerInstant<T>, interval: Delta) -> u64 { |
| 685 | + // SAFETY: |
| 686 | + // - We are guaranteed to be within the context of a timer callback by our type invariants |
| 687 | + // - By our type invariants, `self.0` always points to a valid `HrTimer<T>` |
| 688 | + unsafe { HrTimer::<T>::raw_forward(self.0.as_ptr(), now, interval) } |
| 689 | + } |
| 690 | +} |
| 691 | + |
635 | 692 | /// Use to implement the [`HasHrTimer<T>`] trait. |
636 | 693 | /// |
637 | 694 | /// See [`module`] documentation for an example. |
|
0 commit comments