18a8afe93SAndreas Hindborg // SPDX-License-Identifier: GPL-2.0 28a8afe93SAndreas Hindborg 38a8afe93SAndreas Hindborg //! Intrusive high resolution timers. 48a8afe93SAndreas Hindborg //! 58a8afe93SAndreas Hindborg //! Allows running timer callbacks without doing allocations at the time of 68a8afe93SAndreas Hindborg //! starting the timer. For now, only one timer per type is allowed. 78a8afe93SAndreas Hindborg //! 88a8afe93SAndreas Hindborg //! # Vocabulary 98a8afe93SAndreas Hindborg //! 108a8afe93SAndreas Hindborg //! States: 118a8afe93SAndreas Hindborg //! 128a8afe93SAndreas Hindborg //! - Stopped: initialized but not started, or cancelled, or not restarted. 138a8afe93SAndreas Hindborg //! - Started: initialized and started or restarted. 148a8afe93SAndreas Hindborg //! - Running: executing the callback. 158a8afe93SAndreas Hindborg //! 168a8afe93SAndreas Hindborg //! Operations: 178a8afe93SAndreas Hindborg //! 188a8afe93SAndreas Hindborg //! * Start 198a8afe93SAndreas Hindborg //! * Cancel 208a8afe93SAndreas Hindborg //! * Restart 218a8afe93SAndreas Hindborg //! 228a8afe93SAndreas Hindborg //! Events: 238a8afe93SAndreas Hindborg //! 248a8afe93SAndreas Hindborg //! * Expire 258a8afe93SAndreas Hindborg //! 268a8afe93SAndreas Hindborg //! ## State Diagram 278a8afe93SAndreas Hindborg //! 288a8afe93SAndreas Hindborg //! ```text 298a8afe93SAndreas Hindborg //! Return NoRestart 308a8afe93SAndreas Hindborg //! +---------------------------------------------------------------------+ 318a8afe93SAndreas Hindborg //! | | 328a8afe93SAndreas Hindborg //! | | 338a8afe93SAndreas Hindborg //! | | 348a8afe93SAndreas Hindborg //! | Return Restart | 358a8afe93SAndreas Hindborg //! | +------------------------+ | 368a8afe93SAndreas Hindborg //! | | | | 378a8afe93SAndreas Hindborg //! | | | | 388a8afe93SAndreas Hindborg //! v v | | 398a8afe93SAndreas Hindborg //! +-----------------+ Start +------------------+ +--------+-----+--+ 408a8afe93SAndreas Hindborg //! | +---------------->| | | | 418a8afe93SAndreas Hindborg //! Init | | | | Expire | | 428a8afe93SAndreas Hindborg //! --------->| Stopped | | Started +---------->| Running | 438a8afe93SAndreas Hindborg //! | | Cancel | | | | 448a8afe93SAndreas Hindborg //! | |<----------------+ | | | 458a8afe93SAndreas Hindborg //! +-----------------+ +---------------+--+ +-----------------+ 468a8afe93SAndreas Hindborg //! ^ | 478a8afe93SAndreas Hindborg //! | | 488a8afe93SAndreas Hindborg //! +---------+ 498a8afe93SAndreas Hindborg //! Restart 508a8afe93SAndreas Hindborg //! ``` 518a8afe93SAndreas Hindborg //! 528a8afe93SAndreas Hindborg //! 538a8afe93SAndreas Hindborg //! A timer is initialized in the **stopped** state. A stopped timer can be 548a8afe93SAndreas Hindborg //! **started** by the `start` operation, with an **expiry** time. After the 558a8afe93SAndreas Hindborg //! `start` operation, the timer is in the **started** state. When the timer 568a8afe93SAndreas Hindborg //! **expires**, the timer enters the **running** state and the handler is 578a8afe93SAndreas Hindborg //! executed. After the handler has returned, the timer may enter the 588a8afe93SAndreas Hindborg //! **started* or **stopped** state, depending on the return value of the 598a8afe93SAndreas Hindborg //! handler. A timer in the **started** or **running** state may be **canceled** 608a8afe93SAndreas Hindborg //! by the `cancel` operation. A timer that is cancelled enters the **stopped** 618a8afe93SAndreas Hindborg //! state. 628a8afe93SAndreas Hindborg //! 638a8afe93SAndreas Hindborg //! A `cancel` or `restart` operation on a timer in the **running** state takes 648a8afe93SAndreas Hindborg //! effect after the handler has returned and the timer has transitioned 658a8afe93SAndreas Hindborg //! out of the **running** state. 668a8afe93SAndreas Hindborg //! 678a8afe93SAndreas Hindborg //! A `restart` operation on a timer in the **stopped** state is equivalent to a 688a8afe93SAndreas Hindborg //! `start` operation. 698a8afe93SAndreas Hindborg 70*aa33de03SAndreas Hindborg use super::ClockId; 718a8afe93SAndreas Hindborg use crate::{prelude::*, time::Ktime, types::Opaque}; 728a8afe93SAndreas Hindborg use core::marker::PhantomData; 738a8afe93SAndreas Hindborg use pin_init::PinInit; 748a8afe93SAndreas Hindborg 758a8afe93SAndreas Hindborg /// A timer backed by a C `struct hrtimer`. 768a8afe93SAndreas Hindborg /// 778a8afe93SAndreas Hindborg /// # Invariants 788a8afe93SAndreas Hindborg /// 798a8afe93SAndreas Hindborg /// * `self.timer` is initialized by `bindings::hrtimer_setup`. 808a8afe93SAndreas Hindborg #[pin_data] 818a8afe93SAndreas Hindborg #[repr(C)] 828a8afe93SAndreas Hindborg pub struct HrTimer<T> { 838a8afe93SAndreas Hindborg #[pin] 84bfa3a410SAndreas Hindborg timer: Opaque<bindings::hrtimer>, 858a8afe93SAndreas Hindborg mode: HrTimerMode, 868a8afe93SAndreas Hindborg _t: PhantomData<T>, 878a8afe93SAndreas Hindborg } 888a8afe93SAndreas Hindborg 898a8afe93SAndreas Hindborg // SAFETY: Ownership of an `HrTimer` can be moved to other threads and 908a8afe93SAndreas Hindborg // used/dropped from there. 918a8afe93SAndreas Hindborg unsafe impl<T> Send for HrTimer<T> {} 928a8afe93SAndreas Hindborg 938a8afe93SAndreas Hindborg // SAFETY: Timer operations are locked on the C side, so it is safe to operate 948a8afe93SAndreas Hindborg // on a timer from multiple threads. 958a8afe93SAndreas Hindborg unsafe impl<T> Sync for HrTimer<T> {} 968a8afe93SAndreas Hindborg 978a8afe93SAndreas Hindborg impl<T> HrTimer<T> { 98*aa33de03SAndreas Hindborg /// Return an initializer for a new timer instance. new(mode: HrTimerMode, clock: ClockId) -> impl PinInit<Self> where T: HrTimerCallback,998a8afe93SAndreas Hindborg pub fn new(mode: HrTimerMode, clock: ClockId) -> impl PinInit<Self> 1008a8afe93SAndreas Hindborg where 1018a8afe93SAndreas Hindborg T: HrTimerCallback, 1028a8afe93SAndreas Hindborg { 1038a8afe93SAndreas Hindborg pin_init!(Self { 1048a8afe93SAndreas Hindborg // INVARIANT: We initialize `timer` with `hrtimer_setup` below. 1058a8afe93SAndreas Hindborg timer <- Opaque::ffi_init(move |place: *mut bindings::hrtimer| { 1068a8afe93SAndreas Hindborg // SAFETY: By design of `pin_init!`, `place` is a pointer to a 1078a8afe93SAndreas Hindborg // live allocation. hrtimer_setup will initialize `place` and 1088a8afe93SAndreas Hindborg // does not require `place` to be initialized prior to the call. 1098a8afe93SAndreas Hindborg unsafe { 1108a8afe93SAndreas Hindborg bindings::hrtimer_setup( 1118a8afe93SAndreas Hindborg place, 112*aa33de03SAndreas Hindborg Some(T::Pointer::run), 113bfa3a410SAndreas Hindborg clock.into_c(), 1148a8afe93SAndreas Hindborg mode.into_c(), 1158a8afe93SAndreas Hindborg ); 1168a8afe93SAndreas Hindborg } 117bfa3a410SAndreas Hindborg }), 1188a8afe93SAndreas Hindborg mode: mode, 1198a8afe93SAndreas Hindborg _t: PhantomData, 1208a8afe93SAndreas Hindborg }) 1218a8afe93SAndreas Hindborg } 1228a8afe93SAndreas Hindborg 1238a8afe93SAndreas Hindborg /// Get a pointer to the contained `bindings::hrtimer`. 1248a8afe93SAndreas Hindborg /// 1258a8afe93SAndreas Hindborg /// This function is useful to get access to the value without creating 1268a8afe93SAndreas Hindborg /// intermediate references. 1278a8afe93SAndreas Hindborg /// 1288a8afe93SAndreas Hindborg /// # Safety 1298a8afe93SAndreas Hindborg /// 1308a8afe93SAndreas Hindborg /// `this` must point to a live allocation of at least the size of `Self`. raw_get(this: *const Self) -> *mut bindings::hrtimer1318a8afe93SAndreas Hindborg unsafe fn raw_get(this: *const Self) -> *mut bindings::hrtimer { 1328a8afe93SAndreas Hindborg // SAFETY: The field projection to `timer` does not go out of bounds, 1338a8afe93SAndreas Hindborg // because the caller of this function promises that `this` points to an 1348a8afe93SAndreas Hindborg // allocation of at least the size of `Self`. 1358a8afe93SAndreas Hindborg unsafe { Opaque::raw_get(core::ptr::addr_of!((*this).timer)) } 1368a8afe93SAndreas Hindborg } 1378a8afe93SAndreas Hindborg 1388a8afe93SAndreas Hindborg /// Cancel an initialized and potentially running timer. 1398a8afe93SAndreas Hindborg /// 1408a8afe93SAndreas Hindborg /// If the timer handler is running, this function will block until the 1418a8afe93SAndreas Hindborg /// handler returns. 1428a8afe93SAndreas Hindborg /// 1438a8afe93SAndreas Hindborg /// Note that the timer might be started by a concurrent start operation. If 1448a8afe93SAndreas Hindborg /// so, the timer might not be in the **stopped** state when this function 1458a8afe93SAndreas Hindborg /// returns. 1468a8afe93SAndreas Hindborg /// 1478a8afe93SAndreas Hindborg /// Users of the `HrTimer` API would not usually call this method directly. 1488a8afe93SAndreas Hindborg /// Instead they would use the safe [`HrTimerHandle::cancel`] on the handle 1498a8afe93SAndreas Hindborg /// returned when the timer was started. 1508a8afe93SAndreas Hindborg /// 1518a8afe93SAndreas Hindborg /// This function is useful to get access to the value without creating 1528a8afe93SAndreas Hindborg /// intermediate references. 1538a8afe93SAndreas Hindborg /// 1548a8afe93SAndreas Hindborg /// # Safety 1558a8afe93SAndreas Hindborg /// 1568a8afe93SAndreas Hindborg /// `this` must point to a valid `Self`. raw_cancel(this: *const Self) -> bool1578a8afe93SAndreas Hindborg pub(crate) unsafe fn raw_cancel(this: *const Self) -> bool { 1588a8afe93SAndreas Hindborg // SAFETY: `this` points to an allocation of at least `HrTimer` size. 1598a8afe93SAndreas Hindborg let c_timer_ptr = unsafe { HrTimer::raw_get(this) }; 1608a8afe93SAndreas Hindborg 1618a8afe93SAndreas Hindborg // If the handler is running, this will wait for the handler to return 1628a8afe93SAndreas Hindborg // before returning. 1638a8afe93SAndreas Hindborg // SAFETY: `c_timer_ptr` is initialized and valid. Synchronization is 1648a8afe93SAndreas Hindborg // handled on the C side. 1658a8afe93SAndreas Hindborg unsafe { bindings::hrtimer_cancel(c_timer_ptr) != 0 } 1668a8afe93SAndreas Hindborg } 1678a8afe93SAndreas Hindborg } 1688a8afe93SAndreas Hindborg 1698a8afe93SAndreas Hindborg /// Implemented by pointer types that point to structs that contain a [`HrTimer`]. 1708a8afe93SAndreas Hindborg /// 1718a8afe93SAndreas Hindborg /// `Self` must be [`Sync`] because it is passed to timer callbacks in another 1728a8afe93SAndreas Hindborg /// thread of execution (hard or soft interrupt context). 1738a8afe93SAndreas Hindborg /// 1748a8afe93SAndreas Hindborg /// Starting a timer returns a [`HrTimerHandle`] that can be used to manipulate 1758a8afe93SAndreas Hindborg /// the timer. Note that it is OK to call the start function repeatedly, and 1768a8afe93SAndreas Hindborg /// that more than one [`HrTimerHandle`] associated with a [`HrTimerPointer`] may 1778a8afe93SAndreas Hindborg /// exist. A timer can be manipulated through any of the handles, and a handle 1788a8afe93SAndreas Hindborg /// may represent a cancelled timer. 1798a8afe93SAndreas Hindborg pub trait HrTimerPointer: Sync + Sized { 1808a8afe93SAndreas Hindborg /// A handle representing a started or restarted timer. 1818a8afe93SAndreas Hindborg /// 1828a8afe93SAndreas Hindborg /// If the timer is running or if the timer callback is executing when the 1838a8afe93SAndreas Hindborg /// handle is dropped, the drop method of [`HrTimerHandle`] should not return 1848a8afe93SAndreas Hindborg /// until the timer is stopped and the callback has completed. 1858a8afe93SAndreas Hindborg /// 1868a8afe93SAndreas Hindborg /// Note: When implementing this trait, consider that it is not unsafe to 1878a8afe93SAndreas Hindborg /// leak the handle. 1888a8afe93SAndreas Hindborg type TimerHandle: HrTimerHandle; 1898a8afe93SAndreas Hindborg 1908a8afe93SAndreas Hindborg /// Start the timer with expiry after `expires` time units. If the timer was 1918a8afe93SAndreas Hindborg /// already running, it is restarted with the new expiry time. start(self, expires: Ktime) -> Self::TimerHandle1928a8afe93SAndreas Hindborg fn start(self, expires: Ktime) -> Self::TimerHandle; 1938a8afe93SAndreas Hindborg } 194a6968ce3SAndreas Hindborg 195a6968ce3SAndreas Hindborg /// Unsafe version of [`HrTimerPointer`] for situations where leaking the 196a6968ce3SAndreas Hindborg /// [`HrTimerHandle`] returned by `start` would be unsound. This is the case for 197a6968ce3SAndreas Hindborg /// stack allocated timers. 198a6968ce3SAndreas Hindborg /// 199a6968ce3SAndreas Hindborg /// Typical implementers are pinned references such as [`Pin<&T>`]. 200a6968ce3SAndreas Hindborg /// 201a6968ce3SAndreas Hindborg /// # Safety 202a6968ce3SAndreas Hindborg /// 203a6968ce3SAndreas Hindborg /// Implementers of this trait must ensure that instances of types implementing 204a6968ce3SAndreas Hindborg /// [`UnsafeHrTimerPointer`] outlives any associated [`HrTimerPointer::TimerHandle`] 205a6968ce3SAndreas Hindborg /// instances. 206a6968ce3SAndreas Hindborg pub unsafe trait UnsafeHrTimerPointer: Sync + Sized { 207a6968ce3SAndreas Hindborg /// A handle representing a running timer. 208a6968ce3SAndreas Hindborg /// 209a6968ce3SAndreas Hindborg /// # Safety 210a6968ce3SAndreas Hindborg /// 211a6968ce3SAndreas Hindborg /// If the timer is running, or if the timer callback is executing when the 212a6968ce3SAndreas Hindborg /// handle is dropped, the drop method of [`Self::TimerHandle`] must not return 213a6968ce3SAndreas Hindborg /// until the timer is stopped and the callback has completed. 214a6968ce3SAndreas Hindborg type TimerHandle: HrTimerHandle; 215a6968ce3SAndreas Hindborg 216a6968ce3SAndreas Hindborg /// Start the timer after `expires` time units. If the timer was already 217a6968ce3SAndreas Hindborg /// running, it is restarted at the new expiry time. 218a6968ce3SAndreas Hindborg /// 219a6968ce3SAndreas Hindborg /// # Safety 220a6968ce3SAndreas Hindborg /// 221a6968ce3SAndreas Hindborg /// Caller promises keep the timer structure alive until the timer is dead. 222a6968ce3SAndreas Hindborg /// Caller can ensure this by not leaking the returned [`Self::TimerHandle`]. start(self, expires: Ktime) -> Self::TimerHandle223a6968ce3SAndreas Hindborg unsafe fn start(self, expires: Ktime) -> Self::TimerHandle; 224a6968ce3SAndreas Hindborg } 225f93b0d83SAndreas Hindborg 226f93b0d83SAndreas Hindborg /// A trait for stack allocated timers. 227f93b0d83SAndreas Hindborg /// 228f93b0d83SAndreas Hindborg /// # Safety 229f93b0d83SAndreas Hindborg /// 230f93b0d83SAndreas Hindborg /// Implementers must ensure that `start_scoped` does not return until the 231f93b0d83SAndreas Hindborg /// timer is dead and the timer handler is not running. 232f93b0d83SAndreas Hindborg pub unsafe trait ScopedHrTimerPointer { 233f93b0d83SAndreas Hindborg /// Start the timer to run after `expires` time units and immediately 234f93b0d83SAndreas Hindborg /// after call `f`. When `f` returns, the timer is cancelled. start_scoped<T, F>(self, expires: Ktime, f: F) -> T where F: FnOnce() -> T235f93b0d83SAndreas Hindborg fn start_scoped<T, F>(self, expires: Ktime, f: F) -> T 236f93b0d83SAndreas Hindborg where 237f93b0d83SAndreas Hindborg F: FnOnce() -> T; 238f93b0d83SAndreas Hindborg } 239f93b0d83SAndreas Hindborg 240f93b0d83SAndreas Hindborg // SAFETY: By the safety requirement of [`UnsafeHrTimerPointer`], dropping the 241f93b0d83SAndreas Hindborg // handle returned by [`UnsafeHrTimerPointer::start`] ensures that the timer is 242f93b0d83SAndreas Hindborg // killed. 243f93b0d83SAndreas Hindborg unsafe impl<T> ScopedHrTimerPointer for T 244f93b0d83SAndreas Hindborg where 245f93b0d83SAndreas Hindborg T: UnsafeHrTimerPointer, 246f93b0d83SAndreas Hindborg { start_scoped<U, F>(self, expires: Ktime, f: F) -> U where F: FnOnce() -> U,247f93b0d83SAndreas Hindborg fn start_scoped<U, F>(self, expires: Ktime, f: F) -> U 248f93b0d83SAndreas Hindborg where 249f93b0d83SAndreas Hindborg F: FnOnce() -> U, 250f93b0d83SAndreas Hindborg { 251f93b0d83SAndreas Hindborg // SAFETY: We drop the timer handle below before returning. 252f93b0d83SAndreas Hindborg let handle = unsafe { UnsafeHrTimerPointer::start(self, expires) }; 253f93b0d83SAndreas Hindborg let t = f(); 254f93b0d83SAndreas Hindborg drop(handle); 255f93b0d83SAndreas Hindborg t 256f93b0d83SAndreas Hindborg } 257f93b0d83SAndreas Hindborg } 2588a8afe93SAndreas Hindborg 2598a8afe93SAndreas Hindborg /// Implemented by [`HrTimerPointer`] implementers to give the C timer callback a 2608a8afe93SAndreas Hindborg /// function to call. 2618a8afe93SAndreas Hindborg // This is split from `HrTimerPointer` to make it easier to specify trait bounds. 2628a8afe93SAndreas Hindborg pub trait RawHrTimerCallback { 2638a8afe93SAndreas Hindborg /// Type of the parameter passed to [`HrTimerCallback::run`]. It may be 2648a8afe93SAndreas Hindborg /// [`Self`], or a pointer type derived from [`Self`]. 2658a8afe93SAndreas Hindborg type CallbackTarget<'a>; 2668a8afe93SAndreas Hindborg 2678a8afe93SAndreas Hindborg /// Callback to be called from C when timer fires. 2688a8afe93SAndreas Hindborg /// 2698a8afe93SAndreas Hindborg /// # Safety 2708a8afe93SAndreas Hindborg /// 2718a8afe93SAndreas Hindborg /// Only to be called by C code in the `hrtimer` subsystem. `this` must point 2728a8afe93SAndreas Hindborg /// to the `bindings::hrtimer` structure that was used to start the timer. run(this: *mut bindings::hrtimer) -> bindings::hrtimer_restart2738a8afe93SAndreas Hindborg unsafe extern "C" fn run(this: *mut bindings::hrtimer) -> bindings::hrtimer_restart; 2748a8afe93SAndreas Hindborg } 2758a8afe93SAndreas Hindborg 2768a8afe93SAndreas Hindborg /// Implemented by structs that can be the target of a timer callback. 2778a8afe93SAndreas Hindborg pub trait HrTimerCallback { 2788a8afe93SAndreas Hindborg /// The type whose [`RawHrTimerCallback::run`] method will be invoked when 2798a8afe93SAndreas Hindborg /// the timer expires. 2808a8afe93SAndreas Hindborg type Pointer<'a>: RawHrTimerCallback; 2818a8afe93SAndreas Hindborg 28294e05a66SAndreas Hindborg /// Called by the timer logic when the timer fires. run(this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>) -> HrTimerRestart where Self: Sized2838a8afe93SAndreas Hindborg fn run(this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>) -> HrTimerRestart 2848a8afe93SAndreas Hindborg where 2858a8afe93SAndreas Hindborg Self: Sized; 2868a8afe93SAndreas Hindborg } 2878a8afe93SAndreas Hindborg 2888a8afe93SAndreas Hindborg /// A handle representing a potentially running timer. 2898a8afe93SAndreas Hindborg /// 2908a8afe93SAndreas Hindborg /// More than one handle representing the same timer might exist. 2918a8afe93SAndreas Hindborg /// 2928a8afe93SAndreas Hindborg /// # Safety 2938a8afe93SAndreas Hindborg /// 2948a8afe93SAndreas Hindborg /// When dropped, the timer represented by this handle must be cancelled, if it 2958a8afe93SAndreas Hindborg /// is running. If the timer handler is running when the handle is dropped, the 2968a8afe93SAndreas Hindborg /// drop method must wait for the handler to return before returning. 2978a8afe93SAndreas Hindborg /// 2988a8afe93SAndreas Hindborg /// Note: One way to satisfy the safety requirement is to call `Self::cancel` in 2998a8afe93SAndreas Hindborg /// the drop implementation for `Self.` 3008a8afe93SAndreas Hindborg pub unsafe trait HrTimerHandle { 3018a8afe93SAndreas Hindborg /// Cancel the timer. If the timer is in the running state, block till the 3028a8afe93SAndreas Hindborg /// handler has returned. 3038a8afe93SAndreas Hindborg /// 3048a8afe93SAndreas Hindborg /// Note that the timer might be started by a concurrent start operation. If 3058a8afe93SAndreas Hindborg /// so, the timer might not be in the **stopped** state when this function 3068a8afe93SAndreas Hindborg /// returns. cancel(&mut self) -> bool3078a8afe93SAndreas Hindborg fn cancel(&mut self) -> bool; 3088a8afe93SAndreas Hindborg } 3098a8afe93SAndreas Hindborg 3108a8afe93SAndreas Hindborg /// Implemented by structs that contain timer nodes. 3118a8afe93SAndreas Hindborg /// 3128a8afe93SAndreas Hindborg /// Clients of the timer API would usually safely implement this trait by using 3138a8afe93SAndreas Hindborg /// the [`crate::impl_has_hr_timer`] macro. 3148a8afe93SAndreas Hindborg /// 3158a8afe93SAndreas Hindborg /// # Safety 3168a8afe93SAndreas Hindborg /// 3178a8afe93SAndreas Hindborg /// Implementers of this trait must ensure that the implementer has a 3188a8afe93SAndreas Hindborg /// [`HrTimer`] field and that all trait methods are implemented according to 3198a8afe93SAndreas Hindborg /// their documentation. All the methods of this trait must operate on the same 3208a8afe93SAndreas Hindborg /// field. 3218a8afe93SAndreas Hindborg pub unsafe trait HasHrTimer<T> { 3228a8afe93SAndreas Hindborg /// Return a pointer to the [`HrTimer`] within `Self`. 3238a8afe93SAndreas Hindborg /// 3248a8afe93SAndreas Hindborg /// This function is useful to get access to the value without creating 3258a8afe93SAndreas Hindborg /// intermediate references. 3268a8afe93SAndreas Hindborg /// 3278a8afe93SAndreas Hindborg /// # Safety 3288a8afe93SAndreas Hindborg /// 3298a8afe93SAndreas Hindborg /// `this` must be a valid pointer. raw_get_timer(this: *const Self) -> *const HrTimer<T>3308a8afe93SAndreas Hindborg unsafe fn raw_get_timer(this: *const Self) -> *const HrTimer<T>; 3318a8afe93SAndreas Hindborg 3328a8afe93SAndreas Hindborg /// Return a pointer to the struct that is containing the [`HrTimer`] pointed 3338a8afe93SAndreas Hindborg /// to by `ptr`. 3348a8afe93SAndreas Hindborg /// 3358a8afe93SAndreas Hindborg /// This function is useful to get access to the value without creating 3368a8afe93SAndreas Hindborg /// intermediate references. 3378a8afe93SAndreas Hindborg /// 3388a8afe93SAndreas Hindborg /// # Safety 3398a8afe93SAndreas Hindborg /// 3408a8afe93SAndreas Hindborg /// `ptr` must point to a [`HrTimer<T>`] field in a struct of type `Self`. timer_container_of(ptr: *mut HrTimer<T>) -> *mut Self where Self: Sized3418a8afe93SAndreas Hindborg unsafe fn timer_container_of(ptr: *mut HrTimer<T>) -> *mut Self 3428a8afe93SAndreas Hindborg where 3438a8afe93SAndreas Hindborg Self: Sized; 3448a8afe93SAndreas Hindborg 3458a8afe93SAndreas Hindborg /// Get pointer to the contained `bindings::hrtimer` struct. 3468a8afe93SAndreas Hindborg /// 3478a8afe93SAndreas Hindborg /// This function is useful to get access to the value without creating 3488a8afe93SAndreas Hindborg /// intermediate references. 3498a8afe93SAndreas Hindborg /// 3508a8afe93SAndreas Hindborg /// # Safety 3518a8afe93SAndreas Hindborg /// 3528a8afe93SAndreas Hindborg /// `this` must be a valid pointer. c_timer_ptr(this: *const Self) -> *const bindings::hrtimer3538a8afe93SAndreas Hindborg unsafe fn c_timer_ptr(this: *const Self) -> *const bindings::hrtimer { 3548a8afe93SAndreas Hindborg // SAFETY: `this` is a valid pointer to a `Self`. 3558a8afe93SAndreas Hindborg let timer_ptr = unsafe { Self::raw_get_timer(this) }; 3568a8afe93SAndreas Hindborg 3578a8afe93SAndreas Hindborg // SAFETY: timer_ptr points to an allocation of at least `HrTimer` size. 3588a8afe93SAndreas Hindborg unsafe { HrTimer::raw_get(timer_ptr) } 3598a8afe93SAndreas Hindborg } 3608a8afe93SAndreas Hindborg 3618a8afe93SAndreas Hindborg /// Start the timer contained in the `Self` pointed to by `self_ptr`. If 3628a8afe93SAndreas Hindborg /// it is already running it is removed and inserted. 3638a8afe93SAndreas Hindborg /// 3648a8afe93SAndreas Hindborg /// # Safety 3658a8afe93SAndreas Hindborg /// 3668a8afe93SAndreas Hindborg /// - `this` must point to a valid `Self`. 3678a8afe93SAndreas Hindborg /// - Caller must ensure that the pointee of `this` lives until the timer 3688a8afe93SAndreas Hindborg /// fires or is canceled. start(this: *const Self, expires: Ktime)3698a8afe93SAndreas Hindborg unsafe fn start(this: *const Self, expires: Ktime) { 3708a8afe93SAndreas Hindborg // SAFETY: By function safety requirement, `this` is a valid `Self`. 3718a8afe93SAndreas Hindborg unsafe { 3728a8afe93SAndreas Hindborg bindings::hrtimer_start_range_ns( 3738a8afe93SAndreas Hindborg Self::c_timer_ptr(this).cast_mut(), 3748a8afe93SAndreas Hindborg expires.to_ns(), 375bfa3a410SAndreas Hindborg 0, 3768a8afe93SAndreas Hindborg (*Self::raw_get_timer(this)).mode.into_c(), 3778a8afe93SAndreas Hindborg ); 3788a8afe93SAndreas Hindborg } 3798a8afe93SAndreas Hindborg } 3808a8afe93SAndreas Hindborg } 38194e05a66SAndreas Hindborg 38294e05a66SAndreas Hindborg /// Restart policy for timers. 38394e05a66SAndreas Hindborg #[derive(Copy, Clone, PartialEq, Eq, Debug)] 38494e05a66SAndreas Hindborg #[repr(u32)] 38594e05a66SAndreas Hindborg pub enum HrTimerRestart { 38694e05a66SAndreas Hindborg /// Timer should not be restarted. 38794e05a66SAndreas Hindborg #[allow(clippy::unnecessary_cast)] 38894e05a66SAndreas Hindborg NoRestart = bindings::hrtimer_restart_HRTIMER_NORESTART as u32, 38994e05a66SAndreas Hindborg /// Timer should be restarted. 39094e05a66SAndreas Hindborg #[allow(clippy::unnecessary_cast)] 39194e05a66SAndreas Hindborg Restart = bindings::hrtimer_restart_HRTIMER_RESTART as u32, 39294e05a66SAndreas Hindborg } 39394e05a66SAndreas Hindborg 39494e05a66SAndreas Hindborg impl HrTimerRestart { into_c(self) -> bindings::hrtimer_restart39594e05a66SAndreas Hindborg fn into_c(self) -> bindings::hrtimer_restart { 39694e05a66SAndreas Hindborg self as bindings::hrtimer_restart 39794e05a66SAndreas Hindborg } 39894e05a66SAndreas Hindborg } 399bfa3a410SAndreas Hindborg 400bfa3a410SAndreas Hindborg /// Operational mode of [`HrTimer`]. 401bfa3a410SAndreas Hindborg // NOTE: Some of these have the same encoding on the C side, so we keep 402bfa3a410SAndreas Hindborg // `repr(Rust)` and convert elsewhere. 403bfa3a410SAndreas Hindborg #[derive(Clone, Copy, PartialEq, Eq, Debug)] 404bfa3a410SAndreas Hindborg pub enum HrTimerMode { 405bfa3a410SAndreas Hindborg /// Timer expires at the given expiration time. 406bfa3a410SAndreas Hindborg Absolute, 407bfa3a410SAndreas Hindborg /// Timer expires after the given expiration time interpreted as a duration from now. 408bfa3a410SAndreas Hindborg Relative, 409bfa3a410SAndreas Hindborg /// Timer does not move between CPU cores. 410bfa3a410SAndreas Hindborg Pinned, 411bfa3a410SAndreas Hindborg /// Timer handler is executed in soft irq context. 412bfa3a410SAndreas Hindborg Soft, 413bfa3a410SAndreas Hindborg /// Timer handler is executed in hard irq context. 414bfa3a410SAndreas Hindborg Hard, 415bfa3a410SAndreas Hindborg /// Timer expires at the given expiration time. 416bfa3a410SAndreas Hindborg /// Timer does not move between CPU cores. 417bfa3a410SAndreas Hindborg AbsolutePinned, 418bfa3a410SAndreas Hindborg /// Timer expires after the given expiration time interpreted as a duration from now. 419bfa3a410SAndreas Hindborg /// Timer does not move between CPU cores. 420bfa3a410SAndreas Hindborg RelativePinned, 421bfa3a410SAndreas Hindborg /// Timer expires at the given expiration time. 422bfa3a410SAndreas Hindborg /// Timer handler is executed in soft irq context. 423bfa3a410SAndreas Hindborg AbsoluteSoft, 424bfa3a410SAndreas Hindborg /// Timer expires after the given expiration time interpreted as a duration from now. 425bfa3a410SAndreas Hindborg /// Timer handler is executed in soft irq context. 426bfa3a410SAndreas Hindborg RelativeSoft, 427bfa3a410SAndreas Hindborg /// Timer expires at the given expiration time. 428bfa3a410SAndreas Hindborg /// Timer does not move between CPU cores. 429bfa3a410SAndreas Hindborg /// Timer handler is executed in soft irq context. 430bfa3a410SAndreas Hindborg AbsolutePinnedSoft, 431bfa3a410SAndreas Hindborg /// Timer expires after the given expiration time interpreted as a duration from now. 432bfa3a410SAndreas Hindborg /// Timer does not move between CPU cores. 433bfa3a410SAndreas Hindborg /// Timer handler is executed in soft irq context. 434bfa3a410SAndreas Hindborg RelativePinnedSoft, 435bfa3a410SAndreas Hindborg /// Timer expires at the given expiration time. 436bfa3a410SAndreas Hindborg /// Timer handler is executed in hard irq context. 437bfa3a410SAndreas Hindborg AbsoluteHard, 438bfa3a410SAndreas Hindborg /// Timer expires after the given expiration time interpreted as a duration from now. 439bfa3a410SAndreas Hindborg /// Timer handler is executed in hard irq context. 440bfa3a410SAndreas Hindborg RelativeHard, 441bfa3a410SAndreas Hindborg /// Timer expires at the given expiration time. 442bfa3a410SAndreas Hindborg /// Timer does not move between CPU cores. 443bfa3a410SAndreas Hindborg /// Timer handler is executed in hard irq context. 444bfa3a410SAndreas Hindborg AbsolutePinnedHard, 445bfa3a410SAndreas Hindborg /// Timer expires after the given expiration time interpreted as a duration from now. 446bfa3a410SAndreas Hindborg /// Timer does not move between CPU cores. 447bfa3a410SAndreas Hindborg /// Timer handler is executed in hard irq context. 448bfa3a410SAndreas Hindborg RelativePinnedHard, 449bfa3a410SAndreas Hindborg } 450bfa3a410SAndreas Hindborg 451bfa3a410SAndreas Hindborg impl HrTimerMode { into_c(self) -> bindings::hrtimer_mode452bfa3a410SAndreas Hindborg fn into_c(self) -> bindings::hrtimer_mode { 453bfa3a410SAndreas Hindborg use bindings::*; 454bfa3a410SAndreas Hindborg match self { 455bfa3a410SAndreas Hindborg HrTimerMode::Absolute => hrtimer_mode_HRTIMER_MODE_ABS, 456bfa3a410SAndreas Hindborg HrTimerMode::Relative => hrtimer_mode_HRTIMER_MODE_REL, 457bfa3a410SAndreas Hindborg HrTimerMode::Pinned => hrtimer_mode_HRTIMER_MODE_PINNED, 458bfa3a410SAndreas Hindborg HrTimerMode::Soft => hrtimer_mode_HRTIMER_MODE_SOFT, 459bfa3a410SAndreas Hindborg HrTimerMode::Hard => hrtimer_mode_HRTIMER_MODE_HARD, 460bfa3a410SAndreas Hindborg HrTimerMode::AbsolutePinned => hrtimer_mode_HRTIMER_MODE_ABS_PINNED, 461bfa3a410SAndreas Hindborg HrTimerMode::RelativePinned => hrtimer_mode_HRTIMER_MODE_REL_PINNED, 462bfa3a410SAndreas Hindborg HrTimerMode::AbsoluteSoft => hrtimer_mode_HRTIMER_MODE_ABS_SOFT, 463bfa3a410SAndreas Hindborg HrTimerMode::RelativeSoft => hrtimer_mode_HRTIMER_MODE_REL_SOFT, 464bfa3a410SAndreas Hindborg HrTimerMode::AbsolutePinnedSoft => hrtimer_mode_HRTIMER_MODE_ABS_PINNED_SOFT, 465bfa3a410SAndreas Hindborg HrTimerMode::RelativePinnedSoft => hrtimer_mode_HRTIMER_MODE_REL_PINNED_SOFT, 466bfa3a410SAndreas Hindborg HrTimerMode::AbsoluteHard => hrtimer_mode_HRTIMER_MODE_ABS_HARD, 467bfa3a410SAndreas Hindborg HrTimerMode::RelativeHard => hrtimer_mode_HRTIMER_MODE_REL_HARD, 468bfa3a410SAndreas Hindborg HrTimerMode::AbsolutePinnedHard => hrtimer_mode_HRTIMER_MODE_ABS_PINNED_HARD, 469bfa3a410SAndreas Hindborg HrTimerMode::RelativePinnedHard => hrtimer_mode_HRTIMER_MODE_REL_PINNED_HARD, 470bfa3a410SAndreas Hindborg } 471bfa3a410SAndreas Hindborg } 472bfa3a410SAndreas Hindborg } 4738a8afe93SAndreas Hindborg 4748a8afe93SAndreas Hindborg /// Use to implement the [`HasHrTimer<T>`] trait. 4758a8afe93SAndreas Hindborg /// 4768a8afe93SAndreas Hindborg /// See [`module`] documentation for an example. 4778a8afe93SAndreas Hindborg /// 4788a8afe93SAndreas Hindborg /// [`module`]: crate::time::hrtimer 4798a8afe93SAndreas Hindborg #[macro_export] 4808a8afe93SAndreas Hindborg macro_rules! impl_has_hr_timer { 4818a8afe93SAndreas Hindborg ( 4828a8afe93SAndreas Hindborg impl$({$($generics:tt)*})? 4838a8afe93SAndreas Hindborg HasHrTimer<$timer_type:ty> 4848a8afe93SAndreas Hindborg for $self:ty 4858a8afe93SAndreas Hindborg { self.$field:ident } 4868a8afe93SAndreas Hindborg $($rest:tt)* 4878a8afe93SAndreas Hindborg ) => { 4888a8afe93SAndreas Hindborg // SAFETY: This implementation of `raw_get_timer` only compiles if the 4898a8afe93SAndreas Hindborg // field has the right type. 4908a8afe93SAndreas Hindborg unsafe impl$(<$($generics)*>)? $crate::time::hrtimer::HasHrTimer<$timer_type> for $self { 4918a8afe93SAndreas Hindborg 4928a8afe93SAndreas Hindborg #[inline] 4938a8afe93SAndreas Hindborg unsafe fn raw_get_timer( 4948a8afe93SAndreas Hindborg this: *const Self, 4958a8afe93SAndreas Hindborg ) -> *const $crate::time::hrtimer::HrTimer<$timer_type> { 4968a8afe93SAndreas Hindborg // SAFETY: The caller promises that the pointer is not dangling. 4978a8afe93SAndreas Hindborg unsafe { ::core::ptr::addr_of!((*this).$field) } 4988a8afe93SAndreas Hindborg } 4998a8afe93SAndreas Hindborg 5008a8afe93SAndreas Hindborg #[inline] 5018a8afe93SAndreas Hindborg unsafe fn timer_container_of( 5028a8afe93SAndreas Hindborg ptr: *mut $crate::time::hrtimer::HrTimer<$timer_type>, 5038a8afe93SAndreas Hindborg ) -> *mut Self { 5048a8afe93SAndreas Hindborg // SAFETY: As per the safety requirement of this function, `ptr` 5058a8afe93SAndreas Hindborg // is pointing inside a `$timer_type`. 5068a8afe93SAndreas Hindborg unsafe { ::kernel::container_of!(ptr, $timer_type, $field).cast_mut() } 5078a8afe93SAndreas Hindborg } 5088a8afe93SAndreas Hindborg } 5098a8afe93SAndreas Hindborg } 510d7bf4786SAndreas Hindborg } 511d7bf4786SAndreas Hindborg 512d7bf4786SAndreas Hindborg mod arc; 513582523d9SAndreas Hindborg pub use arc::ArcHrTimerHandle; 514582523d9SAndreas Hindborg mod pin; 515042b0c79SAndreas Hindborg pub use pin::PinHrTimerHandle; 516042b0c79SAndreas Hindborg mod pin_mut; 517374b60a0SAndreas Hindborg pub use pin_mut::PinMutHrTimerHandle; 518374b60a0SAndreas Hindborg // `box` is a reserved keyword, so prefix with `t` for timer 519374b60a0SAndreas Hindborg mod tbox; 520 pub use tbox::BoxHrTimerHandle; 521