xref: /linux-6.15/rust/kernel/time/hrtimer/pin_mut.rs (revision 042b0c79)
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