Re: [PATCH v5 1/7] rust: time: make Delta generic over its time unit
Andreas Hindborg <[email protected]> Thu, 06 Aug 2026 11:44:21 +0200
| Newsgroups | org.kernel.vger.rust-for-linux |
|---|---|
| Message-ID | <[email protected]> |
FUJITA Tomonori <[email protected]> writes: > From: FUJITA Tomonori <[email protected]> > > Delta hardcodes its value as i64 nanoseconds. A later patch adds a > jiffies span, whose natural representation is isize jiffies rather than > i64 nanoseconds, and a separate type per unit would duplicate the > arithmetic and comparison machinery. > > Make Delta generic over its time unit so the jiffies span can reuse that > machinery. The nanosecond Delta keeps its current representation and API > via the default unit parameter, so no functional change. > users. > > Reviewed-by: Gary Guo <[email protected]> > Signed-off-by: FUJITA Tomonori <[email protected]> > --- > rust/kernel/time.rs | 72 ++++++++++++++++++++++++++++++--------------- > 1 file changed, 48 insertions(+), 24 deletions(-) > > diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs > index b8463823aed9..589bd7827523 100644 > --- a/rust/kernel/time.rs > +++ b/rust/kernel/time.rs > @@ -246,7 +246,7 @@ impl<C: ClockSource> ops::Sub for Instant<C> { > #[inline] > fn sub(self, other: Instant<C>) -> Delta { > Delta { > - nanos: self.inner - other.inner, > + value: self.inner - other.inner, > } > } > } > @@ -258,7 +258,7 @@ impl<T: ClockSource> ops::Add<Delta> for Instant<T> { > fn add(self, rhs: Delta) -> Self::Output { > // INVARIANT: With arithmetic over/underflow checks enabled, this will panic if we overflow > // (e.g. go above `KTIME_MAX`) > - let res = self.inner + rhs.nanos; > + let res = self.inner + rhs.value; > > // INVARIANT: With overflow checks enabled, we verify here that the value is >= 0 > #[cfg(CONFIG_RUST_OVERFLOW_CHECKS)] > @@ -278,7 +278,7 @@ impl<T: ClockSource> ops::Sub<Delta> for Instant<T> { > fn sub(self, rhs: Delta) -> Self::Output { > // INVARIANT: With arithmetic over/underflow checks enabled, this will panic if we overflow > // (e.g. go above `KTIME_MAX`) > - let res = self.inner - rhs.nanos; > + let res = self.inner - rhs.value; > > // INVARIANT: With overflow checks enabled, we verify here that the value is >= 0 > #[cfg(CONFIG_RUST_OVERFLOW_CHECKS)] > @@ -291,14 +291,38 @@ fn sub(self, rhs: Delta) -> Self::Output { > } > } > > +mod private { > + pub trait Sealed {} > + > + impl Sealed for super::Nsec {} > +} > + > +/// A trait for time units. > +pub trait TimeUnit: private::Sealed { > + /// The underlying representation of the time unit. > + type Repr: Copy + Clone + PartialEq + PartialOrd + Eq + Ord + core::fmt::Debug; > +} > + > +/// A time unit of nanoseconds. > +/// > +/// A [`Delta<Nsec>`] stores its value as `i64` nanoseconds and can represent > +/// any `i64` value, including negative, zero, and positive numbers. > +#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)] > +pub struct Nsec; Should we make these enum with zero variants to indicate they should not be constructed? > + > +impl TimeUnit for Nsec { > + type Repr = i64; > +} > + > /// A span of time. > /// > -/// This struct represents a span of time, with its value stored as nanoseconds. > -/// The value can represent any valid i64 value, including negative, zero, and > -/// positive numbers. > +/// The span is stored in the unit given by the type parameter `U` (see > +/// [`TimeUnit`]); its value has type `U::Repr`. `U` defaults to [`Nsec`], so a > +/// plain [`Delta`] is a span in nanoseconds. The value can be negative, zero, or > +/// positive. > #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)] > -pub struct Delta { > - nanos: i64, > +pub struct Delta<U: TimeUnit = Nsec> { > + value: U::Repr, > } > > impl ops::Add for Delta { When you add `Jiffy` later, this impl block will only cover `Delta<Nsec>`. Is that intentional, or did you intend to support all these operations operations for `Delta<Jiffy>` as well? Best regards, Andreas Hindborg