From 22b65a40574e597e1919ca22cc3535c2b541f764 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Wed, 20 Aug 2025 16:26:43 -0400 Subject: [PATCH] rust: time: Implement Add/Sub for Instant In order to copy the behavior rust currently follows for basic arithmetic operations and panic if the result of an addition or subtraction results in a value that would violate the invariants of Instant, but only if the kernel has overflow checking for rust enabled. Signed-off-by: Lyude Paul Reviewed-by: Alice Ryhl Reviewed-by: FUJITA Tomonori Reviewed-by: Andreas Hindborg Reviewed-by: Daniel Almeida Link: https://lore.kernel.org/r/20250820203704.731588-2-lyude@redhat.com Signed-off-by: Andreas Hindborg --- rust/kernel/time.rs | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs index 7320d8715bcc2..642c42a520a80 100644 --- a/rust/kernel/time.rs +++ b/rust/kernel/time.rs @@ -25,6 +25,7 @@ //! C header: [`include/linux/ktime.h`](srctree/include/linux/ktime.h). use core::marker::PhantomData; +use core::ops; pub mod delay; pub mod hrtimer; @@ -224,7 +225,7 @@ impl Instant { } } -impl core::ops::Sub for Instant { +impl ops::Sub for Instant { type Output = Delta; // By the type invariant, it never overflows. @@ -236,6 +237,46 @@ impl core::ops::Sub for Instant { } } +impl ops::Add for Instant { + type Output = Self; + + #[inline] + 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; + + // INVARIANT: With overflow checks enabled, we verify here that the value is >= 0 + #[cfg(CONFIG_RUST_OVERFLOW_CHECKS)] + assert!(res >= 0); + + Self { + inner: res, + _c: PhantomData, + } + } +} + +impl ops::Sub for Instant { + type Output = Self; + + #[inline] + 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; + + // INVARIANT: With overflow checks enabled, we verify here that the value is >= 0 + #[cfg(CONFIG_RUST_OVERFLOW_CHECKS)] + assert!(res >= 0); + + Self { + inner: res, + _c: PhantomData, + } + } +} + /// A span of time. /// /// This struct represents a span of time, with its value stored as nanoseconds. -- 2.47.3