[PATCH 7/9] rust: hrtimer: expose interrupt state in hard callbacks
Mike Lothian <[email protected]>
| Newsgroups | org.kernel.vger.rust-for-linux,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
Hard hrtimer modes guarantee that their callbacks run with local interrupts disabled. Carry that guarantee through HrTimerCallbackContext so users of IRQ-aware locks do not need to assert the callback context themselves. Assisted-by: Claude:claude-opus-5 Signed-off-by: Mike Lothian <[email protected]> --- rust/kernel/time/hrtimer.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs index 2d7f1131a813..a55b3ce53735 100644 --- a/rust/kernel/time/hrtimer.rs +++ b/rust/kernel/time/hrtimer.rs @@ -404,7 +404,7 @@ //! [`Arc`]: kernel::sync::Arc use super::{ClockSource, Delta, Instant}; -use crate::{prelude::*, types::Opaque}; +use crate::{interrupt::LocalInterruptDisabled, prelude::*, types::Opaque}; use core::{marker::PhantomData, ptr::NonNull}; use pin_init::PinInit; @@ -900,6 +900,11 @@ pub trait HrTimerMode: private::Sealed { type Expires: HrTimerExpires; } +/// A timer mode whose callback runs with local interrupts disabled. +/// +/// This trait is sealed by [`HrTimerMode`]. +pub trait HardHrTimerMode: HrTimerMode {} + /// Timer that expires at a fixed point in time. pub struct AbsoluteMode<C: ClockSource>(PhantomData<C>); @@ -982,6 +987,7 @@ impl<C: ClockSource> HrTimerMode for AbsoluteHardMode<C> { type Clock = C; type Expires = Instant<C>; } +impl<C: ClockSource> HardHrTimerMode for AbsoluteHardMode<C> {} /// Timer with relative expiration, handled in hard irq context. pub struct RelativeHardMode<C: ClockSource>(PhantomData<C>); @@ -991,6 +997,7 @@ impl<C: ClockSource> HrTimerMode for RelativeHardMode<C> { type Clock = C; type Expires = Delta; } +impl<C: ClockSource> HardHrTimerMode for RelativeHardMode<C> {} /// Timer with absolute expiration, pinned to CPU and handled in hard irq context. pub struct AbsolutePinnedHardMode<C: ClockSource>(PhantomData<C>); @@ -1000,6 +1007,7 @@ impl<C: ClockSource> HrTimerMode for AbsolutePinnedHardMode<C> { type Clock = C; type Expires = Instant<C>; } +impl<C: ClockSource> HardHrTimerMode for AbsolutePinnedHardMode<C> {} /// Timer with relative expiration, pinned to CPU and handled in hard irq context. pub struct RelativePinnedHardMode<C: ClockSource>(PhantomData<C>); @@ -1009,6 +1017,7 @@ impl<C: ClockSource> HrTimerMode for RelativePinnedHardMode<C> { type Clock = C; type Expires = Delta; } +impl<C: ClockSource> HardHrTimerMode for RelativePinnedHardMode<C> {} /// Privileged smart-pointer for a [`HrTimer`] callback context. /// @@ -1065,6 +1074,16 @@ pub fn forward(&mut self, now: HrTimerInstant<T>, interval: Delta) -> u64 { pub fn forward_now(&mut self, duration: Delta) -> u64 { self.forward(HrTimerInstant::<T>::now(), duration) } + + /// Returns proof that local interrupts are disabled for a hard timer callback. + pub fn local_interrupt_disabled(&self) -> &LocalInterruptDisabled + where + T::TimerMode: HardHrTimerMode, + { + // SAFETY: `Self` can only be constructed while running this timer's callback, and the + // `HardHrTimerMode` bound guarantees that the callback runs in hard interrupt context. + unsafe { LocalInterruptDisabled::assume_disabled() } + } } /// Use to implement the [`HasHrTimer<T>`] trait.