1*042b0c79SAndreas Hindborg // SPDX-License-Identifier: GPL-2.0 2*042b0c79SAndreas Hindborg 3*042b0c79SAndreas Hindborg use super::{ 4*042b0c79SAndreas Hindborg HasHrTimer, HrTimer, HrTimerCallback, HrTimerHandle, RawHrTimerCallback, UnsafeHrTimerPointer, 5*042b0c79SAndreas Hindborg }; 6*042b0c79SAndreas Hindborg use crate::time::Ktime; 7*042b0c79SAndreas Hindborg use core::{marker::PhantomData, pin::Pin, ptr::NonNull}; 8*042b0c79SAndreas Hindborg 9*042b0c79SAndreas Hindborg /// A handle for a `Pin<&mut HasHrTimer>`. When the handle exists, the timer might 10*042b0c79SAndreas Hindborg /// be running. 11*042b0c79SAndreas Hindborg pub struct PinMutHrTimerHandle<'a, T> 12*042b0c79SAndreas Hindborg where 13*042b0c79SAndreas Hindborg T: HasHrTimer<T>, 14*042b0c79SAndreas Hindborg { 15*042b0c79SAndreas Hindborg pub(crate) inner: NonNull<T>, 16*042b0c79SAndreas Hindborg _p: PhantomData<&'a mut T>, 17*042b0c79SAndreas Hindborg } 18*042b0c79SAndreas Hindborg 19*042b0c79SAndreas Hindborg // SAFETY: We cancel the timer when the handle is dropped. The implementation of 20*042b0c79SAndreas Hindborg // the `cancel` method will block if the timer handler is running. 21*042b0c79SAndreas Hindborg unsafe impl<'a, T> HrTimerHandle for PinMutHrTimerHandle<'a, T> 22*042b0c79SAndreas Hindborg where 23*042b0c79SAndreas Hindborg T: HasHrTimer<T>, 24*042b0c79SAndreas Hindborg { cancel(&mut self) -> bool25*042b0c79SAndreas Hindborg fn cancel(&mut self) -> bool { 26*042b0c79SAndreas Hindborg let self_ptr = self.inner.as_ptr(); 27*042b0c79SAndreas Hindborg 28*042b0c79SAndreas Hindborg // SAFETY: As we got `self_ptr` from a reference above, it must point to 29*042b0c79SAndreas Hindborg // a valid `T`. 30*042b0c79SAndreas Hindborg let timer_ptr = unsafe { <T as HasHrTimer<T>>::raw_get_timer(self_ptr) }; 31*042b0c79SAndreas Hindborg 32*042b0c79SAndreas Hindborg // SAFETY: As `timer_ptr` is derived from a reference, it must point to 33*042b0c79SAndreas Hindborg // a valid and initialized `HrTimer`. 34*042b0c79SAndreas Hindborg unsafe { HrTimer::<T>::raw_cancel(timer_ptr) } 35*042b0c79SAndreas Hindborg } 36*042b0c79SAndreas Hindborg } 37*042b0c79SAndreas Hindborg 38*042b0c79SAndreas Hindborg impl<'a, T> Drop for PinMutHrTimerHandle<'a, T> 39*042b0c79SAndreas Hindborg where 40*042b0c79SAndreas Hindborg T: HasHrTimer<T>, 41*042b0c79SAndreas Hindborg { drop(&mut self)42*042b0c79SAndreas Hindborg fn drop(&mut self) { 43*042b0c79SAndreas Hindborg self.cancel(); 44*042b0c79SAndreas Hindborg } 45*042b0c79SAndreas Hindborg } 46*042b0c79SAndreas Hindborg 47*042b0c79SAndreas Hindborg // SAFETY: We capture the lifetime of `Self` when we create a 48*042b0c79SAndreas Hindborg // `PinMutHrTimerHandle`, so `Self` will outlive the handle. 49*042b0c79SAndreas Hindborg unsafe impl<'a, T> UnsafeHrTimerPointer for Pin<&'a mut T> 50*042b0c79SAndreas Hindborg where 51*042b0c79SAndreas Hindborg T: Send + Sync, 52*042b0c79SAndreas Hindborg T: HasHrTimer<T>, 53*042b0c79SAndreas Hindborg T: HrTimerCallback<Pointer<'a> = Self>, 54*042b0c79SAndreas Hindborg { 55*042b0c79SAndreas Hindborg type TimerHandle = PinMutHrTimerHandle<'a, T>; 56*042b0c79SAndreas Hindborg start(mut self, expires: Ktime) -> Self::TimerHandle57*042b0c79SAndreas Hindborg unsafe fn start(mut self, expires: Ktime) -> Self::TimerHandle { 58*042b0c79SAndreas Hindborg // SAFETY: 59*042b0c79SAndreas Hindborg // - We promise not to move out of `self`. We only pass `self` 60*042b0c79SAndreas Hindborg // back to the caller as a `Pin<&mut self>`. 61*042b0c79SAndreas Hindborg // - The return value of `get_unchecked_mut` is guaranteed not to be null. 62*042b0c79SAndreas Hindborg let self_ptr = unsafe { NonNull::new_unchecked(self.as_mut().get_unchecked_mut()) }; 63*042b0c79SAndreas Hindborg 64*042b0c79SAndreas Hindborg // SAFETY: 65*042b0c79SAndreas Hindborg // - As we derive `self_ptr` from a reference above, it must point to a 66*042b0c79SAndreas Hindborg // valid `T`. 67*042b0c79SAndreas Hindborg // - We keep `self` alive by wrapping it in a handle below. 68*042b0c79SAndreas Hindborg unsafe { T::start(self_ptr.as_ptr(), expires) }; 69*042b0c79SAndreas Hindborg 70*042b0c79SAndreas Hindborg PinMutHrTimerHandle { 71*042b0c79SAndreas Hindborg inner: self_ptr, 72*042b0c79SAndreas Hindborg _p: PhantomData, 73*042b0c79SAndreas Hindborg } 74*042b0c79SAndreas Hindborg } 75*042b0c79SAndreas Hindborg } 76*042b0c79SAndreas Hindborg 77*042b0c79SAndreas Hindborg impl<'a, T> RawHrTimerCallback for Pin<&'a mut T> 78*042b0c79SAndreas Hindborg where 79*042b0c79SAndreas Hindborg T: HasHrTimer<T>, 80*042b0c79SAndreas Hindborg T: HrTimerCallback<Pointer<'a> = Self>, 81*042b0c79SAndreas Hindborg { 82*042b0c79SAndreas Hindborg type CallbackTarget<'b> = Self; 83*042b0c79SAndreas Hindborg run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart84*042b0c79SAndreas Hindborg unsafe extern "C" fn run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart { 85*042b0c79SAndreas Hindborg // `HrTimer` is `repr(C)` 86*042b0c79SAndreas Hindborg let timer_ptr = ptr as *mut HrTimer<T>; 87*042b0c79SAndreas Hindborg 88*042b0c79SAndreas Hindborg // SAFETY: By the safety requirement of this function, `timer_ptr` 89*042b0c79SAndreas Hindborg // points to a `HrTimer<T>` contained in an `T`. 90*042b0c79SAndreas Hindborg let receiver_ptr = unsafe { T::timer_container_of(timer_ptr) }; 91*042b0c79SAndreas Hindborg 92*042b0c79SAndreas Hindborg // SAFETY: 93*042b0c79SAndreas Hindborg // - By the safety requirement of this function, `timer_ptr` 94*042b0c79SAndreas Hindborg // points to a `HrTimer<T>` contained in an `T`. 95*042b0c79SAndreas Hindborg // - As per the safety requirements of the trait `HrTimerHandle`, the 96*042b0c79SAndreas Hindborg // `PinMutHrTimerHandle` associated with this timer is guaranteed to 97*042b0c79SAndreas Hindborg // be alive until this method returns. That handle borrows the `T` 98*042b0c79SAndreas Hindborg // behind `receiver_ptr` mutably thus guaranteeing the validity of 99*042b0c79SAndreas Hindborg // the reference created below. 100*042b0c79SAndreas Hindborg let receiver_ref = unsafe { &mut *receiver_ptr }; 101*042b0c79SAndreas Hindborg 102*042b0c79SAndreas Hindborg // SAFETY: `receiver_ref` only exists as pinned, so it is safe to pin it 103*042b0c79SAndreas Hindborg // here. 104*042b0c79SAndreas Hindborg let receiver_pin = unsafe { Pin::new_unchecked(receiver_ref) }; 105*042b0c79SAndreas Hindborg 106*042b0c79SAndreas Hindborg T::run(receiver_pin).into_c() 107*042b0c79SAndreas Hindborg } 108*042b0c79SAndreas Hindborg } 109