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