Rust for Linux List
 help / color / mirror / Atom feed
* [PATCH v3 0/2] rust: use Delta and new Jiffies type instead of raw jiffies for timeouts and delays
@ 2026-07-17  4:22 FUJITA Tomonori
  2026-07-17  4:22 ` [PATCH v3 1/2] rust: time: add Delta::as_millis_ceil() FUJITA Tomonori
  2026-07-17  4:22 ` [PATCH v3 2/2] rust: use Delta and a Jiffies newtype for timeouts and delays FUJITA Tomonori
  0 siblings, 2 replies; 8+ messages in thread
From: FUJITA Tomonori @ 2026-07-17  4:22 UTC (permalink / raw)
  To: a.hindborg, aliceryhl, arve, boqun, brauner, cmllamas, gary,
	gregkh, ojeda, tkjos
  Cc: acourbot, anna-maria, bjorn3_gh, dakr, daniel.almeida, frederic,
	jstultz, lossin, lyude, sboyd, tamird, tglx, tmgross, work,
	rust-for-linux, FUJITA Tomonori

From: FUJITA Tomonori <fujita.tomonori@gmail.com>

CondVar::wait_interruptible_timeout() and Queue::enqueue_delayed() use
a raw jiffies count (a plain c_ulong alias with no type
safety). Callers have to know on their own that the value meant
jiffies and convert to/from it themselves, which is easy to get wrong
(e.g. passing a millisecond value where a jiffies value is expected).

Unlike the previous versions, v3 introduces a dedicated `Jiffies`
newtype instead. The APIs take `impl Into<Jiffies>`, so a caller can
pass either a `Delta` (the duration is converted once, rounding up) or
a `Jiffies` directly with no conversion. Jiffies returned by the C
side stay as `Jiffies`, so a caller that works in jiffies never
converts and the round trip is gone.

Why a `Jiffies` type, but no `Micros`/`Nanos`/... types?

`Delta` represents a span of time as a nanosecond count. Microseconds,
milliseconds and seconds are exact multiples of a nanosecond, so they
embed into `Delta` losslessly and round-trip through it losslessly; they
are already covered by Delta's constructors and accessors (from_millis(),
as_millis_ceil(), ...) and would gain nothing from their own types.

A jiffy is 1/HZ of a second, which is generally not an exact number of
nanoseconds (e.g. HZ=300). Converting between jiffies and Delta is
therefore inherently lossy in both directions, and that is exactly
what makes a jiffies count a distinct quantity -- a count of timer
ticks -- rather than just another way to spell a Delta. So it, and
only it, gets its own (unsigned) newtype.

The Delta -> Jiffies conversion reuses the C `__msecs_to_jiffies()`
helper -- the same routine the existing Rust `msecs_to_jiffies()`
wrapper already called. The arithmetic (and the range clamping) is
done on the C side so it works on 32-bit architectures.

v3:
- Add new Jiffies type and convert the APIs to take impl Into<Jiffies>
v2: https://lore.kernel.org/rust-for-linux/20260712235246.3069713-1-tomo@flapping.org/
- Fix potential overflow in from_jiffies()
- Fix inflating bug in as_jiffies_ceil()
- Add a patch to convert enqueue_delayed()
- Add a patch to remove Jiffies/Msecs aliases
v1: https://lore.kernel.org/rust-for-linux/20260704132558.2253275-1-tomo@aliasing.net/

FUJITA Tomonori (2):
  rust: time: add Delta::as_millis_ceil()
  rust: use Delta and a Jiffies newtype for timeouts and delays

 drivers/android/binder/process.rs |  7 ++--
 rust/kernel/sync/condvar.rs       | 21 +++++++---
 rust/kernel/time.rs               | 64 ++++++++++++++++++++++++++-----
 rust/kernel/workqueue.rs          | 11 ++++--
 4 files changed, 82 insertions(+), 21 deletions(-)


base-commit: 7059bdf4f04a3e14f4fafb3ac35fdca913e3e21a
-- 
2.43.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH v3 1/2] rust: time: add Delta::as_millis_ceil()
  2026-07-17  4:22 [PATCH v3 0/2] rust: use Delta and new Jiffies type instead of raw jiffies for timeouts and delays FUJITA Tomonori
@ 2026-07-17  4:22 ` FUJITA Tomonori
  2026-07-17  4:22 ` [PATCH v3 2/2] rust: use Delta and a Jiffies newtype for timeouts and delays FUJITA Tomonori
  1 sibling, 0 replies; 8+ messages in thread
From: FUJITA Tomonori @ 2026-07-17  4:22 UTC (permalink / raw)
  To: a.hindborg, aliceryhl, arve, boqun, brauner, cmllamas, gary,
	gregkh, ojeda, tkjos
  Cc: acourbot, anna-maria, bjorn3_gh, dakr, daniel.almeida, frederic,
	jstultz, lossin, lyude, sboyd, tamird, tglx, tmgross, work,
	rust-for-linux, FUJITA Tomonori

From: FUJITA Tomonori <fujita.tomonori@gmail.com>

Add a ceiling variant, mirroring the existing as_micros_ceil() since
the existing as_millis() truncates towards zero.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 rust/kernel/time.rs | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
index 363e93cbb139..23ef5c77383f 100644
--- a/rust/kernel/time.rs
+++ b/rust/kernel/time.rs
@@ -468,6 +468,29 @@ pub fn as_millis(self) -> i64 {
         }
     }
 
+    /// Return the smallest number of milliseconds greater than or equal
+    /// to the value in the [`Delta`].
+    #[inline]
+    pub fn as_millis_ceil(self) -> i64 {
+        let n = self.as_nanos();
+        let n = if n > 0 {
+            n.saturating_add(NSEC_PER_MSEC - 1)
+        } else {
+            n
+        };
+
+        #[cfg(CONFIG_64BIT)]
+        {
+            n / NSEC_PER_MSEC
+        }
+
+        #[cfg(not(CONFIG_64BIT))]
+        // SAFETY: It is always safe to call `ktime_to_ms()` with any value.
+        unsafe {
+            bindings::ktime_to_ms(n)
+        }
+    }
+
     /// 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
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH v3 2/2] rust: use Delta and a Jiffies newtype for timeouts and delays
  2026-07-17  4:22 [PATCH v3 0/2] rust: use Delta and new Jiffies type instead of raw jiffies for timeouts and delays FUJITA Tomonori
  2026-07-17  4:22 ` [PATCH v3 1/2] rust: time: add Delta::as_millis_ceil() FUJITA Tomonori
@ 2026-07-17  4:22 ` FUJITA Tomonori
  2026-07-18 15:20   ` Gary Guo
  1 sibling, 1 reply; 8+ messages in thread
From: FUJITA Tomonori @ 2026-07-17  4:22 UTC (permalink / raw)
  To: a.hindborg, aliceryhl, arve, boqun, brauner, cmllamas, gary,
	gregkh, ojeda, tkjos
  Cc: acourbot, anna-maria, bjorn3_gh, dakr, daniel.almeida, frederic,
	jstultz, lossin, lyude, sboyd, tamird, tglx, tmgross, work,
	rust-for-linux, FUJITA Tomonori

From: FUJITA Tomonori <fujita.tomonori@gmail.com>

Turn Jiffies into a distinct newtype and let these APIs take
impl Into<Jiffies>. A caller can now pass a Delta, the duration type
already used elsewhere, so the unit is part of the type rather than a
caller convention. A caller that already holds a jiffies count can
still pass Jiffies directly, avoiding a lossy jiffies -> Delta ->
jiffies round trip.

Update CondVar::wait_interruptible_timeout() and
Queue::enqueue_delayed(), which took a raw jiffies count through a
bare c_ulong alias with no type safety. Callers had to know on their
own that the value meant jiffies and convert to and from it
themselves, which is easy to get wrong.

Once callers express timeouts and delays as Delta, msecs_to_jiffies()
and the Msecs alias have no remaining users, so remove them.

Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
 drivers/android/binder/process.rs |  7 +++---
 rust/kernel/sync/condvar.rs       | 21 +++++++++++-----
 rust/kernel/time.rs               | 41 ++++++++++++++++++++++++-------
 rust/kernel/workqueue.rs          | 11 ++++++---
 4 files changed, 59 insertions(+), 21 deletions(-)

diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
index cdd1a9079726..5230ea492a75 100644
--- a/drivers/android/binder/process.rs
+++ b/drivers/android/binder/process.rs
@@ -1482,8 +1482,9 @@ pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
         inner.is_frozen = IsFrozen::InProgress;
 
         if info.timeout_ms > 0 {
-            let mut jiffies = kernel::time::msecs_to_jiffies(info.timeout_ms);
-            while jiffies > 0 {
+            let mut jiffies: kernel::time::Jiffies =
+                kernel::time::Delta::from_millis(info.timeout_ms.into()).into();
+            while !jiffies.is_zero() {
                 if inner.outstanding_txns == 0 {
                     break;
                 }
@@ -1500,7 +1501,7 @@ pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
                         jiffies = remaining;
                     }
                     CondVarTimeoutResult::Timeout => {
-                        jiffies = 0;
+                        jiffies = kernel::time::Jiffies::ZERO;
                     }
                 }
             }
diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
index 69d58dfbad7b..e215f83825e4 100644
--- a/rust/kernel/sync/condvar.rs
+++ b/rust/kernel/sync/condvar.rs
@@ -7,7 +7,7 @@
 
 use super::{lock::Backend, lock::Guard, LockClassKey};
 use crate::{
-    ffi::{c_int, c_long},
+    ffi::{c_int, c_long, c_ulong},
     str::{CStr, CStrExt as _},
     task::{
         MAX_SCHEDULE_TIMEOUT, TASK_FREEZABLE, TASK_INTERRUPTIBLE, TASK_NORMAL, TASK_UNINTERRUPTIBLE,
@@ -186,15 +186,24 @@ pub fn wait_interruptible_freezable<T: ?Sized, B: Backend>(
     pub fn wait_interruptible_timeout<T: ?Sized, B: Backend>(
         &self,
         guard: &mut Guard<'_, T, B>,
-        jiffies: Jiffies,
+        duration: impl Into<Jiffies>,
     ) -> CondVarTimeoutResult {
-        let jiffies = jiffies.try_into().unwrap_or(MAX_SCHEDULE_TIMEOUT);
+        let raw_jiffies: c_ulong = duration.into().as_raw();
+        let jiffies = c_long::try_from(raw_jiffies).unwrap_or(MAX_SCHEDULE_TIMEOUT);
         let res = self.wait_internal(TASK_INTERRUPTIBLE, guard, jiffies);
 
-        match (res as Jiffies, crate::current!().signal_pending()) {
-            (jiffies, true) => CondVarTimeoutResult::Signal { jiffies },
+        match (res, crate::current!().signal_pending()) {
+            (jiffies, true) => CondVarTimeoutResult::Signal {
+                // CAST: `wait_internal()` never returns negative,
+                // so it is safe to cast `jiffies` to `c_ulong`.
+                jiffies: Jiffies::new(jiffies as c_ulong),
+            },
             (0, false) => CondVarTimeoutResult::Timeout,
-            (jiffies, false) => CondVarTimeoutResult::Woken { jiffies },
+            (jiffies, false) => CondVarTimeoutResult::Woken {
+                // CAST: `wait_internal()` never returns negative,
+                // so it is safe to cast `jiffies` to `c_ulong`.
+                jiffies: Jiffies::new(jiffies as c_ulong),
+            },
         }
     }
 
diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
index 23ef5c77383f..206296b6b6ea 100644
--- a/rust/kernel/time.rs
+++ b/rust/kernel/time.rs
@@ -40,17 +40,40 @@
 pub const NSEC_PER_SEC: i64 = bindings::NSEC_PER_SEC as i64;
 
 /// The time unit of Linux kernel. One jiffy equals (1/HZ) second.
-pub type Jiffies = crate::ffi::c_ulong;
+#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
+pub struct Jiffies(crate::ffi::c_ulong);
 
-/// The millisecond time unit.
-pub type Msecs = crate::ffi::c_uint;
+impl Jiffies {
+    /// A jiffies value of zero.
+    pub const ZERO: Self = Self(0);
 
-/// Converts milliseconds to jiffies.
-#[inline]
-pub fn msecs_to_jiffies(msecs: Msecs) -> Jiffies {
-    // SAFETY: The `__msecs_to_jiffies` function is always safe to call no
-    // matter what the argument is.
-    unsafe { bindings::__msecs_to_jiffies(msecs) }
+    /// Create a new [`Jiffies`] from the C side's `jiffies` value.
+    #[inline]
+    pub const fn new(jiffies: crate::ffi::c_ulong) -> Self {
+        Self(jiffies)
+    }
+
+    #[inline]
+    pub(crate) const fn as_raw(self) -> crate::ffi::c_ulong {
+        self.0
+    }
+
+    /// Return `true` if the [`Jiffies`] has a value of zero.
+    #[inline]
+    pub fn is_zero(self) -> bool {
+        self.0 == 0
+    }
+}
+
+impl From<Delta> for Jiffies {
+    #[inline]
+    fn from(delta: Delta) -> Self {
+        let millis = u32::try_from(delta.as_millis_ceil().max(0)).unwrap_or(u32::MAX);
+        // SAFETY: The `__msecs_to_jiffies` function is always safe to call no
+        // matter what the argument is.
+        let jiffies = unsafe { bindings::__msecs_to_jiffies(millis) };
+        Self(jiffies)
+    }
 }
 
 /// Trait for clock sources.
diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
index 7e253b6f299c..41fa1a9eb9d7 100644
--- a/rust/kernel/workqueue.rs
+++ b/rust/kernel/workqueue.rs
@@ -136,6 +136,7 @@
 //! ```
 //! use kernel::sync::Arc;
 //! use kernel::workqueue::{self, impl_has_delayed_work, new_delayed_work, DelayedWork, WorkItem};
+//! use kernel::time::Jiffies;
 //!
 //! #[pin_data]
 //! struct MyStruct {
@@ -171,7 +172,7 @@
 //! /// This method will enqueue the struct for execution on the system workqueue, where its value
 //! /// will be printed 12 jiffies later.
 //! fn print_later(val: Arc<MyStruct>) {
-//!     let _ = workqueue::system().enqueue_delayed(val, 12);
+//!     let _ = workqueue::system().enqueue_delayed(val, Jiffies::new(12));
 //! }
 //!
 //! /// It is also possible to use the ordinary `enqueue` method together with `DelayedWork`. This
@@ -303,7 +304,11 @@ pub fn enqueue<W, const ID: u64>(&self, w: W) -> W::EnqueueOutput
     /// This may fail if the work item is already enqueued in a workqueue.
     ///
     /// The work item will be submitted using `WORK_CPU_UNBOUND`.
-    pub fn enqueue_delayed<W, const ID: u64>(&self, w: W, delay: Jiffies) -> W::EnqueueOutput
+    pub fn enqueue_delayed<W, const ID: u64>(
+        &self,
+        w: W,
+        delay: impl Into<Jiffies>,
+    ) -> W::EnqueueOutput
     where
         W: RawDelayedWorkItem<ID> + Send + 'static,
     {
@@ -328,7 +333,7 @@ pub fn enqueue_delayed<W, const ID: u64>(&self, w: W, delay: Jiffies) -> W::Enqu
                     bindings::wq_misc_consts_WORK_CPU_UNBOUND as ffi::c_int,
                     queue_ptr,
                     container_of!(work_ptr, bindings::delayed_work, work),
-                    delay,
+                    delay.into().as_raw(),
                 )
             })
         }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 2/2] rust: use Delta and a Jiffies newtype for timeouts and delays
  2026-07-17  4:22 ` [PATCH v3 2/2] rust: use Delta and a Jiffies newtype for timeouts and delays FUJITA Tomonori
@ 2026-07-18 15:20   ` Gary Guo
  2026-07-20  9:47     ` FUJITA Tomonori
  0 siblings, 1 reply; 8+ messages in thread
From: Gary Guo @ 2026-07-18 15:20 UTC (permalink / raw)
  To: FUJITA Tomonori, a.hindborg, aliceryhl, arve, boqun, brauner,
	cmllamas, gary, gregkh, ojeda, tkjos
  Cc: acourbot, anna-maria, bjorn3_gh, dakr, daniel.almeida, frederic,
	jstultz, lossin, lyude, sboyd, tamird, tglx, tmgross, work,
	rust-for-linux, FUJITA Tomonori

On Fri Jul 17, 2026 at 5:22 AM BST, FUJITA Tomonori wrote:
> From: FUJITA Tomonori <fujita.tomonori@gmail.com>
>
> Turn Jiffies into a distinct newtype and let these APIs take
> impl Into<Jiffies>. A caller can now pass a Delta, the duration type
> already used elsewhere, so the unit is part of the type rather than a
> caller convention. A caller that already holds a jiffies count can
> still pass Jiffies directly, avoiding a lossy jiffies -> Delta ->
> jiffies round trip.
>
> Update CondVar::wait_interruptible_timeout() and
> Queue::enqueue_delayed(), which took a raw jiffies count through a
> bare c_ulong alias with no type safety. Callers had to know on their
> own that the value meant jiffies and convert to and from it
> themselves, which is easy to get wrong.
>
> Once callers express timeouts and delays as Delta, msecs_to_jiffies()
> and the Msecs alias have no remaining users, so remove them.
>
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
> ---
>  drivers/android/binder/process.rs |  7 +++---
>  rust/kernel/sync/condvar.rs       | 21 +++++++++++-----
>  rust/kernel/time.rs               | 41 ++++++++++++++++++++++++-------
>  rust/kernel/workqueue.rs          | 11 ++++++---
>  4 files changed, 59 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
> index cdd1a9079726..5230ea492a75 100644
> --- a/drivers/android/binder/process.rs
> +++ b/drivers/android/binder/process.rs
> @@ -1482,8 +1482,9 @@ pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
>          inner.is_frozen = IsFrozen::InProgress;
>  
>          if info.timeout_ms > 0 {
> -            let mut jiffies = kernel::time::msecs_to_jiffies(info.timeout_ms);
> -            while jiffies > 0 {
> +            let mut jiffies: kernel::time::Jiffies =
> +                kernel::time::Delta::from_millis(info.timeout_ms.into()).into();
> +            while !jiffies.is_zero() {
>                  if inner.outstanding_txns == 0 {
>                      break;
>                  }
> @@ -1500,7 +1501,7 @@ pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
>                          jiffies = remaining;
>                      }
>                      CondVarTimeoutResult::Timeout => {
> -                        jiffies = 0;
> +                        jiffies = kernel::time::Jiffies::ZERO;
>                      }
>                  }
>              }
> diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
> index 69d58dfbad7b..e215f83825e4 100644
> --- a/rust/kernel/sync/condvar.rs
> +++ b/rust/kernel/sync/condvar.rs
> @@ -7,7 +7,7 @@
>  
>  use super::{lock::Backend, lock::Guard, LockClassKey};
>  use crate::{
> -    ffi::{c_int, c_long},
> +    ffi::{c_int, c_long, c_ulong},
>      str::{CStr, CStrExt as _},
>      task::{
>          MAX_SCHEDULE_TIMEOUT, TASK_FREEZABLE, TASK_INTERRUPTIBLE, TASK_NORMAL, TASK_UNINTERRUPTIBLE,
> @@ -186,15 +186,24 @@ pub fn wait_interruptible_freezable<T: ?Sized, B: Backend>(
>      pub fn wait_interruptible_timeout<T: ?Sized, B: Backend>(
>          &self,
>          guard: &mut Guard<'_, T, B>,
> -        jiffies: Jiffies,
> +        duration: impl Into<Jiffies>,
>      ) -> CondVarTimeoutResult {
> -        let jiffies = jiffies.try_into().unwrap_or(MAX_SCHEDULE_TIMEOUT);
> +        let raw_jiffies: c_ulong = duration.into().as_raw();
> +        let jiffies = c_long::try_from(raw_jiffies).unwrap_or(MAX_SCHEDULE_TIMEOUT);

This is existing problem, but this code pretty much assumes that
`MAX_SCHEDULE_TIMEOUT == c_long::MAX`, which is true but would be bad code. So I
would expect this to be just a compare, or would eventually become
`saturating_cast_signed` (once it's stable) which explicitly relies on that
assumption.

>          let res = self.wait_internal(TASK_INTERRUPTIBLE, guard, jiffies);
>  
> -        match (res as Jiffies, crate::current!().signal_pending()) {
> -            (jiffies, true) => CondVarTimeoutResult::Signal { jiffies },
> +        match (res, crate::current!().signal_pending()) {
> +            (jiffies, true) => CondVarTimeoutResult::Signal {
> +                // CAST: `wait_internal()` never returns negative,
> +                // so it is safe to cast `jiffies` to `c_ulong`.
> +                jiffies: Jiffies::new(jiffies as c_ulong),
> +            },
>              (0, false) => CondVarTimeoutResult::Timeout,
> -            (jiffies, false) => CondVarTimeoutResult::Woken { jiffies },
> +            (jiffies, false) => CondVarTimeoutResult::Woken {
> +                // CAST: `wait_internal()` never returns negative,
> +                // so it is safe to cast `jiffies` to `c_ulong`.
> +                jiffies: Jiffies::new(jiffies as c_ulong),
> +            },
>          }
>      }
>  
> diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
> index 23ef5c77383f..206296b6b6ea 100644
> --- a/rust/kernel/time.rs
> +++ b/rust/kernel/time.rs
> @@ -40,17 +40,40 @@
>  pub const NSEC_PER_SEC: i64 = bindings::NSEC_PER_SEC as i64;
>  
>  /// The time unit of Linux kernel. One jiffy equals (1/HZ) second.
> -pub type Jiffies = crate::ffi::c_ulong;
> +#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
> +pub struct Jiffies(crate::ffi::c_ulong);

Hmm, I feel that we are again making the same mistake that we had for `ktime_t`
abstraction, namely that we use the same type for instant and delta, albeit this
time the measure unit is jiffies and not nanoseconds. The reason that signed and
unsigned casts is needed in the above code basically is this.

Arguably, your earlier version don't have this issue, but then we are
introducing costly divisions implicitly in many places which is bad for
different reason.

I wonder if we should have time types being generic over units. So you can have
`Delta<Nsec>` and `Delta<Jiffy>` and `Instant<Nsec>`, `Instant<Jiffy>`, with the
generic default being set to `Nsec`.

    Delta::new(42) // Delta<Nsec>
    Delta::new_jiffies(42) // Delta<Jiffy>

Thoughts?

Best,
Gary

>  
> -/// The millisecond time unit.
> -pub type Msecs = crate::ffi::c_uint;
> +impl Jiffies {
> +    /// A jiffies value of zero.
> +    pub const ZERO: Self = Self(0);
>  
> -/// Converts milliseconds to jiffies.
> -#[inline]
> -pub fn msecs_to_jiffies(msecs: Msecs) -> Jiffies {
> -    // SAFETY: The `__msecs_to_jiffies` function is always safe to call no
> -    // matter what the argument is.
> -    unsafe { bindings::__msecs_to_jiffies(msecs) }
> +    /// Create a new [`Jiffies`] from the C side's `jiffies` value.
> +    #[inline]
> +    pub const fn new(jiffies: crate::ffi::c_ulong) -> Self {

Given that this is a public API not just for binding code, I think it's better
to use `usize`.

> +        Self(jiffies)
> +    }
> +

This function can be `pub`.

> +    #[inline]
> +    pub(crate) const fn as_raw(self) -> crate::ffi::c_ulong {
> +        self.0
> +    }
> +
> +    /// Return `true` if the [`Jiffies`] has a value of zero.
> +    #[inline]
> +    pub fn is_zero(self) -> bool {
> +        self.0 == 0
> +    }
> +}
> +
> +impl From<Delta> for Jiffies {
> +    #[inline]
> +    fn from(delta: Delta) -> Self {
> +        let millis = u32::try_from(delta.as_millis_ceil().max(0)).unwrap_or(u32::MAX);
> +        // SAFETY: The `__msecs_to_jiffies` function is always safe to call no
> +        // matter what the argument is.
> +        let jiffies = unsafe { bindings::__msecs_to_jiffies(millis) };
> +        Self(jiffies)
> +    }
>  }
>  
>  /// Trait for clock sources.
> diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
> index 7e253b6f299c..41fa1a9eb9d7 100644
> --- a/rust/kernel/workqueue.rs
> +++ b/rust/kernel/workqueue.rs
> @@ -136,6 +136,7 @@
>  //! ```
>  //! use kernel::sync::Arc;
>  //! use kernel::workqueue::{self, impl_has_delayed_work, new_delayed_work, DelayedWork, WorkItem};
> +//! use kernel::time::Jiffies;
>  //!
>  //! #[pin_data]
>  //! struct MyStruct {
> @@ -171,7 +172,7 @@
>  //! /// This method will enqueue the struct for execution on the system workqueue, where its value
>  //! /// will be printed 12 jiffies later.
>  //! fn print_later(val: Arc<MyStruct>) {
> -//!     let _ = workqueue::system().enqueue_delayed(val, 12);
> +//!     let _ = workqueue::system().enqueue_delayed(val, Jiffies::new(12));
>  //! }
>  //!
>  //! /// It is also possible to use the ordinary `enqueue` method together with `DelayedWork`. This
> @@ -303,7 +304,11 @@ pub fn enqueue<W, const ID: u64>(&self, w: W) -> W::EnqueueOutput
>      /// This may fail if the work item is already enqueued in a workqueue.
>      ///
>      /// The work item will be submitted using `WORK_CPU_UNBOUND`.
> -    pub fn enqueue_delayed<W, const ID: u64>(&self, w: W, delay: Jiffies) -> W::EnqueueOutput
> +    pub fn enqueue_delayed<W, const ID: u64>(
> +        &self,
> +        w: W,
> +        delay: impl Into<Jiffies>,
> +    ) -> W::EnqueueOutput
>      where
>          W: RawDelayedWorkItem<ID> + Send + 'static,
>      {
> @@ -328,7 +333,7 @@ pub fn enqueue_delayed<W, const ID: u64>(&self, w: W, delay: Jiffies) -> W::Enqu
>                      bindings::wq_misc_consts_WORK_CPU_UNBOUND as ffi::c_int,
>                      queue_ptr,
>                      container_of!(work_ptr, bindings::delayed_work, work),
> -                    delay,
> +                    delay.into().as_raw(),
>                  )
>              })
>          }



^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 2/2] rust: use Delta and a Jiffies newtype for timeouts and delays
  2026-07-18 15:20   ` Gary Guo
@ 2026-07-20  9:47     ` FUJITA Tomonori
  2026-07-20 12:04       ` Gary Guo
  2026-07-20 18:16       ` John Stultz
  0 siblings, 2 replies; 8+ messages in thread
From: FUJITA Tomonori @ 2026-07-20  9:47 UTC (permalink / raw)
  To: gary
  Cc: tomo, a.hindborg, aliceryhl, arve, boqun, brauner, cmllamas,
	gregkh, ojeda, tkjos, acourbot, anna-maria, bjorn3_gh, dakr,
	daniel.almeida, frederic, jstultz, lossin, lyude, sboyd, tamird,
	tglx, tmgross, work, rust-for-linux, fujita.tomonori

On Sat, 18 Jul 2026 16:20:10 +0100
"Gary Guo" <gary@garyguo.net> wrote:

> On Fri Jul 17, 2026 at 5:22 AM BST, FUJITA Tomonori wrote:
>> From: FUJITA Tomonori <fujita.tomonori@gmail.com>
>>
>> Turn Jiffies into a distinct newtype and let these APIs take
>> impl Into<Jiffies>. A caller can now pass a Delta, the duration type
>> already used elsewhere, so the unit is part of the type rather than a
>> caller convention. A caller that already holds a jiffies count can
>> still pass Jiffies directly, avoiding a lossy jiffies -> Delta ->
>> jiffies round trip.
>>
>> Update CondVar::wait_interruptible_timeout() and
>> Queue::enqueue_delayed(), which took a raw jiffies count through a
>> bare c_ulong alias with no type safety. Callers had to know on their
>> own that the value meant jiffies and convert to and from it
>> themselves, which is easy to get wrong.
>>
>> Once callers express timeouts and delays as Delta, msecs_to_jiffies()
>> and the Msecs alias have no remaining users, so remove them.
>>
>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
>> ---
>>  drivers/android/binder/process.rs |  7 +++---
>>  rust/kernel/sync/condvar.rs       | 21 +++++++++++-----
>>  rust/kernel/time.rs               | 41 ++++++++++++++++++++++++-------
>>  rust/kernel/workqueue.rs          | 11 ++++++---
>>  4 files changed, 59 insertions(+), 21 deletions(-)
>>
>> diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
>> index cdd1a9079726..5230ea492a75 100644
>> --- a/drivers/android/binder/process.rs
>> +++ b/drivers/android/binder/process.rs
>> @@ -1482,8 +1482,9 @@ pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
>>          inner.is_frozen = IsFrozen::InProgress;
>>  
>>          if info.timeout_ms > 0 {
>> -            let mut jiffies = kernel::time::msecs_to_jiffies(info.timeout_ms);
>> -            while jiffies > 0 {
>> +            let mut jiffies: kernel::time::Jiffies =
>> +                kernel::time::Delta::from_millis(info.timeout_ms.into()).into();
>> +            while !jiffies.is_zero() {
>>                  if inner.outstanding_txns == 0 {
>>                      break;
>>                  }
>> @@ -1500,7 +1501,7 @@ pub(crate) fn ioctl_freeze(&self, info: &BinderFreezeInfo) -> Result {
>>                          jiffies = remaining;
>>                      }
>>                      CondVarTimeoutResult::Timeout => {
>> -                        jiffies = 0;
>> +                        jiffies = kernel::time::Jiffies::ZERO;
>>                      }
>>                  }
>>              }
>> diff --git a/rust/kernel/sync/condvar.rs b/rust/kernel/sync/condvar.rs
>> index 69d58dfbad7b..e215f83825e4 100644
>> --- a/rust/kernel/sync/condvar.rs
>> +++ b/rust/kernel/sync/condvar.rs
>> @@ -7,7 +7,7 @@
>>  
>>  use super::{lock::Backend, lock::Guard, LockClassKey};
>>  use crate::{
>> -    ffi::{c_int, c_long},
>> +    ffi::{c_int, c_long, c_ulong},
>>      str::{CStr, CStrExt as _},
>>      task::{
>>          MAX_SCHEDULE_TIMEOUT, TASK_FREEZABLE, TASK_INTERRUPTIBLE, TASK_NORMAL, TASK_UNINTERRUPTIBLE,
>> @@ -186,15 +186,24 @@ pub fn wait_interruptible_freezable<T: ?Sized, B: Backend>(
>>      pub fn wait_interruptible_timeout<T: ?Sized, B: Backend>(
>>          &self,
>>          guard: &mut Guard<'_, T, B>,
>> -        jiffies: Jiffies,
>> +        duration: impl Into<Jiffies>,
>>      ) -> CondVarTimeoutResult {
>> -        let jiffies = jiffies.try_into().unwrap_or(MAX_SCHEDULE_TIMEOUT);
>> +        let raw_jiffies: c_ulong = duration.into().as_raw();
>> +        let jiffies = c_long::try_from(raw_jiffies).unwrap_or(MAX_SCHEDULE_TIMEOUT);
> 
> This is existing problem, but this code pretty much assumes that
> `MAX_SCHEDULE_TIMEOUT == c_long::MAX`, which is true but would be bad code. So I
> would expect this to be just a compare, or would eventually become
> `saturating_cast_signed` (once it's stable) which explicitly relies on that
> assumption.

Agreed - the fallback should be c_long::MAX, not MAX_SCHEDULE_TIMEOUT;
relying on the two being equal is exactly the kind of assumption to
avoid.

>> diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
>> index 23ef5c77383f..206296b6b6ea 100644
>> --- a/rust/kernel/time.rs
>> +++ b/rust/kernel/time.rs
>> @@ -40,17 +40,40 @@
>>  pub const NSEC_PER_SEC: i64 = bindings::NSEC_PER_SEC as i64;
>>  
>>  /// The time unit of Linux kernel. One jiffy equals (1/HZ) second.
>> -pub type Jiffies = crate::ffi::c_ulong;
>> +#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
>> +pub struct Jiffies(crate::ffi::c_ulong);
> 
> Hmm, I feel that we are again making the same mistake that we had for `ktime_t`
> abstraction, namely that we use the same type for instant and delta, albeit this
> time the measure unit is jiffies and not nanoseconds. The reason that signed and
> unsigned casts is needed in the above code basically is this.
> 
> Arguably, your earlier version don't have this issue, but then we are
> introducing costly divisions implicitly in many places which is bad for
> different reason.

Agreed.

> I wonder if we should have time types being generic over units. So you can have
> `Delta<Nsec>` and `Delta<Jiffy>` and `Instant<Nsec>`, `Instant<Jiffy>`, with the
> generic default being set to `Nsec`.
> 
>     Delta::new(42) // Delta<Nsec>
>     Delta::new_jiffies(42) // Delta<Jiffy>
> 
> Thoughts?

I think making Delta generic over the time unit makes sense; Delta
<Nsec> and Delta<Jiffy>.

However, I don't think making Instant generic over the time unit is a
good idea, even though it clearly is for Delta.

Instant is already generic over ClockSource, and jiffies is not a
clock source: it has no clockid_t, it is read via get_jiffies_64()
rather than ktime_get(), and it cannot be armed through hrtimer. That
leaves two ways to force a jiffies Instant, both looks wrong:

a) Add a second unit parameter, Instant<C, Unit>. But then the type
admits meaningless combinations - there is no Instant<Monotonic,
Jiffy> - and jiffies still has no ClockSource to put in the C slot, so
(a) really collapses into (b).

b) Make jiffies a fake ClockSource. But ClockSource::ID is passed
straight to hrtimer_setup(), so a fabricated clockid_t would make
HrTimer over jiffies type-check even though there is no corresponding
C operation.

This matches the C world: for deltas, jiffy and nsec interconvert
(nsecs_to_jiffies() and friends), which is exactly what Delta<Unit>
with conversions models. But the jiffies counter and ktime_get()
values are never mixed - there isn't even an API to compare or convert
between them - so there is no unit-generic notion of an instant to
represent. A jiffies point in time, should be its own concrete type
rather than a specialization of Instant.


>> -/// The millisecond time unit.
>> -pub type Msecs = crate::ffi::c_uint;
>> +impl Jiffies {
>> +    /// A jiffies value of zero.
>> +    pub const ZERO: Self = Self(0);
>>  
>> -/// Converts milliseconds to jiffies.
>> -#[inline]
>> -pub fn msecs_to_jiffies(msecs: Msecs) -> Jiffies {
>> -    // SAFETY: The `__msecs_to_jiffies` function is always safe to call no
>> -    // matter what the argument is.
>> -    unsafe { bindings::__msecs_to_jiffies(msecs) }
>> +    /// Create a new [`Jiffies`] from the C side's `jiffies` value.
>> +    #[inline]
>> +    pub const fn new(jiffies: crate::ffi::c_ulong) -> Self {
> 
> Given that this is a public API not just for binding code, I think it's better
> to use `usize`.

Good point, I'll use usize.


> This function can be `pub`.
> 
>> +    #[inline]
>> +    pub(crate) const fn as_raw(self) -> crate::ffi::c_ulong {
>> +        self.0
>> +    }
>> +

I'd prefer to keep this pub(crate) until there's an in-tree user,
following the usual practice of not exposing public API without a
user. Also, if we do make it pub, it should return usize rather than
ffi::c_ulong, to stay consistent with the constructor change above. Do
you have a specific use case in mind that needs it public?

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 2/2] rust: use Delta and a Jiffies newtype for timeouts and delays
  2026-07-20  9:47     ` FUJITA Tomonori
@ 2026-07-20 12:04       ` Gary Guo
  2026-07-20 18:16       ` John Stultz
  1 sibling, 0 replies; 8+ messages in thread
From: Gary Guo @ 2026-07-20 12:04 UTC (permalink / raw)
  To: FUJITA Tomonori, gary
  Cc: a.hindborg, aliceryhl, arve, boqun, brauner, cmllamas, gregkh,
	ojeda, tkjos, acourbot, anna-maria, bjorn3_gh, dakr,
	daniel.almeida, frederic, jstultz, lossin, lyude, sboyd, tamird,
	tglx, tmgross, work, rust-for-linux, fujita.tomonori

On Mon Jul 20, 2026 at 10:47 AM BST, FUJITA Tomonori wrote:
>>> diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
>>> index 23ef5c77383f..206296b6b6ea 100644
>>> --- a/rust/kernel/time.rs
>>> +++ b/rust/kernel/time.rs
>>> @@ -40,17 +40,40 @@
>>>  pub const NSEC_PER_SEC: i64 = bindings::NSEC_PER_SEC as i64;
>>>  
>>>  /// The time unit of Linux kernel. One jiffy equals (1/HZ) second.
>>> -pub type Jiffies = crate::ffi::c_ulong;
>>> +#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
>>> +pub struct Jiffies(crate::ffi::c_ulong);
>> 
>> Hmm, I feel that we are again making the same mistake that we had for `ktime_t`
>> abstraction, namely that we use the same type for instant and delta, albeit this
>> time the measure unit is jiffies and not nanoseconds. The reason that signed and
>> unsigned casts is needed in the above code basically is this.
>> 
>> Arguably, your earlier version don't have this issue, but then we are
>> introducing costly divisions implicitly in many places which is bad for
>> different reason.
>
> Agreed.
>
>> I wonder if we should have time types being generic over units. So you can have
>> `Delta<Nsec>` and `Delta<Jiffy>` and `Instant<Nsec>`, `Instant<Jiffy>`, with the
>> generic default being set to `Nsec`.
>> 
>>     Delta::new(42) // Delta<Nsec>
>>     Delta::new_jiffies(42) // Delta<Jiffy>
>> 
>> Thoughts?
>
> I think making Delta generic over the time unit makes sense; Delta
> <Nsec> and Delta<Jiffy>.
>
> However, I don't think making Instant generic over the time unit is a
> good idea, even though it clearly is for Delta.
>
> Instant is already generic over ClockSource, and jiffies is not a
> clock source: it has no clockid_t, it is read via get_jiffies_64()
> rather than ktime_get(), and it cannot be armed through hrtimer. That
> leaves two ways to force a jiffies Instant, both looks wrong:
>
> a) Add a second unit parameter, Instant<C, Unit>. But then the type
> admits meaningless combinations - there is no Instant<Monotonic,
> Jiffy> - and jiffies still has no ClockSource to put in the C slot, so
> (a) really collapses into (b).

We could split the `ClockSource` trait to be a generic `ClockSource` that
supports everything and a `HrClockSource` that provides ID.

>
> b) Make jiffies a fake ClockSource. But ClockSource::ID is passed
> straight to hrtimer_setup(), so a fabricated clockid_t would make
> HrTimer over jiffies type-check even though there is no corresponding
> C operation.
>
> This matches the C world: for deltas, jiffy and nsec interconvert
> (nsecs_to_jiffies() and friends), which is exactly what Delta<Unit>
> with conversions models. But the jiffies counter and ktime_get()
> values are never mixed - there isn't even an API to compare or convert
> between them - so there is no unit-generic notion of an instant to
> represent. A jiffies point in time, should be its own concrete type
> rather than a specialization of Instant.

Well, `Instant` never inter-converts with anything, so a `Instant<Jiffies>`
would be fine too. That said, we can delay making the change until we have a
user that needs to get jiffies count. So far it seems that people just use it as
a delta only.
>
>
>>> -/// The millisecond time unit.
>>> -pub type Msecs = crate::ffi::c_uint;
>>> +impl Jiffies {
>>> +    /// A jiffies value of zero.
>>> +    pub const ZERO: Self = Self(0);
>>>  
>>> -/// Converts milliseconds to jiffies.
>>> -#[inline]
>>> -pub fn msecs_to_jiffies(msecs: Msecs) -> Jiffies {
>>> -    // SAFETY: The `__msecs_to_jiffies` function is always safe to call no
>>> -    // matter what the argument is.
>>> -    unsafe { bindings::__msecs_to_jiffies(msecs) }
>>> +    /// Create a new [`Jiffies`] from the C side's `jiffies` value.
>>> +    #[inline]
>>> +    pub const fn new(jiffies: crate::ffi::c_ulong) -> Self {
>> 
>> Given that this is a public API not just for binding code, I think it's better
>> to use `usize`.
>
> Good point, I'll use usize.
>
>
>> This function can be `pub`.
>> 
>>> +    #[inline]
>>> +    pub(crate) const fn as_raw(self) -> crate::ffi::c_ulong {
>>> +        self.0
>>> +    }
>>> +
>
> I'd prefer to keep this pub(crate) until there's an in-tree user,
> following the usual practice of not exposing public API without a
> user. Also, if we do make it pub, it should return usize rather than
> ffi::c_ulong, to stay consistent with the constructor change above. Do
> you have a specific use case in mind that needs it public?

I think knowing how many jiffies are there in a `Delta<Jiffy>` is a reasonable
need while getting a raw pointer type from other abstractions are more
suspicious for drivers.

Best,
Gary

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 2/2] rust: use Delta and a Jiffies newtype for timeouts and delays
  2026-07-20  9:47     ` FUJITA Tomonori
  2026-07-20 12:04       ` Gary Guo
@ 2026-07-20 18:16       ` John Stultz
  2026-07-21  9:57         ` FUJITA Tomonori
  1 sibling, 1 reply; 8+ messages in thread
From: John Stultz @ 2026-07-20 18:16 UTC (permalink / raw)
  To: FUJITA Tomonori
  Cc: gary, a.hindborg, aliceryhl, arve, boqun, brauner, cmllamas,
	gregkh, ojeda, tkjos, acourbot, anna-maria, bjorn3_gh, dakr,
	daniel.almeida, frederic, lossin, lyude, sboyd, tamird, tglx,
	tmgross, work, rust-for-linux, fujita.tomonori

On Mon, Jul 20, 2026 at 2:48 AM FUJITA Tomonori <tomo@flapping.org> wrote:
> On Sat, 18 Jul 2026 16:20:10 +0100
> "Gary Guo" <gary@garyguo.net> wrote:
> > I wonder if we should have time types being generic over units. So you can have
> > `Delta<Nsec>` and `Delta<Jiffy>` and `Instant<Nsec>`, `Instant<Jiffy>`, with the
> > generic default being set to `Nsec`.
> >
> >     Delta::new(42) // Delta<Nsec>
> >     Delta::new_jiffies(42) // Delta<Jiffy>
> >
> > Thoughts?
>
> I think making Delta generic over the time unit makes sense; Delta
> <Nsec> and Delta<Jiffy>.
>
> However, I don't think making Instant generic over the time unit is a
> good idea, even though it clearly is for Delta.
>
> Instant is already generic over ClockSource, and jiffies is not a
> clock source: it has no clockid_t, it is read via get_jiffies_64()
> rather than ktime_get(), and it cannot be armed through hrtimer. That
> leaves two ways to force a jiffies Instant, both looks wrong:

I read the above and thought, "but jiffies is a clocksource":
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/time/jiffies.c#n21

And then I realized there has been some unfortunate naming overlap,
where it seems the rust ClockSource seems to map to the clockid_t, not
to the clocksource concept that Linux uses to abstract the hardware
counter used as a source of time (for the majority of the clockids).

Very much a bikeshed request, but is it too late to rename this to
ClockID or something? So there is maybe less confusion when reading
across C and Rust code?

thanks
-john

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH v3 2/2] rust: use Delta and a Jiffies newtype for timeouts and delays
  2026-07-20 18:16       ` John Stultz
@ 2026-07-21  9:57         ` FUJITA Tomonori
  0 siblings, 0 replies; 8+ messages in thread
From: FUJITA Tomonori @ 2026-07-21  9:57 UTC (permalink / raw)
  To: jstultz
  Cc: tomo, gary, a.hindborg, aliceryhl, arve, boqun, brauner, cmllamas,
	gregkh, ojeda, tkjos, acourbot, anna-maria, bjorn3_gh, dakr,
	daniel.almeida, frederic, lossin, lyude, sboyd, tamird, tglx,
	tmgross, work, rust-for-linux, fujita.tomonori

On Mon, 20 Jul 2026 11:16:06 -0700
John Stultz <jstultz@google.com> wrote:

> On Mon, Jul 20, 2026 at 2:48 AM FUJITA Tomonori <tomo@flapping.org> wrote:
>> On Sat, 18 Jul 2026 16:20:10 +0100
>> "Gary Guo" <gary@garyguo.net> wrote:
>> > I wonder if we should have time types being generic over units. So you can have
>> > `Delta<Nsec>` and `Delta<Jiffy>` and `Instant<Nsec>`, `Instant<Jiffy>`, with the
>> > generic default being set to `Nsec`.
>> >
>> >     Delta::new(42) // Delta<Nsec>
>> >     Delta::new_jiffies(42) // Delta<Jiffy>
>> >
>> > Thoughts?
>>
>> I think making Delta generic over the time unit makes sense; Delta
>> <Nsec> and Delta<Jiffy>.
>>
>> However, I don't think making Instant generic over the time unit is a
>> good idea, even though it clearly is for Delta.
>>
>> Instant is already generic over ClockSource, and jiffies is not a
>> clock source: it has no clockid_t, it is read via get_jiffies_64()
>> rather than ktime_get(), and it cannot be armed through hrtimer. That
>> leaves two ways to force a jiffies Instant, both looks wrong:
> 
> I read the above and thought, "but jiffies is a clocksource":
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/time/jiffies.c#n21
> 
> And then I realized there has been some unfortunate naming overlap,
> where it seems the rust ClockSource seems to map to the clockid_t, not
> to the clocksource concept that Linux uses to abstract the hardware
> counter used as a source of time (for the majority of the clockids).
> 
> Very much a bikeshed request, but is it too late to rename this to
> ClockID or something? So there is maybe less confusion when reading
> across C and Rust code?

Ah, I misunderstood. Thanks for the pointer!

You're right; the trait carries the clockid_t, not the hardware
clocksource. It's not too late at all; I'll rename ClockSource to
ClockId.


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-07-21  9:57 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-17  4:22 [PATCH v3 0/2] rust: use Delta and new Jiffies type instead of raw jiffies for timeouts and delays FUJITA Tomonori
2026-07-17  4:22 ` [PATCH v3 1/2] rust: time: add Delta::as_millis_ceil() FUJITA Tomonori
2026-07-17  4:22 ` [PATCH v3 2/2] rust: use Delta and a Jiffies newtype for timeouts and delays FUJITA Tomonori
2026-07-18 15:20   ` Gary Guo
2026-07-20  9:47     ` FUJITA Tomonori
2026-07-20 12:04       ` Gary Guo
2026-07-20 18:16       ` John Stultz
2026-07-21  9:57         ` FUJITA Tomonori

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox