1d7bf4786SAndreas Hindborg // SPDX-License-Identifier: GPL-2.0 2d7bf4786SAndreas Hindborg 3d7bf4786SAndreas Hindborg use super::HasHrTimer; 4d7bf4786SAndreas Hindborg use super::HrTimer; 5d7bf4786SAndreas Hindborg use super::HrTimerCallback; 6d7bf4786SAndreas Hindborg use super::HrTimerHandle; 7d7bf4786SAndreas Hindborg use super::HrTimerPointer; 8*1116f0c5SFUJITA Tomonori use super::Ktime; 9d7bf4786SAndreas Hindborg use super::RawHrTimerCallback; 10d7bf4786SAndreas Hindborg use crate::sync::Arc; 11d7bf4786SAndreas Hindborg use crate::sync::ArcBorrow; 12d7bf4786SAndreas Hindborg 13d7bf4786SAndreas Hindborg /// A handle for an `Arc<HasHrTimer<T>>` returned by a call to 14d7bf4786SAndreas Hindborg /// [`HrTimerPointer::start`]. 15d7bf4786SAndreas Hindborg pub struct ArcHrTimerHandle<T> 16d7bf4786SAndreas Hindborg where 17d7bf4786SAndreas Hindborg T: HasHrTimer<T>, 18d7bf4786SAndreas Hindborg { 19d7bf4786SAndreas Hindborg pub(crate) inner: Arc<T>, 20d7bf4786SAndreas Hindborg } 21d7bf4786SAndreas Hindborg 22d7bf4786SAndreas Hindborg // SAFETY: We implement drop below, and we cancel the timer in the drop 23d7bf4786SAndreas Hindborg // implementation. 24d7bf4786SAndreas Hindborg unsafe impl<T> HrTimerHandle for ArcHrTimerHandle<T> 25d7bf4786SAndreas Hindborg where 26d7bf4786SAndreas Hindborg T: HasHrTimer<T>, 27d7bf4786SAndreas Hindborg { cancel(&mut self) -> bool28d7bf4786SAndreas Hindborg fn cancel(&mut self) -> bool { 29d7bf4786SAndreas Hindborg let self_ptr = Arc::as_ptr(&self.inner); 30d7bf4786SAndreas Hindborg 31d7bf4786SAndreas Hindborg // SAFETY: As we obtained `self_ptr` from a valid reference above, it 32d7bf4786SAndreas Hindborg // must point to a valid `T`. 33d7bf4786SAndreas Hindborg let timer_ptr = unsafe { <T as HasHrTimer<T>>::raw_get_timer(self_ptr) }; 34d7bf4786SAndreas Hindborg 35d7bf4786SAndreas Hindborg // SAFETY: As `timer_ptr` points into `T` and `T` is valid, `timer_ptr` 36d7bf4786SAndreas Hindborg // must point to a valid `HrTimer` instance. 37d7bf4786SAndreas Hindborg unsafe { HrTimer::<T>::raw_cancel(timer_ptr) } 38d7bf4786SAndreas Hindborg } 39d7bf4786SAndreas Hindborg } 40d7bf4786SAndreas Hindborg 41d7bf4786SAndreas Hindborg impl<T> Drop for ArcHrTimerHandle<T> 42d7bf4786SAndreas Hindborg where 43d7bf4786SAndreas Hindborg T: HasHrTimer<T>, 44d7bf4786SAndreas Hindborg { drop(&mut self)45d7bf4786SAndreas Hindborg fn drop(&mut self) { 46d7bf4786SAndreas Hindborg self.cancel(); 47d7bf4786SAndreas Hindborg } 48d7bf4786SAndreas Hindborg } 49d7bf4786SAndreas Hindborg 50d7bf4786SAndreas Hindborg impl<T> HrTimerPointer for Arc<T> 51d7bf4786SAndreas Hindborg where 52d7bf4786SAndreas Hindborg T: 'static, 53d7bf4786SAndreas Hindborg T: Send + Sync, 54d7bf4786SAndreas Hindborg T: HasHrTimer<T>, 55d7bf4786SAndreas Hindborg T: for<'a> HrTimerCallback<Pointer<'a> = Self>, 56d7bf4786SAndreas Hindborg { 57d7bf4786SAndreas Hindborg type TimerHandle = ArcHrTimerHandle<T>; 58d7bf4786SAndreas Hindborg start(self, expires: Ktime) -> ArcHrTimerHandle<T>59d7bf4786SAndreas Hindborg fn start(self, expires: Ktime) -> ArcHrTimerHandle<T> { 60d7bf4786SAndreas Hindborg // SAFETY: 61d7bf4786SAndreas Hindborg // - We keep `self` alive by wrapping it in a handle below. 62d7bf4786SAndreas Hindborg // - Since we generate the pointer passed to `start` from a valid 63d7bf4786SAndreas Hindborg // reference, it is a valid pointer. 64d7bf4786SAndreas Hindborg unsafe { T::start(Arc::as_ptr(&self), expires) }; 65d7bf4786SAndreas Hindborg ArcHrTimerHandle { inner: self } 66d7bf4786SAndreas Hindborg } 67d7bf4786SAndreas Hindborg } 68d7bf4786SAndreas Hindborg 69d7bf4786SAndreas Hindborg impl<T> RawHrTimerCallback for Arc<T> 70d7bf4786SAndreas Hindborg where 71d7bf4786SAndreas Hindborg T: 'static, 72d7bf4786SAndreas Hindborg T: HasHrTimer<T>, 73d7bf4786SAndreas Hindborg T: for<'a> HrTimerCallback<Pointer<'a> = Self>, 74d7bf4786SAndreas Hindborg { 75d7bf4786SAndreas Hindborg type CallbackTarget<'a> = ArcBorrow<'a, T>; 76d7bf4786SAndreas Hindborg run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart77d7bf4786SAndreas Hindborg unsafe extern "C" fn run(ptr: *mut bindings::hrtimer) -> bindings::hrtimer_restart { 78d7bf4786SAndreas Hindborg // `HrTimer` is `repr(C)` 79d7bf4786SAndreas Hindborg let timer_ptr = ptr.cast::<super::HrTimer<T>>(); 80d7bf4786SAndreas Hindborg 81d7bf4786SAndreas Hindborg // SAFETY: By C API contract `ptr` is the pointer we passed when 82d7bf4786SAndreas Hindborg // queuing the timer, so it is a `HrTimer<T>` embedded in a `T`. 83d7bf4786SAndreas Hindborg let data_ptr = unsafe { T::timer_container_of(timer_ptr) }; 84d7bf4786SAndreas Hindborg 85d7bf4786SAndreas Hindborg // SAFETY: 86d7bf4786SAndreas Hindborg // - `data_ptr` is derived form the pointer to the `T` that was used to 87d7bf4786SAndreas Hindborg // queue the timer. 88d7bf4786SAndreas Hindborg // - As per the safety requirements of the trait `HrTimerHandle`, the 89d7bf4786SAndreas Hindborg // `ArcHrTimerHandle` associated with this timer is guaranteed to 90d7bf4786SAndreas Hindborg // be alive until this method returns. That handle borrows the `T` 91d7bf4786SAndreas Hindborg // behind `data_ptr` thus guaranteeing the validity of 92d7bf4786SAndreas Hindborg // the `ArcBorrow` created below. 93d7bf4786SAndreas Hindborg // - We own one refcount in the `ArcTimerHandle` associated with this 94d7bf4786SAndreas Hindborg // timer, so it is not possible to get a `UniqueArc` to this 95d7bf4786SAndreas Hindborg // allocation from other `Arc` clones. 96d7bf4786SAndreas Hindborg let receiver = unsafe { ArcBorrow::from_raw(data_ptr) }; 97d7bf4786SAndreas Hindborg 9894e05a66SAndreas Hindborg T::run(receiver).into_c() 99d7bf4786SAndreas Hindborg } 100d7bf4786SAndreas Hindborg } 101