1042b0c79SAndreas Hindborg // SPDX-License-Identifier: GPL-2.0 2042b0c79SAndreas Hindborg 3042b0c79SAndreas Hindborg use super::{ 4*1116f0c5SFUJITA Tomonori HasHrTimer, HrTimer, HrTimerCallback, HrTimerHandle, Ktime, RawHrTimerCallback, 5*1116f0c5SFUJITA Tomonori UnsafeHrTimerPointer, 6042b0c79SAndreas Hindborg }; 7042b0c79SAndreas Hindborg use core::{marker::PhantomData, pin::Pin, ptr::NonNull}; 8042b0c79SAndreas Hindborg 9042b0c79SAndreas Hindborg /// A handle for a `Pin<&mut HasHrTimer>`. When the handle exists, the timer might 10042b0c79SAndreas Hindborg /// be running. 11042b0c79SAndreas Hindborg pub struct PinMutHrTimerHandle<'a, T> 12042b0c79SAndreas Hindborg where 13042b0c79SAndreas Hindborg T: HasHrTimer<T>, 14042b0c79SAndreas Hindborg { 15042b0c79SAndreas Hindborg pub(crate) inner: NonNull<T>, 16042b0c79SAndreas Hindborg _p: PhantomData<&'a mut T>, 17042b0c79SAndreas Hindborg } 18042b0c79SAndreas Hindborg 19042b0c79SAndreas Hindborg // SAFETY: We cancel the timer when the handle is dropped. The implementation of 20042b0c79SAndreas Hindborg // the `cancel` method will block if the timer handler is running. 21042b0c79SAndreas Hindborg unsafe impl<'a, T> HrTimerHandle for PinMutHrTimerHandle<'a, T> 22042b0c79SAndreas Hindborg where 23042b0c79SAndreas Hindborg T: HasHrTimer<T>, 24042b0c79SAndreas Hindborg { cancel(&mut self) -> bool25042b0c79SAndreas Hindborg fn cancel(&mut self) -> bool { 26042b0c79SAndreas Hindborg let self_ptr = self.inner.as_ptr(); 27042b0c79SAndreas Hindborg 28042b0c79SAndreas Hindborg // SAFETY: As we got `self_ptr` from a reference above, it must point to 29042b0c79SAndreas Hindborg // a valid `T`. 30042b0c79SAndreas Hindborg let timer_ptr = unsafe { <T as HasHrTimer<T>>::raw_get_timer(self_ptr) }; 31042b0c79SAndreas Hindborg 32042b0c79SAndreas Hindborg // SAFETY: As `timer_ptr` is derived from a reference, it must point to 33042b0c79SAndreas Hindborg // a valid and initialized `HrTimer`. 34042b0c79SAndreas Hindborg unsafe { HrTimer::<T>::raw_cancel(timer_ptr) } 35042b0c79SAndreas Hindborg } 36042b0c79SAndreas Hindborg } 37042b0c79SAndreas Hindborg 38042b0c79SAndreas Hindborg impl<'a, T> Drop for PinMutHrTimerHandle<'a, T> 39042b0c79SAndreas Hindborg where 40042b0c79SAndreas Hindborg T: HasHrTimer<T>, 41042b0c79SAndreas Hindborg { drop(&mut self)42042b0c79SAndreas Hindborg fn drop(&mut self) { 43042b0c79SAndreas Hindborg self.cancel(); 44042b0c79SAndreas Hindborg } 45042b0c79SAndreas Hindborg } 46042b0c79SAndreas Hindborg 47042b0c79SAndreas Hindborg // SAFETY: We capture the lifetime of `Self` when we create a 48042b0c79SAndreas Hindborg // `PinMutHrTimerHandle`, so `Self` will outlive the handle. 49042b0c79SAndreas Hindborg unsafe impl<'a, T> UnsafeHrTimerPointer for Pin<&'a mut T> 50042b0c79SAndreas Hindborg where 51042b0c79SAndreas Hindborg T: Send + Sync, 52042b0c79SAndreas Hindborg T: HasHrTimer<T>, 53042b0c79SAndreas Hindborg T: HrTimerCallback<Pointer<'a> = Self>, 54042b0c79SAndreas Hindborg { 55042b0c79SAndreas Hindborg type TimerHandle = PinMutHrTimerHandle<'a, T>; 56042b0c79SAndreas Hindborg start(mut self, expires: Ktime) -> Self::TimerHandle57042b0c79SAndreas Hindborg unsafe fn start(mut self, expires: Ktime) -> Self::TimerHandle { 58042b0c79SAndreas Hindborg // SAFETY: 59042b0c79SAndreas Hindborg // - We promise not to move out of `self`. We only pass `self` 60042b0c79SAndreas Hindborg // back to the caller as a `Pin<&mut self>`. 61042b0c79SAndreas Hindborg // - The return value of `get_unchecked_mut` is guaranteed not to be null. 62042b0c79SAndreas Hindborg let self_ptr = unsafe { NonNull::new_unchecked(self.as_mut().get_unchecked_mut()) }; 63042b0c79SAndreas Hindborg 64042b0c79SAndreas Hindborg // SAFETY: 65042b0c79SAndreas Hindborg // - As we derive `self_ptr` from a reference above, it must point to a 66042b0c79SAndreas Hindborg // valid `T`. 67042b0c79SAndreas Hindborg // - We keep `self` alive by wrapping it in a handle below. 68042b0c79SAndreas Hindborg unsafe { T::start(self_ptr.as_ptr(), expires) }; 69042b0c79SAndreas Hindborg 70042b0c79SAndreas Hindborg PinMutHrTimerHandle { 71042b0c79SAndreas Hindborg inner: self_ptr, 72042b0c79SAndreas Hindborg _p: PhantomData, 73042b0c79SAndreas Hindborg } 74042b0c79SAndreas Hindborg } 75042b0c79SAndreas Hindborg } 76042b0c79SAndreas Hindborg 77042b0c79SAndreas Hindborg impl<'a, T> RawHrTimerCallback for Pin<&'a mut T> 78042b0c79SAndreas Hindborg where 79042b0c79SAndreas Hindborg T: HasHrTimer<T>, 80042b0c79SAndreas Hindborg T: HrTimerCallback<Pointer<'a> = Self>, 81042b0c79SAndreas Hindborg { 82042b0c79SAndreas Hindborg type CallbackTarget<'b> = Self; 83042b0c79SAndreas Hindborg run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart84042b0c79SAndreas Hindborg unsafe extern "C" fn run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart { 85042b0c79SAndreas Hindborg // `HrTimer` is `repr(C)` 86042b0c79SAndreas Hindborg let timer_ptr = ptr as *mut HrTimer<T>; 87042b0c79SAndreas Hindborg 88042b0c79SAndreas Hindborg // SAFETY: By the safety requirement of this function, `timer_ptr` 89042b0c79SAndreas Hindborg // points to a `HrTimer<T>` contained in an `T`. 90042b0c79SAndreas Hindborg let receiver_ptr = unsafe { T::timer_container_of(timer_ptr) }; 91042b0c79SAndreas Hindborg 92042b0c79SAndreas Hindborg // SAFETY: 93042b0c79SAndreas Hindborg // - By the safety requirement of this function, `timer_ptr` 94042b0c79SAndreas Hindborg // points to a `HrTimer<T>` contained in an `T`. 95042b0c79SAndreas Hindborg // - As per the safety requirements of the trait `HrTimerHandle`, the 96042b0c79SAndreas Hindborg // `PinMutHrTimerHandle` associated with this timer is guaranteed to 97042b0c79SAndreas Hindborg // be alive until this method returns. That handle borrows the `T` 98042b0c79SAndreas Hindborg // behind `receiver_ptr` mutably thus guaranteeing the validity of 99042b0c79SAndreas Hindborg // the reference created below. 100042b0c79SAndreas Hindborg let receiver_ref = unsafe { &mut *receiver_ptr }; 101042b0c79SAndreas Hindborg 102042b0c79SAndreas Hindborg // SAFETY: `receiver_ref` only exists as pinned, so it is safe to pin it 103042b0c79SAndreas Hindborg // here. 104042b0c79SAndreas Hindborg let receiver_pin = unsafe { Pin::new_unchecked(receiver_ref) }; 105042b0c79SAndreas Hindborg 106042b0c79SAndreas Hindborg T::run(receiver_pin).into_c() 107042b0c79SAndreas Hindborg } 108042b0c79SAndreas Hindborg } 109