All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andreas Hindborg <a.hindborg@kernel.org>
To: "FUJITA Tomonori" <fujita.tomonori@gmail.com>
Cc: <rust-for-linux@vger.kernel.org>,  <boqun.feng@gmail.com>,
	<frederic@kernel.org>,  <lyude@redhat.com>,  <tglx@linutronix.de>,
	<anna-maria@linutronix.de>,  <jstultz@google.com>,
	 <sboyd@kernel.org>, <ojeda@kernel.org>,  <alex.gaynor@gmail.com>,
	 <gary@garyguo.net>, <bjorn3_gh@protonmail.com>,
	 <benno.lossin@proton.me>, <aliceryhl@google.com>,
	 <tmgross@umich.edu>,  <dakr@kernel.org>,
	<linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v1 4/5] rust: time: Make HasHrTimer generic over HrTimerMode
Date: Mon, 02 Jun 2025 14:41:10 +0200	[thread overview]
Message-ID: <877c1u71uh.fsf@kernel.org> (raw)
In-Reply-To: <20250504045959.238068-5-fujita.tomonori@gmail.com> (FUJITA Tomonori's message of "Sun, 04 May 2025 13:59:57 +0900")

"FUJITA Tomonori" <fujita.tomonori@gmail.com> writes:

> Add a `TimerMode` associated type to the `HasHrTimer` trait to
> represent the operational mode of the timer, such as absolute or
> relative expiration.  This new type must implement the `HrTimerMode`
> trait, which defines how expiration values are interpreted.
>
> Update the `start()` method to accept an `expires` parameter of type
> `<Self::TimerMode as HrTimerMode>::Expires` instead of the fixed `Ktime`.
> This enables different timer modes to provide strongly typed expiration
> values, such as `Instant<C>` or `Delta`.
>
> The `impl_has_hr_timer` macro is also extended to allow specifying the
> `HrTimerMode`. In the following example, it guarantees that the
> `start()` method for `Foo` only accepts `Instant<Monotonic>`. Using a
> `Delta` or an `Instant` with a different clock source will result in a
> compile-time error:
>
> struct Foo {
>     #[pin]
>     timer: HrTimer<Self>,
>
> }
>
> impl_has_hr_timer! {
>     impl HasHrTimer<Self> for Foo {
>         mode = AbsoluteMode<Monotonic>,
>         self.timer
>     }
> }
>
> This design eliminates runtime mismatches between expires types and
> clock sources, and enables stronger type-level guarantees throughout
> hrtimer.
>
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
> ---
>  rust/kernel/time/hrtimer.rs         | 55 ++++++++++++++++++++++-------
>  rust/kernel/time/hrtimer/arc.rs     |  8 +++--
>  rust/kernel/time/hrtimer/pin.rs     |  8 +++--
>  rust/kernel/time/hrtimer/pin_mut.rs |  8 +++--
>  rust/kernel/time/hrtimer/tbox.rs    |  8 +++--
>  5 files changed, 66 insertions(+), 21 deletions(-)
>
> diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
> index 55e1825425b6..3355ae6fe76d 100644
> --- a/rust/kernel/time/hrtimer.rs
> +++ b/rust/kernel/time/hrtimer.rs
> @@ -98,7 +98,6 @@ pub fn to_ns(self) -> i64 {
>  pub struct HrTimer<T> {
>      #[pin]
>      timer: Opaque<bindings::hrtimer>,
> -    mode: bindings::hrtimer_mode,
>      _t: PhantomData<T>,
>  }
>
> @@ -112,9 +111,10 @@ unsafe impl<T> Sync for HrTimer<T> {}
>
>  impl<T> HrTimer<T> {
>      /// Return an initializer for a new timer instance.
> -    pub fn new<U: ClockSource, M: HrTimerMode>() -> impl PinInit<Self>
> +    pub fn new() -> impl PinInit<Self>
>      where
>          T: HrTimerCallback,
> +        T: HasHrTimer<T>,
>      {
>          pin_init!(Self {
>              // INVARIANT: We initialize `timer` with `hrtimer_setup` below.
> @@ -126,12 +126,11 @@ pub fn new<U: ClockSource, M: HrTimerMode>() -> impl PinInit<Self>
>                      bindings::hrtimer_setup(
>                          place,
>                          Some(T::Pointer::run),
> -                        U::ID,
> -                        M::C_MODE,
> +                        <<T as HasHrTimer<T>>::TimerMode as HrTimerMode>::Clock::ID,
> +                        <T as HasHrTimer<T>>::TimerMode::C_MODE,
>                      );
>                  }
>              }),
> -            mode: M::C_MODE,
>              _t: PhantomData,
>          })
>      }
> @@ -193,6 +192,11 @@ pub(crate) unsafe fn raw_cancel(this: *const Self) -> bool {
>  /// exist. A timer can be manipulated through any of the handles, and a handle
>  /// may represent a cancelled timer.
>  pub trait HrTimerPointer: Sync + Sized {
> +    /// The operational mode associated with this timer.
> +    ///
> +    /// This defines how the expiration value is interpreted.
> +    type TimerMode: HrTimerMode;
> +
>      /// A handle representing a started or restarted timer.
>      ///
>      /// If the timer is running or if the timer callback is executing when the
> @@ -205,7 +209,7 @@ pub trait HrTimerPointer: Sync + Sized {
>
>      /// Start the timer with expiry after `expires` time units. If the timer was
>      /// already running, it is restarted with the new expiry time.
> -    fn start(self, expires: Ktime) -> Self::TimerHandle;
> +    fn start(self, expires: <Self::TimerMode as HrTimerMode>::Expires) -> Self::TimerHandle;
>  }
>
>  /// Unsafe version of [`HrTimerPointer`] for situations where leaking the
> @@ -220,6 +224,11 @@ pub trait HrTimerPointer: Sync + Sized {
>  /// [`UnsafeHrTimerPointer`] outlives any associated [`HrTimerPointer::TimerHandle`]
>  /// instances.
>  pub unsafe trait UnsafeHrTimerPointer: Sync + Sized {
> +    /// The operational mode associated with this timer.
> +    ///
> +    /// This defines how the expiration value is interpreted.
> +    type TimerMode: HrTimerMode;
> +
>      /// A handle representing a running timer.
>      ///
>      /// # Safety
> @@ -236,7 +245,7 @@ pub unsafe trait UnsafeHrTimerPointer: Sync + Sized {
>      ///
>      /// Caller promises keep the timer structure alive until the timer is dead.
>      /// Caller can ensure this by not leaking the returned [`Self::TimerHandle`].
> -    unsafe fn start(self, expires: Ktime) -> Self::TimerHandle;
> +    unsafe fn start(self, expires: <Self::TimerMode as HrTimerMode>::Expires) -> Self::TimerHandle;
>  }
>
>  /// A trait for stack allocated timers.
> @@ -246,9 +255,14 @@ pub unsafe trait UnsafeHrTimerPointer: Sync + Sized {
>  /// Implementers must ensure that `start_scoped` does not return until the
>  /// timer is dead and the timer handler is not running.
>  pub unsafe trait ScopedHrTimerPointer {
> +    /// The operational mode associated with this timer.
> +    ///
> +    /// This defines how the expiration value is interpreted.
> +    type TimerMode: HrTimerMode;
> +
>      /// Start the timer to run after `expires` time units and immediately
>      /// after call `f`. When `f` returns, the timer is cancelled.
> -    fn start_scoped<T, F>(self, expires: Ktime, f: F) -> T
> +    fn start_scoped<T, F>(self, expires: <Self::TimerMode as HrTimerMode>::Expires, f: F) -> T
>      where
>          F: FnOnce() -> T;
>  }
> @@ -260,7 +274,13 @@ unsafe impl<T> ScopedHrTimerPointer for T
>  where
>      T: UnsafeHrTimerPointer,
>  {
> -    fn start_scoped<U, F>(self, expires: Ktime, f: F) -> U
> +    type TimerMode = T::TimerMode;
> +
> +    fn start_scoped<U, F>(
> +        self,
> +        expires: <<T as UnsafeHrTimerPointer>::TimerMode as HrTimerMode>::Expires,
> +        f: F,
> +    ) -> U
>      where
>          F: FnOnce() -> U,
>      {
> @@ -335,6 +355,11 @@ pub unsafe trait HrTimerHandle {
>  /// their documentation. All the methods of this trait must operate on the same
>  /// field.
>  pub unsafe trait HasHrTimer<T> {
> +    /// The operational mode associated with this timer.
> +    ///
> +    /// This defines how the expiration value is interpreted.
> +    type TimerMode: HrTimerMode;
> +
>      /// Return a pointer to the [`HrTimer`] within `Self`.
>      ///
>      /// This function is useful to get access to the value without creating
> @@ -382,14 +407,14 @@ unsafe fn c_timer_ptr(this: *const Self) -> *const bindings::hrtimer {
>      /// - `this` must point to a valid `Self`.
>      /// - Caller must ensure that the pointee of `this` lives until the timer
>      ///   fires or is canceled.
> -    unsafe fn start(this: *const Self, expires: Ktime) {
> +    unsafe fn start(this: *const Self, expires: <Self::TimerMode as HrTimerMode>::Expires) {
>          // SAFETY: By function safety requirement, `this` is a valid `Self`.
>          unsafe {
>              bindings::hrtimer_start_range_ns(
>                  Self::c_timer_ptr(this).cast_mut(),
> -                expires.to_ns(),
> +                expires.as_nanos(),
>                  0,
> -                (*Self::raw_get_timer(this)).mode,
> +                <Self::TimerMode as HrTimerMode>::Clock::ID as u32,
>              );
>          }
>      }
> @@ -579,12 +604,16 @@ macro_rules! impl_has_hr_timer {
>          impl$({$($generics:tt)*})?
>              HasHrTimer<$timer_type:ty>
>              for $self:ty
> -        { self.$field:ident }
> +        {
> +            mode = $mode:ty,
> +            self.$field:ident

How about:

  mode = $mode:ty,
  field = self.$field:ident

So that there is some sort of red line when calling this. We could also
consider adopting another syntax for association:

  mode: $mode:ty,
  field: self.$field:ident

or something else like `<-` or `->` ?


Best regards,
Andreas Hindborg



  reply	other threads:[~2025-06-02 12:41 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-04  4:59 [PATCH v1 0/5] rust: time: Convert hrtimer to use Instant and Delta FUJITA Tomonori
2025-05-04  4:59 ` [PATCH v1 1/5] rust: time: Change Delta methods to take &self instead of self FUJITA Tomonori
2025-06-02  8:23   ` Alice Ryhl
2025-06-02 12:19     ` Andreas Hindborg
2025-06-03 13:31       ` FUJITA Tomonori
2025-05-04  4:59 ` [PATCH v1 2/5] rust: timer: Replace HrTimerMode enum with trait-based mode types FUJITA Tomonori
2025-06-02 12:53   ` Andreas Hindborg
2025-05-04  4:59 ` [PATCH v1 3/5] rust: time: Add HrTimerExpires trait FUJITA Tomonori
2025-05-30 13:04   ` Andreas Hindborg
2025-06-03 13:51     ` FUJITA Tomonori
2025-06-03 16:28       ` Andreas Hindborg
2025-05-04  4:59 ` [PATCH v1 4/5] rust: time: Make HasHrTimer generic over HrTimerMode FUJITA Tomonori
2025-06-02 12:41   ` Andreas Hindborg [this message]
2025-06-03 14:08     ` FUJITA Tomonori
2025-06-03 16:30       ` Andreas Hindborg
2025-05-04  4:59 ` [PATCH v1 5/5] rust: time: Remove Ktime in hrtimer FUJITA Tomonori
2025-06-02 12:41   ` Andreas Hindborg

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=877c1u71uh.fsf@kernel.org \
    --to=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=anna-maria@linutronix.de \
    --cc=benno.lossin@proton.me \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=dakr@kernel.org \
    --cc=frederic@kernel.org \
    --cc=fujita.tomonori@gmail.com \
    --cc=gary@garyguo.net \
    --cc=jstultz@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lyude@redhat.com \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=sboyd@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=tmgross@umich.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.