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 70aa33de03SAndreas Hindborg use super::ClockId; 711116f0c5SFUJITA Tomonori use crate::{prelude::*, types::Opaque}; 728a8afe93SAndreas Hindborg use core::marker::PhantomData; 73e6ea10d5SMiguel Ojeda use pin_init::PinInit; 748a8afe93SAndreas Hindborg 751116f0c5SFUJITA Tomonori /// A Rust wrapper around a `ktime_t`. 761116f0c5SFUJITA Tomonori // NOTE: Ktime is going to be removed when hrtimer is converted to Instant/Delta. 771116f0c5SFUJITA Tomonori #[repr(transparent)] 781116f0c5SFUJITA Tomonori #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)] 791116f0c5SFUJITA Tomonori pub struct Ktime { 801116f0c5SFUJITA Tomonori inner: bindings::ktime_t, 811116f0c5SFUJITA Tomonori } 821116f0c5SFUJITA Tomonori 831116f0c5SFUJITA Tomonori impl Ktime { 841116f0c5SFUJITA Tomonori /// Returns the number of nanoseconds. 851116f0c5SFUJITA Tomonori #[inline] to_ns(self) -> i64861116f0c5SFUJITA Tomonori pub fn to_ns(self) -> i64 { 871116f0c5SFUJITA Tomonori self.inner 881116f0c5SFUJITA Tomonori } 891116f0c5SFUJITA Tomonori } 901116f0c5SFUJITA Tomonori 918a8afe93SAndreas Hindborg /// A timer backed by a C `struct hrtimer`. 928a8afe93SAndreas Hindborg /// 938a8afe93SAndreas Hindborg /// # Invariants 948a8afe93SAndreas Hindborg /// 958a8afe93SAndreas Hindborg /// * `self.timer` is initialized by `bindings::hrtimer_setup`. 968a8afe93SAndreas Hindborg #[pin_data] 978a8afe93SAndreas Hindborg #[repr(C)] 988a8afe93SAndreas Hindborg pub struct HrTimer<T> { 998a8afe93SAndreas Hindborg #[pin] 1008a8afe93SAndreas Hindborg timer: Opaque<bindings::hrtimer>, 101bfa3a410SAndreas Hindborg mode: HrTimerMode, 1028a8afe93SAndreas Hindborg _t: PhantomData<T>, 1038a8afe93SAndreas Hindborg } 1048a8afe93SAndreas Hindborg 1058a8afe93SAndreas Hindborg // SAFETY: Ownership of an `HrTimer` can be moved to other threads and 1068a8afe93SAndreas Hindborg // used/dropped from there. 1078a8afe93SAndreas Hindborg unsafe impl<T> Send for HrTimer<T> {} 1088a8afe93SAndreas Hindborg 1098a8afe93SAndreas Hindborg // SAFETY: Timer operations are locked on the C side, so it is safe to operate 1108a8afe93SAndreas Hindborg // on a timer from multiple threads. 1118a8afe93SAndreas Hindborg unsafe impl<T> Sync for HrTimer<T> {} 1128a8afe93SAndreas Hindborg 1138a8afe93SAndreas Hindborg impl<T> HrTimer<T> { 1148a8afe93SAndreas Hindborg /// Return an initializer for a new timer instance. new(mode: HrTimerMode, clock: ClockId) -> impl PinInit<Self> where T: HrTimerCallback,115aa33de03SAndreas Hindborg pub fn new(mode: HrTimerMode, clock: ClockId) -> impl PinInit<Self> 1168a8afe93SAndreas Hindborg where 1178a8afe93SAndreas Hindborg T: HrTimerCallback, 1188a8afe93SAndreas Hindborg { 1198a8afe93SAndreas Hindborg pin_init!(Self { 1208a8afe93SAndreas Hindborg // INVARIANT: We initialize `timer` with `hrtimer_setup` below. 1218a8afe93SAndreas Hindborg timer <- Opaque::ffi_init(move |place: *mut bindings::hrtimer| { 1228a8afe93SAndreas Hindborg // SAFETY: By design of `pin_init!`, `place` is a pointer to a 1238a8afe93SAndreas Hindborg // live allocation. hrtimer_setup will initialize `place` and 1248a8afe93SAndreas Hindborg // does not require `place` to be initialized prior to the call. 1258a8afe93SAndreas Hindborg unsafe { 1268a8afe93SAndreas Hindborg bindings::hrtimer_setup( 1278a8afe93SAndreas Hindborg place, 1288a8afe93SAndreas Hindborg Some(T::Pointer::run), 129aa33de03SAndreas Hindborg clock.into_c(), 130bfa3a410SAndreas Hindborg mode.into_c(), 1318a8afe93SAndreas Hindborg ); 1328a8afe93SAndreas Hindborg } 1338a8afe93SAndreas Hindborg }), 134bfa3a410SAndreas Hindborg mode: mode, 1358a8afe93SAndreas Hindborg _t: PhantomData, 1368a8afe93SAndreas Hindborg }) 1378a8afe93SAndreas Hindborg } 1388a8afe93SAndreas Hindborg 1398a8afe93SAndreas Hindborg /// Get a pointer to the contained `bindings::hrtimer`. 1408a8afe93SAndreas Hindborg /// 1418a8afe93SAndreas Hindborg /// This function is useful to get access to the value without creating 1428a8afe93SAndreas Hindborg /// intermediate references. 1438a8afe93SAndreas Hindborg /// 1448a8afe93SAndreas Hindborg /// # Safety 1458a8afe93SAndreas Hindborg /// 1468a8afe93SAndreas Hindborg /// `this` must point to a live allocation of at least the size of `Self`. raw_get(this: *const Self) -> *mut bindings::hrtimer1478a8afe93SAndreas Hindborg unsafe fn raw_get(this: *const Self) -> *mut bindings::hrtimer { 1488a8afe93SAndreas Hindborg // SAFETY: The field projection to `timer` does not go out of bounds, 1498a8afe93SAndreas Hindborg // because the caller of this function promises that `this` points to an 1508a8afe93SAndreas Hindborg // allocation of at least the size of `Self`. 1518a8afe93SAndreas Hindborg unsafe { Opaque::raw_get(core::ptr::addr_of!((*this).timer)) } 1528a8afe93SAndreas Hindborg } 1538a8afe93SAndreas Hindborg 1548a8afe93SAndreas Hindborg /// Cancel an initialized and potentially running timer. 1558a8afe93SAndreas Hindborg /// 1568a8afe93SAndreas Hindborg /// If the timer handler is running, this function will block until the 1578a8afe93SAndreas Hindborg /// handler returns. 1588a8afe93SAndreas Hindborg /// 1598a8afe93SAndreas Hindborg /// Note that the timer might be started by a concurrent start operation. If 1608a8afe93SAndreas Hindborg /// so, the timer might not be in the **stopped** state when this function 1618a8afe93SAndreas Hindborg /// returns. 1628a8afe93SAndreas Hindborg /// 1638a8afe93SAndreas Hindborg /// Users of the `HrTimer` API would not usually call this method directly. 1648a8afe93SAndreas Hindborg /// Instead they would use the safe [`HrTimerHandle::cancel`] on the handle 1658a8afe93SAndreas Hindborg /// returned when the timer was started. 1668a8afe93SAndreas Hindborg /// 1678a8afe93SAndreas Hindborg /// This function is useful to get access to the value without creating 1688a8afe93SAndreas Hindborg /// intermediate references. 1698a8afe93SAndreas Hindborg /// 1708a8afe93SAndreas Hindborg /// # Safety 1718a8afe93SAndreas Hindborg /// 1728a8afe93SAndreas Hindborg /// `this` must point to a valid `Self`. raw_cancel(this: *const Self) -> bool1738a8afe93SAndreas Hindborg pub(crate) unsafe fn raw_cancel(this: *const Self) -> bool { 1748a8afe93SAndreas Hindborg // SAFETY: `this` points to an allocation of at least `HrTimer` size. 1758a8afe93SAndreas Hindborg let c_timer_ptr = unsafe { HrTimer::raw_get(this) }; 1768a8afe93SAndreas Hindborg 1778a8afe93SAndreas Hindborg // If the handler is running, this will wait for the handler to return 1788a8afe93SAndreas Hindborg // before returning. 1798a8afe93SAndreas Hindborg // SAFETY: `c_timer_ptr` is initialized and valid. Synchronization is 1808a8afe93SAndreas Hindborg // handled on the C side. 1818a8afe93SAndreas Hindborg unsafe { bindings::hrtimer_cancel(c_timer_ptr) != 0 } 1828a8afe93SAndreas Hindborg } 1838a8afe93SAndreas Hindborg } 1848a8afe93SAndreas Hindborg 1858a8afe93SAndreas Hindborg /// Implemented by pointer types that point to structs that contain a [`HrTimer`]. 1868a8afe93SAndreas Hindborg /// 1878a8afe93SAndreas Hindborg /// `Self` must be [`Sync`] because it is passed to timer callbacks in another 1888a8afe93SAndreas Hindborg /// thread of execution (hard or soft interrupt context). 1898a8afe93SAndreas Hindborg /// 1908a8afe93SAndreas Hindborg /// Starting a timer returns a [`HrTimerHandle`] that can be used to manipulate 1918a8afe93SAndreas Hindborg /// the timer. Note that it is OK to call the start function repeatedly, and 1928a8afe93SAndreas Hindborg /// that more than one [`HrTimerHandle`] associated with a [`HrTimerPointer`] may 1938a8afe93SAndreas Hindborg /// exist. A timer can be manipulated through any of the handles, and a handle 1948a8afe93SAndreas Hindborg /// may represent a cancelled timer. 1958a8afe93SAndreas Hindborg pub trait HrTimerPointer: Sync + Sized { 1968a8afe93SAndreas Hindborg /// A handle representing a started or restarted timer. 1978a8afe93SAndreas Hindborg /// 1988a8afe93SAndreas Hindborg /// If the timer is running or if the timer callback is executing when the 1998a8afe93SAndreas Hindborg /// handle is dropped, the drop method of [`HrTimerHandle`] should not return 2008a8afe93SAndreas Hindborg /// until the timer is stopped and the callback has completed. 2018a8afe93SAndreas Hindborg /// 2028a8afe93SAndreas Hindborg /// Note: When implementing this trait, consider that it is not unsafe to 2038a8afe93SAndreas Hindborg /// leak the handle. 2048a8afe93SAndreas Hindborg type TimerHandle: HrTimerHandle; 2058a8afe93SAndreas Hindborg 2068a8afe93SAndreas Hindborg /// Start the timer with expiry after `expires` time units. If the timer was 2078a8afe93SAndreas Hindborg /// already running, it is restarted with the new expiry time. start(self, expires: Ktime) -> Self::TimerHandle2088a8afe93SAndreas Hindborg fn start(self, expires: Ktime) -> Self::TimerHandle; 2098a8afe93SAndreas Hindborg } 2108a8afe93SAndreas Hindborg 211a6968ce3SAndreas Hindborg /// Unsafe version of [`HrTimerPointer`] for situations where leaking the 212a6968ce3SAndreas Hindborg /// [`HrTimerHandle`] returned by `start` would be unsound. This is the case for 213a6968ce3SAndreas Hindborg /// stack allocated timers. 214a6968ce3SAndreas Hindborg /// 215a6968ce3SAndreas Hindborg /// Typical implementers are pinned references such as [`Pin<&T>`]. 216a6968ce3SAndreas Hindborg /// 217a6968ce3SAndreas Hindborg /// # Safety 218a6968ce3SAndreas Hindborg /// 219a6968ce3SAndreas Hindborg /// Implementers of this trait must ensure that instances of types implementing 220a6968ce3SAndreas Hindborg /// [`UnsafeHrTimerPointer`] outlives any associated [`HrTimerPointer::TimerHandle`] 221a6968ce3SAndreas Hindborg /// instances. 222a6968ce3SAndreas Hindborg pub unsafe trait UnsafeHrTimerPointer: Sync + Sized { 223a6968ce3SAndreas Hindborg /// A handle representing a running timer. 224a6968ce3SAndreas Hindborg /// 225a6968ce3SAndreas Hindborg /// # Safety 226a6968ce3SAndreas Hindborg /// 227a6968ce3SAndreas Hindborg /// If the timer is running, or if the timer callback is executing when the 228a6968ce3SAndreas Hindborg /// handle is dropped, the drop method of [`Self::TimerHandle`] must not return 229a6968ce3SAndreas Hindborg /// until the timer is stopped and the callback has completed. 230a6968ce3SAndreas Hindborg type TimerHandle: HrTimerHandle; 231a6968ce3SAndreas Hindborg 232a6968ce3SAndreas Hindborg /// Start the timer after `expires` time units. If the timer was already 233a6968ce3SAndreas Hindborg /// running, it is restarted at the new expiry time. 234a6968ce3SAndreas Hindborg /// 235a6968ce3SAndreas Hindborg /// # Safety 236a6968ce3SAndreas Hindborg /// 237a6968ce3SAndreas Hindborg /// Caller promises keep the timer structure alive until the timer is dead. 238a6968ce3SAndreas Hindborg /// Caller can ensure this by not leaking the returned [`Self::TimerHandle`]. start(self, expires: Ktime) -> Self::TimerHandle239a6968ce3SAndreas Hindborg unsafe fn start(self, expires: Ktime) -> Self::TimerHandle; 240a6968ce3SAndreas Hindborg } 241a6968ce3SAndreas Hindborg 242f93b0d83SAndreas Hindborg /// A trait for stack allocated timers. 243f93b0d83SAndreas Hindborg /// 244f93b0d83SAndreas Hindborg /// # Safety 245f93b0d83SAndreas Hindborg /// 246f93b0d83SAndreas Hindborg /// Implementers must ensure that `start_scoped` does not return until the 247f93b0d83SAndreas Hindborg /// timer is dead and the timer handler is not running. 248f93b0d83SAndreas Hindborg pub unsafe trait ScopedHrTimerPointer { 249f93b0d83SAndreas Hindborg /// Start the timer to run after `expires` time units and immediately 250f93b0d83SAndreas Hindborg /// after call `f`. When `f` returns, the timer is cancelled. start_scoped<T, F>(self, expires: Ktime, f: F) -> T where F: FnOnce() -> T251f93b0d83SAndreas Hindborg fn start_scoped<T, F>(self, expires: Ktime, f: F) -> T 252f93b0d83SAndreas Hindborg where 253f93b0d83SAndreas Hindborg F: FnOnce() -> T; 254f93b0d83SAndreas Hindborg } 255f93b0d83SAndreas Hindborg 256f93b0d83SAndreas Hindborg // SAFETY: By the safety requirement of [`UnsafeHrTimerPointer`], dropping the 257f93b0d83SAndreas Hindborg // handle returned by [`UnsafeHrTimerPointer::start`] ensures that the timer is 258f93b0d83SAndreas Hindborg // killed. 259f93b0d83SAndreas Hindborg unsafe impl<T> ScopedHrTimerPointer for T 260f93b0d83SAndreas Hindborg where 261f93b0d83SAndreas Hindborg T: UnsafeHrTimerPointer, 262f93b0d83SAndreas Hindborg { start_scoped<U, F>(self, expires: Ktime, f: F) -> U where F: FnOnce() -> U,263f93b0d83SAndreas Hindborg fn start_scoped<U, F>(self, expires: Ktime, f: F) -> U 264f93b0d83SAndreas Hindborg where 265f93b0d83SAndreas Hindborg F: FnOnce() -> U, 266f93b0d83SAndreas Hindborg { 267f93b0d83SAndreas Hindborg // SAFETY: We drop the timer handle below before returning. 268f93b0d83SAndreas Hindborg let handle = unsafe { UnsafeHrTimerPointer::start(self, expires) }; 269f93b0d83SAndreas Hindborg let t = f(); 270f93b0d83SAndreas Hindborg drop(handle); 271f93b0d83SAndreas Hindborg t 272f93b0d83SAndreas Hindborg } 273f93b0d83SAndreas Hindborg } 274f93b0d83SAndreas Hindborg 2758a8afe93SAndreas Hindborg /// Implemented by [`HrTimerPointer`] implementers to give the C timer callback a 2768a8afe93SAndreas Hindborg /// function to call. 2778a8afe93SAndreas Hindborg // This is split from `HrTimerPointer` to make it easier to specify trait bounds. 2788a8afe93SAndreas Hindborg pub trait RawHrTimerCallback { 2798a8afe93SAndreas Hindborg /// Type of the parameter passed to [`HrTimerCallback::run`]. It may be 2808a8afe93SAndreas Hindborg /// [`Self`], or a pointer type derived from [`Self`]. 2818a8afe93SAndreas Hindborg type CallbackTarget<'a>; 2828a8afe93SAndreas Hindborg 2838a8afe93SAndreas Hindborg /// Callback to be called from C when timer fires. 2848a8afe93SAndreas Hindborg /// 2858a8afe93SAndreas Hindborg /// # Safety 2868a8afe93SAndreas Hindborg /// 2878a8afe93SAndreas Hindborg /// Only to be called by C code in the `hrtimer` subsystem. `this` must point 2888a8afe93SAndreas Hindborg /// to the `bindings::hrtimer` structure that was used to start the timer. run(this: *mut bindings::hrtimer) -> bindings::hrtimer_restart2898a8afe93SAndreas Hindborg unsafe extern "C" fn run(this: *mut bindings::hrtimer) -> bindings::hrtimer_restart; 2908a8afe93SAndreas Hindborg } 2918a8afe93SAndreas Hindborg 2928a8afe93SAndreas Hindborg /// Implemented by structs that can be the target of a timer callback. 2938a8afe93SAndreas Hindborg pub trait HrTimerCallback { 2948a8afe93SAndreas Hindborg /// The type whose [`RawHrTimerCallback::run`] method will be invoked when 2958a8afe93SAndreas Hindborg /// the timer expires. 2968a8afe93SAndreas Hindborg type Pointer<'a>: RawHrTimerCallback; 2978a8afe93SAndreas Hindborg 2988a8afe93SAndreas Hindborg /// Called by the timer logic when the timer fires. run(this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>) -> HrTimerRestart where Self: Sized29994e05a66SAndreas Hindborg fn run(this: <Self::Pointer<'_> as RawHrTimerCallback>::CallbackTarget<'_>) -> HrTimerRestart 3008a8afe93SAndreas Hindborg where 3018a8afe93SAndreas Hindborg Self: Sized; 3028a8afe93SAndreas Hindborg } 3038a8afe93SAndreas Hindborg 3048a8afe93SAndreas Hindborg /// A handle representing a potentially running timer. 3058a8afe93SAndreas Hindborg /// 3068a8afe93SAndreas Hindborg /// More than one handle representing the same timer might exist. 3078a8afe93SAndreas Hindborg /// 3088a8afe93SAndreas Hindborg /// # Safety 3098a8afe93SAndreas Hindborg /// 3108a8afe93SAndreas Hindborg /// When dropped, the timer represented by this handle must be cancelled, if it 3118a8afe93SAndreas Hindborg /// is running. If the timer handler is running when the handle is dropped, the 3128a8afe93SAndreas Hindborg /// drop method must wait for the handler to return before returning. 3138a8afe93SAndreas Hindborg /// 3148a8afe93SAndreas Hindborg /// Note: One way to satisfy the safety requirement is to call `Self::cancel` in 3158a8afe93SAndreas Hindborg /// the drop implementation for `Self.` 3168a8afe93SAndreas Hindborg pub unsafe trait HrTimerHandle { 3178a8afe93SAndreas Hindborg /// Cancel the timer. If the timer is in the running state, block till the 3188a8afe93SAndreas Hindborg /// handler has returned. 3198a8afe93SAndreas Hindborg /// 3208a8afe93SAndreas Hindborg /// Note that the timer might be started by a concurrent start operation. If 3218a8afe93SAndreas Hindborg /// so, the timer might not be in the **stopped** state when this function 3228a8afe93SAndreas Hindborg /// returns. cancel(&mut self) -> bool3238a8afe93SAndreas Hindborg fn cancel(&mut self) -> bool; 3248a8afe93SAndreas Hindborg } 3258a8afe93SAndreas Hindborg 3268a8afe93SAndreas Hindborg /// Implemented by structs that contain timer nodes. 3278a8afe93SAndreas Hindborg /// 3288a8afe93SAndreas Hindborg /// Clients of the timer API would usually safely implement this trait by using 3298a8afe93SAndreas Hindborg /// the [`crate::impl_has_hr_timer`] macro. 3308a8afe93SAndreas Hindborg /// 3318a8afe93SAndreas Hindborg /// # Safety 3328a8afe93SAndreas Hindborg /// 3338a8afe93SAndreas Hindborg /// Implementers of this trait must ensure that the implementer has a 3348a8afe93SAndreas Hindborg /// [`HrTimer`] field and that all trait methods are implemented according to 3358a8afe93SAndreas Hindborg /// their documentation. All the methods of this trait must operate on the same 3368a8afe93SAndreas Hindborg /// field. 3378a8afe93SAndreas Hindborg pub unsafe trait HasHrTimer<T> { 3388a8afe93SAndreas Hindborg /// Return a pointer to the [`HrTimer`] within `Self`. 3398a8afe93SAndreas Hindborg /// 3408a8afe93SAndreas Hindborg /// This function is useful to get access to the value without creating 3418a8afe93SAndreas Hindborg /// intermediate references. 3428a8afe93SAndreas Hindborg /// 3438a8afe93SAndreas Hindborg /// # Safety 3448a8afe93SAndreas Hindborg /// 3458a8afe93SAndreas Hindborg /// `this` must be a valid pointer. raw_get_timer(this: *const Self) -> *const HrTimer<T>3468a8afe93SAndreas Hindborg unsafe fn raw_get_timer(this: *const Self) -> *const HrTimer<T>; 3478a8afe93SAndreas Hindborg 3488a8afe93SAndreas Hindborg /// Return a pointer to the struct that is containing the [`HrTimer`] pointed 3498a8afe93SAndreas Hindborg /// to by `ptr`. 3508a8afe93SAndreas Hindborg /// 3518a8afe93SAndreas Hindborg /// This function is useful to get access to the value without creating 3528a8afe93SAndreas Hindborg /// intermediate references. 3538a8afe93SAndreas Hindborg /// 3548a8afe93SAndreas Hindborg /// # Safety 3558a8afe93SAndreas Hindborg /// 3568a8afe93SAndreas 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: Sized3578a8afe93SAndreas Hindborg unsafe fn timer_container_of(ptr: *mut HrTimer<T>) -> *mut Self 3588a8afe93SAndreas Hindborg where 3598a8afe93SAndreas Hindborg Self: Sized; 3608a8afe93SAndreas Hindborg 3618a8afe93SAndreas Hindborg /// Get pointer to the contained `bindings::hrtimer` struct. 3628a8afe93SAndreas Hindborg /// 3638a8afe93SAndreas Hindborg /// This function is useful to get access to the value without creating 3648a8afe93SAndreas Hindborg /// intermediate references. 3658a8afe93SAndreas Hindborg /// 3668a8afe93SAndreas Hindborg /// # Safety 3678a8afe93SAndreas Hindborg /// 3688a8afe93SAndreas Hindborg /// `this` must be a valid pointer. c_timer_ptr(this: *const Self) -> *const bindings::hrtimer3698a8afe93SAndreas Hindborg unsafe fn c_timer_ptr(this: *const Self) -> *const bindings::hrtimer { 3708a8afe93SAndreas Hindborg // SAFETY: `this` is a valid pointer to a `Self`. 3718a8afe93SAndreas Hindborg let timer_ptr = unsafe { Self::raw_get_timer(this) }; 3728a8afe93SAndreas Hindborg 3738a8afe93SAndreas Hindborg // SAFETY: timer_ptr points to an allocation of at least `HrTimer` size. 3748a8afe93SAndreas Hindborg unsafe { HrTimer::raw_get(timer_ptr) } 3758a8afe93SAndreas Hindborg } 3768a8afe93SAndreas Hindborg 3778a8afe93SAndreas Hindborg /// Start the timer contained in the `Self` pointed to by `self_ptr`. If 3788a8afe93SAndreas Hindborg /// it is already running it is removed and inserted. 3798a8afe93SAndreas Hindborg /// 3808a8afe93SAndreas Hindborg /// # Safety 3818a8afe93SAndreas Hindborg /// 3828a8afe93SAndreas Hindborg /// - `this` must point to a valid `Self`. 3838a8afe93SAndreas Hindborg /// - Caller must ensure that the pointee of `this` lives until the timer 3848a8afe93SAndreas Hindborg /// fires or is canceled. start(this: *const Self, expires: Ktime)3858a8afe93SAndreas Hindborg unsafe fn start(this: *const Self, expires: Ktime) { 3868a8afe93SAndreas Hindborg // SAFETY: By function safety requirement, `this` is a valid `Self`. 3878a8afe93SAndreas Hindborg unsafe { 3888a8afe93SAndreas Hindborg bindings::hrtimer_start_range_ns( 3898a8afe93SAndreas Hindborg Self::c_timer_ptr(this).cast_mut(), 3908a8afe93SAndreas Hindborg expires.to_ns(), 3918a8afe93SAndreas Hindborg 0, 392bfa3a410SAndreas Hindborg (*Self::raw_get_timer(this)).mode.into_c(), 3938a8afe93SAndreas Hindborg ); 3948a8afe93SAndreas Hindborg } 3958a8afe93SAndreas Hindborg } 3968a8afe93SAndreas Hindborg } 3978a8afe93SAndreas Hindborg 39894e05a66SAndreas Hindborg /// Restart policy for timers. 39994e05a66SAndreas Hindborg #[derive(Copy, Clone, PartialEq, Eq, Debug)] 40094e05a66SAndreas Hindborg #[repr(u32)] 40194e05a66SAndreas Hindborg pub enum HrTimerRestart { 40294e05a66SAndreas Hindborg /// Timer should not be restarted. 4038cbc95f9SMiguel Ojeda NoRestart = bindings::hrtimer_restart_HRTIMER_NORESTART, 40494e05a66SAndreas Hindborg /// Timer should be restarted. 4058cbc95f9SMiguel Ojeda Restart = bindings::hrtimer_restart_HRTIMER_RESTART, 40694e05a66SAndreas Hindborg } 40794e05a66SAndreas Hindborg 40894e05a66SAndreas Hindborg impl HrTimerRestart { into_c(self) -> bindings::hrtimer_restart40994e05a66SAndreas Hindborg fn into_c(self) -> bindings::hrtimer_restart { 41094e05a66SAndreas Hindborg self as bindings::hrtimer_restart 41194e05a66SAndreas Hindborg } 41294e05a66SAndreas Hindborg } 41394e05a66SAndreas Hindborg 414bfa3a410SAndreas Hindborg /// Operational mode of [`HrTimer`]. 415bfa3a410SAndreas Hindborg // NOTE: Some of these have the same encoding on the C side, so we keep 416bfa3a410SAndreas Hindborg // `repr(Rust)` and convert elsewhere. 417bfa3a410SAndreas Hindborg #[derive(Clone, Copy, PartialEq, Eq, Debug)] 418bfa3a410SAndreas Hindborg pub enum HrTimerMode { 419bfa3a410SAndreas Hindborg /// Timer expires at the given expiration time. 420bfa3a410SAndreas Hindborg Absolute, 421bfa3a410SAndreas Hindborg /// Timer expires after the given expiration time interpreted as a duration from now. 422bfa3a410SAndreas Hindborg Relative, 423bfa3a410SAndreas Hindborg /// Timer does not move between CPU cores. 424bfa3a410SAndreas Hindborg Pinned, 425bfa3a410SAndreas Hindborg /// Timer handler is executed in soft irq context. 426bfa3a410SAndreas Hindborg Soft, 427bfa3a410SAndreas Hindborg /// Timer handler is executed in hard irq context. 428bfa3a410SAndreas Hindborg Hard, 429bfa3a410SAndreas Hindborg /// Timer expires at the given expiration time. 430bfa3a410SAndreas Hindborg /// Timer does not move between CPU cores. 431bfa3a410SAndreas Hindborg AbsolutePinned, 432bfa3a410SAndreas Hindborg /// Timer expires after the given expiration time interpreted as a duration from now. 433bfa3a410SAndreas Hindborg /// Timer does not move between CPU cores. 434bfa3a410SAndreas Hindborg RelativePinned, 435bfa3a410SAndreas Hindborg /// Timer expires at the given expiration time. 436bfa3a410SAndreas Hindborg /// Timer handler is executed in soft irq context. 437bfa3a410SAndreas Hindborg AbsoluteSoft, 438bfa3a410SAndreas Hindborg /// Timer expires after the given expiration time interpreted as a duration from now. 439bfa3a410SAndreas Hindborg /// Timer handler is executed in soft irq context. 440bfa3a410SAndreas Hindborg RelativeSoft, 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 soft irq context. 444bfa3a410SAndreas Hindborg AbsolutePinnedSoft, 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 soft irq context. 448bfa3a410SAndreas Hindborg RelativePinnedSoft, 449bfa3a410SAndreas Hindborg /// Timer expires at the given expiration time. 450bfa3a410SAndreas Hindborg /// Timer handler is executed in hard irq context. 451bfa3a410SAndreas Hindborg AbsoluteHard, 452bfa3a410SAndreas Hindborg /// Timer expires after the given expiration time interpreted as a duration from now. 453bfa3a410SAndreas Hindborg /// Timer handler is executed in hard irq context. 454bfa3a410SAndreas Hindborg RelativeHard, 455bfa3a410SAndreas Hindborg /// Timer expires at the given expiration time. 456bfa3a410SAndreas Hindborg /// Timer does not move between CPU cores. 457bfa3a410SAndreas Hindborg /// Timer handler is executed in hard irq context. 458bfa3a410SAndreas Hindborg AbsolutePinnedHard, 459bfa3a410SAndreas Hindborg /// Timer expires after the given expiration time interpreted as a duration from now. 460bfa3a410SAndreas Hindborg /// Timer does not move between CPU cores. 461bfa3a410SAndreas Hindborg /// Timer handler is executed in hard irq context. 462bfa3a410SAndreas Hindborg RelativePinnedHard, 463bfa3a410SAndreas Hindborg } 464bfa3a410SAndreas Hindborg 465bfa3a410SAndreas Hindborg impl HrTimerMode { into_c(self) -> bindings::hrtimer_mode466bfa3a410SAndreas Hindborg fn into_c(self) -> bindings::hrtimer_mode { 467bfa3a410SAndreas Hindborg use bindings::*; 468bfa3a410SAndreas Hindborg match self { 469bfa3a410SAndreas Hindborg HrTimerMode::Absolute => hrtimer_mode_HRTIMER_MODE_ABS, 470bfa3a410SAndreas Hindborg HrTimerMode::Relative => hrtimer_mode_HRTIMER_MODE_REL, 471bfa3a410SAndreas Hindborg HrTimerMode::Pinned => hrtimer_mode_HRTIMER_MODE_PINNED, 472bfa3a410SAndreas Hindborg HrTimerMode::Soft => hrtimer_mode_HRTIMER_MODE_SOFT, 473bfa3a410SAndreas Hindborg HrTimerMode::Hard => hrtimer_mode_HRTIMER_MODE_HARD, 474bfa3a410SAndreas Hindborg HrTimerMode::AbsolutePinned => hrtimer_mode_HRTIMER_MODE_ABS_PINNED, 475bfa3a410SAndreas Hindborg HrTimerMode::RelativePinned => hrtimer_mode_HRTIMER_MODE_REL_PINNED, 476bfa3a410SAndreas Hindborg HrTimerMode::AbsoluteSoft => hrtimer_mode_HRTIMER_MODE_ABS_SOFT, 477bfa3a410SAndreas Hindborg HrTimerMode::RelativeSoft => hrtimer_mode_HRTIMER_MODE_REL_SOFT, 478bfa3a410SAndreas Hindborg HrTimerMode::AbsolutePinnedSoft => hrtimer_mode_HRTIMER_MODE_ABS_PINNED_SOFT, 479bfa3a410SAndreas Hindborg HrTimerMode::RelativePinnedSoft => hrtimer_mode_HRTIMER_MODE_REL_PINNED_SOFT, 480bfa3a410SAndreas Hindborg HrTimerMode::AbsoluteHard => hrtimer_mode_HRTIMER_MODE_ABS_HARD, 481bfa3a410SAndreas Hindborg HrTimerMode::RelativeHard => hrtimer_mode_HRTIMER_MODE_REL_HARD, 482bfa3a410SAndreas Hindborg HrTimerMode::AbsolutePinnedHard => hrtimer_mode_HRTIMER_MODE_ABS_PINNED_HARD, 483bfa3a410SAndreas Hindborg HrTimerMode::RelativePinnedHard => hrtimer_mode_HRTIMER_MODE_REL_PINNED_HARD, 484bfa3a410SAndreas Hindborg } 485bfa3a410SAndreas Hindborg } 486bfa3a410SAndreas Hindborg } 487bfa3a410SAndreas Hindborg 4888a8afe93SAndreas Hindborg /// Use to implement the [`HasHrTimer<T>`] trait. 4898a8afe93SAndreas Hindborg /// 4908a8afe93SAndreas Hindborg /// See [`module`] documentation for an example. 4918a8afe93SAndreas Hindborg /// 4928a8afe93SAndreas Hindborg /// [`module`]: crate::time::hrtimer 4938a8afe93SAndreas Hindborg #[macro_export] 4948a8afe93SAndreas Hindborg macro_rules! impl_has_hr_timer { 4958a8afe93SAndreas Hindborg ( 4968a8afe93SAndreas Hindborg impl$({$($generics:tt)*})? 4978a8afe93SAndreas Hindborg HasHrTimer<$timer_type:ty> 4988a8afe93SAndreas Hindborg for $self:ty 4998a8afe93SAndreas Hindborg { self.$field:ident } 5008a8afe93SAndreas Hindborg $($rest:tt)* 5018a8afe93SAndreas Hindborg ) => { 5028a8afe93SAndreas Hindborg // SAFETY: This implementation of `raw_get_timer` only compiles if the 5038a8afe93SAndreas Hindborg // field has the right type. 5048a8afe93SAndreas Hindborg unsafe impl$(<$($generics)*>)? $crate::time::hrtimer::HasHrTimer<$timer_type> for $self { 5058a8afe93SAndreas Hindborg 5068a8afe93SAndreas Hindborg #[inline] 5078a8afe93SAndreas Hindborg unsafe fn raw_get_timer( 5088a8afe93SAndreas Hindborg this: *const Self, 5098a8afe93SAndreas Hindborg ) -> *const $crate::time::hrtimer::HrTimer<$timer_type> { 5108a8afe93SAndreas Hindborg // SAFETY: The caller promises that the pointer is not dangling. 5118a8afe93SAndreas Hindborg unsafe { ::core::ptr::addr_of!((*this).$field) } 5128a8afe93SAndreas Hindborg } 5138a8afe93SAndreas Hindborg 5148a8afe93SAndreas Hindborg #[inline] 5158a8afe93SAndreas Hindborg unsafe fn timer_container_of( 5168a8afe93SAndreas Hindborg ptr: *mut $crate::time::hrtimer::HrTimer<$timer_type>, 5178a8afe93SAndreas Hindborg ) -> *mut Self { 5188a8afe93SAndreas Hindborg // SAFETY: As per the safety requirement of this function, `ptr` 5198a8afe93SAndreas Hindborg // is pointing inside a `$timer_type`. 520*5b2d595eSFUJITA Tomonori unsafe { ::kernel::container_of!(ptr, $timer_type, $field) } 5218a8afe93SAndreas Hindborg } 5228a8afe93SAndreas Hindborg } 5238a8afe93SAndreas Hindborg } 5248a8afe93SAndreas Hindborg } 525d7bf4786SAndreas Hindborg 526d7bf4786SAndreas Hindborg mod arc; 527d7bf4786SAndreas Hindborg pub use arc::ArcHrTimerHandle; 528582523d9SAndreas Hindborg mod pin; 529582523d9SAndreas Hindborg pub use pin::PinHrTimerHandle; 530042b0c79SAndreas Hindborg mod pin_mut; 531042b0c79SAndreas Hindborg pub use pin_mut::PinMutHrTimerHandle; 532374b60a0SAndreas Hindborg // `box` is a reserved keyword, so prefix with `t` for timer 533374b60a0SAndreas Hindborg mod tbox; 534374b60a0SAndreas Hindborg pub use tbox::BoxHrTimerHandle; 535