linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Lyude Paul <lyude@redhat.com>
To: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
	Thomas Gleixner <tglx@linutronix.de>,
	Andreas Hindborg <a.hindborg@kernel.org>,
	FUJITA Tomonori <fujita.tomonori@gmail.com>
Cc: "Boqun Feng" <boqun.feng@gmail.com>,
	"Frederic Weisbecker" <frederic@kernel.org>,
	"Anna-Maria Behnsen" <anna-maria@linutronix.de>,
	"John Stultz" <jstultz@google.com>,
	"Stephen Boyd" <sboyd@kernel.org>,
	"Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <lossin@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Danilo Krummrich" <dakr@kernel.org>
Subject: [PATCH v3 2/2] rust: time: Implement basic arithmetic operations for Delta
Date: Wed, 20 Aug 2025 16:26:44 -0400	[thread overview]
Message-ID: <20250820203704.731588-3-lyude@redhat.com> (raw)
In-Reply-To: <20250820203704.731588-1-lyude@redhat.com>

While rvkms is only going to be using a few of these, since Deltas are
basically the same as i64 it's easy enough to just implement all of the
basic arithmetic operations for Delta types.

Keep in mind there's one quirk here - the kernel has no support for
i64 % i64 on 32 bit platforms, the closest we have is i64 % i32 through
div_s64_rem(). So, instead of implementing ops::Rem or ops::RemAssign we
simply provide Delta::rem_nanos().

Signed-off-by: Lyude Paul <lyude@redhat.com>

---
V2:
* Don't forget to make sure that we inline all of these
* Drop ops::Rem and ops::RemAssign implementations for Delta, replace with
  Delta::rem_nanos() instead. It turns out that there's actually no way to
  perform i64 % i64 on 32 bit platforms in the kernel at the moment, the
  closest that we have is div_s64_rem() which only allows a 32 bit divisor.
* Actually use the kernel arithmetic helpers for division/remainders so
  that this code works on both 32 and 64 bit platforms.
V3:
* Change the output type for Div to i64, drop DivAssign
* Change Mul/MulAssign to accept i64, not another Delta
* Fix parameter name in rem_nanos (ns -> dividend)

 rust/kernel/time.rs | 98 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 98 insertions(+)

diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
index 4bd7a8a009f3e..e64c5b13152dd 100644
--- a/rust/kernel/time.rs
+++ b/rust/kernel/time.rs
@@ -265,6 +265,78 @@ pub struct Delta {
     nanos: i64,
 }
 
+impl ops::Add for Delta {
+    type Output = Self;
+
+    #[inline]
+    fn add(self, rhs: Self) -> Self {
+        Self {
+            nanos: self.nanos + rhs.nanos,
+        }
+    }
+}
+
+impl ops::AddAssign for Delta {
+    #[inline]
+    fn add_assign(&mut self, rhs: Self) {
+        self.nanos += rhs.nanos;
+    }
+}
+
+impl ops::Sub for Delta {
+    type Output = Self;
+
+    #[inline]
+    fn sub(self, rhs: Self) -> Self::Output {
+        Self {
+            nanos: self.nanos - rhs.nanos,
+        }
+    }
+}
+
+impl ops::SubAssign for Delta {
+    #[inline]
+    fn sub_assign(&mut self, rhs: Self) {
+        self.nanos -= rhs.nanos;
+    }
+}
+
+impl ops::Mul<i64> for Delta {
+    type Output = Self;
+
+    #[inline]
+    fn mul(self, rhs: i64) -> Self::Output {
+        Self {
+            nanos: self.nanos * rhs,
+        }
+    }
+}
+
+impl ops::MulAssign<i64> for Delta {
+    #[inline]
+    fn mul_assign(&mut self, rhs: i64) {
+        self.nanos *= rhs;
+    }
+}
+
+impl ops::Div for Delta {
+    type Output = i64;
+
+    #[inline]
+    fn div(self, rhs: Self) -> Self::Output {
+        #[cfg(CONFIG_64BIT)]
+        {
+            self.nanos / rhs.nanos
+        }
+
+        #[cfg(not(CONFIG_64BIT))]
+        {
+            // SAFETY: This function is always safe to call regardless of the input values
+            unsafe { bindings::div64_s64(self.nanos, rhs.nanos) }
+        }
+    }
+}
+
 impl Delta {
     /// A span of time equal to zero.
     pub const ZERO: Self = Self { nanos: 0 };
@@ -353,4 +425,30 @@ pub fn as_millis(self) -> i64 {
             bindings::ktime_to_ms(self.as_nanos())
         }
     }
+
+    /// Return `self % dividend` where `dividend` is in nanoseconds.
+    ///
+    /// The kernel doesn't have any emulation for `s64 % s64` on 32 bit platforms, so this is
+    /// limited to 32 bit dividends.
+    #[inline]
+    pub fn rem_nanos(self, dividend: i32) -> Self {
+        #[cfg(CONFIG_64BIT)]
+        {
+            Self {
+                nanos: self.as_nanos() % i64::from(dividend),
+            }
+        }
+
+        #[cfg(not(CONFIG_64BIT))]
+        {
+            let mut rem = 0;
+
+            // SAFETY: `rem` is in the stack, so we can always provide a valid pointer to it.
+            unsafe { bindings::div_s64_rem(self.as_nanos(), dividend, &mut rem) };
+
+            Self {
+                nanos: i64::from(rem),
+            }
+        }
+    }
 }
-- 
2.50.0


  parent reply	other threads:[~2025-08-20 20:37 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-08-20 20:26 [PATCH v3 0/2] Arithmetic ops for Instant/Delta Lyude Paul
2025-08-20 20:26 ` [PATCH v3 1/2] rust: time: Implement Add<Delta>/Sub<Delta> for Instant Lyude Paul
2025-08-26  9:25   ` Andreas Hindborg
2025-08-26 12:23   ` FUJITA Tomonori
2025-08-26 14:11   ` Daniel Almeida
2025-08-26 20:59     ` Lyude Paul
2025-08-26 21:19       ` Daniel Almeida
2025-08-27 10:29   ` Alice Ryhl
2025-08-20 20:26 ` Lyude Paul [this message]
2025-08-26  9:26   ` [PATCH v3 2/2] rust: time: Implement basic arithmetic operations for Delta Andreas Hindborg
2025-08-26 12:58   ` FUJITA Tomonori
2025-08-26 14:28   ` Daniel Almeida

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=20250820203704.731588-3-lyude@redhat.com \
    --to=lyude@redhat.com \
    --cc=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=anna-maria@linutronix.de \
    --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=lossin@kernel.org \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).