* [PATCH v1 0/3] rust: time: Introduce typed clock sources and generalize Instant
@ 2025-04-13 10:56 FUJITA Tomonori
2025-04-13 10:56 ` [PATCH v1 1/3] rust: time: replace ClockId enum with ClockSource trait FUJITA Tomonori
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: FUJITA Tomonori @ 2025-04-13 10:56 UTC (permalink / raw)
To: rust-for-linux
Cc: boqun.feng, a.hindborg, ojeda, alex.gaynor, gary, bjorn3_gh,
benno.lossin, aliceryhl, tmgross, dakr, frederic, lyude, tglx,
anna-maria, jstultz, sboyd
This patch series introduces a type-safe abstraction over clock
sources. The goal is to remove the need for runtime clock selection
(via ClockId) and instead leverage Rust's type system to statically
associate the Instant type with a specific clock.
This approach enables compile-time enforcement of clock correctness
across APIs.
This patchset can be applied on top of the instant and duration
patchset [1].
[1] https://lore.kernel.org/lkml/20250413104310.162045-1-fujita.tomonori@gmail.com/
FUJITA Tomonori (3):
rust: time: replace ClockId enum with ClockSource trait
rust: time: make Instant generic over ClockSource
rust: time: add ktime_get() to ClockSource trait
rust/helpers/time.c | 16 +++
rust/kernel/time.rs | 200 +++++++++++++++++-----------
rust/kernel/time/hrtimer.rs | 26 ++--
rust/kernel/time/hrtimer/arc.rs | 5 +-
rust/kernel/time/hrtimer/pin.rs | 5 +-
rust/kernel/time/hrtimer/pin_mut.rs | 7 +-
rust/kernel/time/hrtimer/tbox.rs | 5 +-
7 files changed, 167 insertions(+), 97 deletions(-)
base-commit: c15cdb5491cf0af24d5558cece48cff059c50785
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v1 1/3] rust: time: replace ClockId enum with ClockSource trait
2025-04-13 10:56 [PATCH v1 0/3] rust: time: Introduce typed clock sources and generalize Instant FUJITA Tomonori
@ 2025-04-13 10:56 ` FUJITA Tomonori
2025-04-22 12:51 ` Andreas Hindborg
2025-04-13 10:56 ` [PATCH v1 2/3] rust: time: make Instant generic over ClockSource FUJITA Tomonori
2025-04-13 10:56 ` [PATCH v1 3/3] rust: time: add ktime_get() to ClockSource trait FUJITA Tomonori
2 siblings, 1 reply; 9+ messages in thread
From: FUJITA Tomonori @ 2025-04-13 10:56 UTC (permalink / raw)
To: rust-for-linux
Cc: boqun.feng, a.hindborg, ojeda, alex.gaynor, gary, bjorn3_gh,
benno.lossin, aliceryhl, tmgross, dakr, frederic, lyude, tglx,
anna-maria, jstultz, sboyd
Replace the ClockId enum with a trait-based abstraction called
ClockSource. This change enables expressing clock sources as types and
leveraging the Rust type system to enforce clock correctness at
compile time.
This also sets the stage for future generic abstractions over Instant
types such as Instant<C>.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
rust/kernel/time.rs | 147 ++++++++++++++++++++----------------
rust/kernel/time/hrtimer.rs | 6 +-
2 files changed, 84 insertions(+), 69 deletions(-)
diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
index 8d6aa88724ad..64f36476d519 100644
--- a/rust/kernel/time.rs
+++ b/rust/kernel/time.rs
@@ -50,6 +50,87 @@ pub fn msecs_to_jiffies(msecs: Msecs) -> Jiffies {
unsafe { bindings::__msecs_to_jiffies(msecs) }
}
+/// Trait for clock sources.
+///
+/// Selection of the clock source depends on the use case. In some cases the usage of a
+/// particular clock is mandatory, e.g. in network protocols, filesystems. In other
+/// cases the user of the clock has to decide which clock is best suited for the
+/// purpose. In most scenarios clock [`Monotonic`] is the best choice as it
+/// provides a accurate monotonic notion of time (leap second smearing ignored).
+pub trait ClockSource {
+ /// The kernel clock ID associated with this clock source.
+ ///
+ /// This constant corresponds to the C side `clockid_t` value.
+ const ID: bindings::clockid_t;
+}
+
+/// A monotonically increasing clock.
+///
+/// A nonsettable system-wide clock that represents monotonic time since as
+/// described by POSIX, "some unspecified point in the past". On Linux, that
+/// point corresponds to the number of seconds that the system has been
+/// running since it was booted.
+///
+/// The CLOCK_MONOTONIC clock is not affected by discontinuous jumps in the
+/// CLOCK_REAL (e.g., if the system administrator manually changes the
+/// clock), but is affected by frequency adjustments. This clock does not
+/// count time that the system is suspended.
+pub struct Monotonic;
+
+impl ClockSource for Monotonic {
+ const ID: bindings::clockid_t = bindings::CLOCK_MONOTONIC as bindings::clockid_t;
+}
+
+/// A settable system-wide clock that measures real (i.e., wall-clock) time.
+///
+/// Setting this clock requires appropriate privileges. This clock is
+/// affected by discontinuous jumps in the system time (e.g., if the system
+/// administrator manually changes the clock), and by frequency adjustments
+/// performed by NTP and similar applications via adjtime(3), adjtimex(2),
+/// clock_adjtime(2), and ntp_adjtime(3). This clock normally counts the
+/// number of seconds since 1970-01-01 00:00:00 Coordinated Universal Time
+/// (UTC) except that it ignores leap seconds; near a leap second it may be
+/// adjusted by leap second smearing to stay roughly in sync with UTC. Leap
+/// second smearing applies frequency adjustments to the clock to speed up
+/// or slow down the clock to account for the leap second without
+/// discontinuities in the clock. If leap second smearing is not applied,
+/// the clock will experience discontinuity around leap second adjustment.
+pub struct RealTime;
+
+impl ClockSource for RealTime {
+ const ID: bindings::clockid_t = bindings::CLOCK_REALTIME as bindings::clockid_t;
+}
+
+/// A monotonic that ticks while system is suspended.
+///
+/// A nonsettable system-wide clock that is identical to CLOCK_MONOTONIC,
+/// except that it also includes any time that the system is suspended. This
+/// allows applications to get a suspend-aware monotonic clock without
+/// having to deal with the complications of CLOCK_REALTIME, which may have
+/// discontinuities if the time is changed using settimeofday(2) or similar.
+pub struct BootTime;
+
+impl ClockSource for BootTime {
+ const ID: bindings::clockid_t = bindings::CLOCK_BOOTTIME as bindings::clockid_t;
+}
+
+/// International Atomic Time.
+///
+/// A system-wide clock derived from wall-clock time but counting leap seconds.
+///
+/// This clock is coupled to CLOCK_REALTIME and will be set when CLOCK_REALTIME is
+/// set, or when the offset to CLOCK_REALTIME is changed via adjtimex(2). This
+/// usually happens during boot and **should** not happen during normal operations.
+/// However, if NTP or another application adjusts CLOCK_REALTIME by leap second
+/// smearing, this clock will not be precise during leap second smearing.
+///
+/// The acronym TAI refers to International Atomic Time.
+pub struct Tai;
+
+impl ClockSource for Tai {
+ const ID: bindings::clockid_t = bindings::CLOCK_TAI as bindings::clockid_t;
+}
+
/// A specific point in time.
///
/// # Invariants
@@ -97,72 +178,6 @@ fn sub(self, other: Instant) -> Delta {
}
}
-/// An identifier for a clock. Used when specifying clock sources.
-///
-///
-/// Selection of the clock depends on the use case. In some cases the usage of a
-/// particular clock is mandatory, e.g. in network protocols, filesystems.In other
-/// cases the user of the clock has to decide which clock is best suited for the
-/// purpose. In most scenarios clock [`ClockId::Monotonic`] is the best choice as it
-/// provides a accurate monotonic notion of time (leap second smearing ignored).
-#[derive(Clone, Copy, PartialEq, Eq, Debug)]
-#[repr(u32)]
-pub enum ClockId {
- /// A settable system-wide clock that measures real (i.e., wall-clock) time.
- ///
- /// Setting this clock requires appropriate privileges. This clock is
- /// affected by discontinuous jumps in the system time (e.g., if the system
- /// administrator manually changes the clock), and by frequency adjustments
- /// performed by NTP and similar applications via adjtime(3), adjtimex(2),
- /// clock_adjtime(2), and ntp_adjtime(3). This clock normally counts the
- /// number of seconds since 1970-01-01 00:00:00 Coordinated Universal Time
- /// (UTC) except that it ignores leap seconds; near a leap second it may be
- /// adjusted by leap second smearing to stay roughly in sync with UTC. Leap
- /// second smearing applies frequency adjustments to the clock to speed up
- /// or slow down the clock to account for the leap second without
- /// discontinuities in the clock. If leap second smearing is not applied,
- /// the clock will experience discontinuity around leap second adjustment.
- RealTime = bindings::CLOCK_REALTIME,
- /// A monotonically increasing clock.
- ///
- /// A nonsettable system-wide clock that represents monotonic time since—as
- /// described by POSIX—"some unspecified point in the past". On Linux, that
- /// point corresponds to the number of seconds that the system has been
- /// running since it was booted.
- ///
- /// The CLOCK_MONOTONIC clock is not affected by discontinuous jumps in the
- /// CLOCK_REAL (e.g., if the system administrator manually changes the
- /// clock), but is affected by frequency adjustments. This clock does not
- /// count time that the system is suspended.
- Monotonic = bindings::CLOCK_MONOTONIC,
- /// A monotonic that ticks while system is suspended.
- ///
- /// A nonsettable system-wide clock that is identical to CLOCK_MONOTONIC,
- /// except that it also includes any time that the system is suspended. This
- /// allows applications to get a suspend-aware monotonic clock without
- /// having to deal with the complications of CLOCK_REALTIME, which may have
- /// discontinuities if the time is changed using settimeofday(2) or similar.
- BootTime = bindings::CLOCK_BOOTTIME,
- /// International Atomic Time.
- ///
- /// A system-wide clock derived from wall-clock time but counting leap seconds.
- ///
- /// This clock is coupled to CLOCK_REALTIME and will be set when CLOCK_REALTIME is
- /// set, or when the offset to CLOCK_REALTIME is changed via adjtimex(2). This
- /// usually happens during boot and **should** not happen during normal operations.
- /// However, if NTP or another application adjusts CLOCK_REALTIME by leap second
- /// smearing, this clock will not be precise during leap second smearing.
- ///
- /// The acronym TAI refers to International Atomic Time.
- TAI = bindings::CLOCK_TAI,
-}
-
-impl ClockId {
- fn into_c(self) -> bindings::clockid_t {
- self as bindings::clockid_t
- }
-}
-
/// A span of time.
///
/// This struct represents a span of time, with its value stored as nanoseconds.
diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
index 27243eaaf8ed..12c359dbb895 100644
--- a/rust/kernel/time/hrtimer.rs
+++ b/rust/kernel/time/hrtimer.rs
@@ -67,7 +67,7 @@
//! A `restart` operation on a timer in the **stopped** state is equivalent to a
//! `start` operation.
-use super::ClockId;
+use super::ClockSource;
use crate::{prelude::*, time::Instant, types::Opaque};
use core::marker::PhantomData;
use pin_init::PinInit;
@@ -96,7 +96,7 @@ unsafe impl<T> Sync for HrTimer<T> {}
impl<T> HrTimer<T> {
/// Return an initializer for a new timer instance.
- pub fn new(mode: HrTimerMode, clock: ClockId) -> impl PinInit<Self>
+ pub fn new<U: ClockSource>(mode: HrTimerMode) -> impl PinInit<Self>
where
T: HrTimerCallback,
{
@@ -110,7 +110,7 @@ pub fn new(mode: HrTimerMode, clock: ClockId) -> impl PinInit<Self>
bindings::hrtimer_setup(
place,
Some(T::Pointer::run),
- clock.into_c(),
+ U::ID,
mode.into_c(),
);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v1 2/3] rust: time: make Instant generic over ClockSource
2025-04-13 10:56 [PATCH v1 0/3] rust: time: Introduce typed clock sources and generalize Instant FUJITA Tomonori
2025-04-13 10:56 ` [PATCH v1 1/3] rust: time: replace ClockId enum with ClockSource trait FUJITA Tomonori
@ 2025-04-13 10:56 ` FUJITA Tomonori
2025-04-22 13:11 ` Andreas Hindborg
2025-04-13 10:56 ` [PATCH v1 3/3] rust: time: add ktime_get() to ClockSource trait FUJITA Tomonori
2 siblings, 1 reply; 9+ messages in thread
From: FUJITA Tomonori @ 2025-04-13 10:56 UTC (permalink / raw)
To: rust-for-linux
Cc: boqun.feng, a.hindborg, ojeda, alex.gaynor, gary, bjorn3_gh,
benno.lossin, aliceryhl, tmgross, dakr, frederic, lyude, tglx,
anna-maria, jstultz, sboyd
Refactor the Instant type to be generic over a ClockSource type
parameter, enabling static enforcement of clock correctness across
APIs that deal with time. Previously, the clock source was implicitly
fixed (typically CLOCK_MONOTONIC), and developers had to ensure
compatibility manually.
This design eliminates runtime mismatches between clock sources, and
enables stronger type-level guarantees throughout the timer subsystem.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
rust/kernel/time.rs | 21 ++++++++++++++++-----
rust/kernel/time/hrtimer.rs | 20 ++++++++++----------
rust/kernel/time/hrtimer/arc.rs | 5 +++--
rust/kernel/time/hrtimer/pin.rs | 5 +++--
rust/kernel/time/hrtimer/pin_mut.rs | 7 ++++---
rust/kernel/time/hrtimer/tbox.rs | 5 +++--
6 files changed, 39 insertions(+), 24 deletions(-)
diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
index 64f36476d519..db9a783631ec 100644
--- a/rust/kernel/time.rs
+++ b/rust/kernel/time.rs
@@ -24,6 +24,7 @@
//! C header: [`include/linux/jiffies.h`](srctree/include/linux/jiffies.h).
//! C header: [`include/linux/ktime.h`](srctree/include/linux/ktime.h).
+use core::marker::PhantomData;
pub mod delay;
pub mod hrtimer;
@@ -137,12 +138,21 @@ impl ClockSource for Tai {
///
/// The `inner` value is in the range from 0 to `KTIME_MAX`.
#[repr(transparent)]
-#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord)]
-pub struct Instant {
+#[derive(PartialEq, PartialOrd, Eq, Ord)]
+pub struct Instant<C: ClockSource> {
inner: bindings::ktime_t,
+ _c: PhantomData<C>,
}
-impl Instant {
+impl<C: ClockSource> Clone for Instant<C> {
+ fn clone(&self) -> Self {
+ *self
+ }
+}
+
+impl<C: ClockSource> Copy for Instant<C> {}
+
+impl<C: ClockSource> Instant<C> {
/// Get the current time using `CLOCK_MONOTONIC`.
#[inline]
pub fn now() -> Self {
@@ -151,6 +161,7 @@ pub fn now() -> Self {
Self {
// SAFETY: It is always safe to call `ktime_get()` outside of NMI context.
inner: unsafe { bindings::ktime_get() },
+ _c: PhantomData,
}
}
@@ -166,12 +177,12 @@ pub(crate) fn as_nanos(self) -> i64 {
}
}
-impl core::ops::Sub for Instant {
+impl<C: ClockSource> core::ops::Sub for Instant<C> {
type Output = Delta;
// By the type invariant, it never overflows.
#[inline]
- fn sub(self, other: Instant) -> Delta {
+ fn sub(self, other: Instant<C>) -> Delta {
Delta {
nanos: self.inner - other.inner,
}
diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
index 12c359dbb895..b1e64e879836 100644
--- a/rust/kernel/time/hrtimer.rs
+++ b/rust/kernel/time/hrtimer.rs
@@ -176,7 +176,7 @@ pub(crate) unsafe fn raw_cancel(this: *const Self) -> bool {
/// that more than one [`HrTimerHandle`] associated with a [`HrTimerPointer`] may
/// exist. A timer can be manipulated through any of the handles, and a handle
/// may represent a cancelled timer.
-pub trait HrTimerPointer: Sync + Sized {
+pub trait HrTimerPointer<C: ClockSource>: Sync + Sized {
/// A handle representing a started or restarted timer.
///
/// If the timer is running or if the timer callback is executing when the
@@ -189,7 +189,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: Instant) -> Self::TimerHandle;
+ fn start(self, expires: Instant<C>) -> Self::TimerHandle;
}
/// Unsafe version of [`HrTimerPointer`] for situations where leaking the
@@ -203,7 +203,7 @@ pub trait HrTimerPointer: Sync + Sized {
/// Implementers of this trait must ensure that instances of types implementing
/// [`UnsafeHrTimerPointer`] outlives any associated [`HrTimerPointer::TimerHandle`]
/// instances.
-pub unsafe trait UnsafeHrTimerPointer: Sync + Sized {
+pub unsafe trait UnsafeHrTimerPointer<C: ClockSource>: Sync + Sized {
/// A handle representing a running timer.
///
/// # Safety
@@ -220,7 +220,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: Instant) -> Self::TimerHandle;
+ unsafe fn start(self, expires: Instant<C>) -> Self::TimerHandle;
}
/// A trait for stack allocated timers.
@@ -229,10 +229,10 @@ 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 {
+pub unsafe trait ScopedHrTimerPointer<C: ClockSource> {
/// 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: Instant, f: F) -> T
+ fn start_scoped<T, F>(self, expires: Instant<C>, f: F) -> T
where
F: FnOnce() -> T;
}
@@ -240,11 +240,11 @@ fn start_scoped<T, F>(self, expires: Instant, f: F) -> T
// SAFETY: By the safety requirement of [`UnsafeHrTimerPointer`], dropping the
// handle returned by [`UnsafeHrTimerPointer::start`] ensures that the timer is
// killed.
-unsafe impl<T> ScopedHrTimerPointer for T
+unsafe impl<T, C: ClockSource> ScopedHrTimerPointer<C> for T
where
- T: UnsafeHrTimerPointer,
+ T: UnsafeHrTimerPointer<C>,
{
- fn start_scoped<U, F>(self, expires: Instant, f: F) -> U
+ fn start_scoped<U, F>(self, expires: Instant<C>, f: F) -> U
where
F: FnOnce() -> U,
{
@@ -366,7 +366,7 @@ 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: Instant) {
+ unsafe fn start<C: ClockSource>(this: *const Self, expires: Instant<C>) {
// SAFETY: By function safety requirement, `this` is a valid `Self`.
unsafe {
bindings::hrtimer_start_range_ns(
diff --git a/rust/kernel/time/hrtimer/arc.rs b/rust/kernel/time/hrtimer/arc.rs
index acc70a0ea1be..455c4dba6226 100644
--- a/rust/kernel/time/hrtimer/arc.rs
+++ b/rust/kernel/time/hrtimer/arc.rs
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
+use super::ClockSource;
use super::HasHrTimer;
use super::HrTimer;
use super::HrTimerCallback;
@@ -47,7 +48,7 @@ fn drop(&mut self) {
}
}
-impl<T> HrTimerPointer for Arc<T>
+impl<T, C: ClockSource> HrTimerPointer<C> for Arc<T>
where
T: 'static,
T: Send + Sync,
@@ -56,7 +57,7 @@ impl<T> HrTimerPointer for Arc<T>
{
type TimerHandle = ArcHrTimerHandle<T>;
- fn start(self, expires: Instant) -> ArcHrTimerHandle<T> {
+ fn start(self, expires: Instant<C>) -> ArcHrTimerHandle<T> {
// SAFETY:
// - We keep `self` alive by wrapping it in a handle below.
// - Since we generate the pointer passed to `start` from a valid
diff --git a/rust/kernel/time/hrtimer/pin.rs b/rust/kernel/time/hrtimer/pin.rs
index dba22d11a95f..179887c4b3c8 100644
--- a/rust/kernel/time/hrtimer/pin.rs
+++ b/rust/kernel/time/hrtimer/pin.rs
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
+use super::ClockSource;
use super::HasHrTimer;
use super::HrTimer;
use super::HrTimerCallback;
@@ -48,7 +49,7 @@ fn drop(&mut self) {
// SAFETY: We capture the lifetime of `Self` when we create a `PinHrTimerHandle`,
// so `Self` will outlive the handle.
-unsafe impl<'a, T> UnsafeHrTimerPointer for Pin<&'a T>
+unsafe impl<'a, T, C: ClockSource> UnsafeHrTimerPointer<C> for Pin<&'a T>
where
T: Send + Sync,
T: HasHrTimer<T>,
@@ -56,7 +57,7 @@ unsafe impl<'a, T> UnsafeHrTimerPointer for Pin<&'a T>
{
type TimerHandle = PinHrTimerHandle<'a, T>;
- unsafe fn start(self, expires: Instant) -> Self::TimerHandle {
+ unsafe fn start(self, expires: Instant<C>) -> Self::TimerHandle {
// Cast to pointer
let self_ptr: *const T = self.get_ref();
diff --git a/rust/kernel/time/hrtimer/pin_mut.rs b/rust/kernel/time/hrtimer/pin_mut.rs
index aeff8e102e1d..ead56fe4a7d7 100644
--- a/rust/kernel/time/hrtimer/pin_mut.rs
+++ b/rust/kernel/time/hrtimer/pin_mut.rs
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
use super::{
- HasHrTimer, HrTimer, HrTimerCallback, HrTimerHandle, RawHrTimerCallback, UnsafeHrTimerPointer,
+ ClockSource, HasHrTimer, HrTimer, HrTimerCallback, HrTimerHandle, RawHrTimerCallback,
+ UnsafeHrTimerPointer,
};
use crate::time::Instant;
use core::{marker::PhantomData, pin::Pin, ptr::NonNull};
@@ -46,7 +47,7 @@ fn drop(&mut self) {
// SAFETY: We capture the lifetime of `Self` when we create a
// `PinMutHrTimerHandle`, so `Self` will outlive the handle.
-unsafe impl<'a, T> UnsafeHrTimerPointer for Pin<&'a mut T>
+unsafe impl<'a, T, C: ClockSource> UnsafeHrTimerPointer<C> for Pin<&'a mut T>
where
T: Send + Sync,
T: HasHrTimer<T>,
@@ -54,7 +55,7 @@ unsafe impl<'a, T> UnsafeHrTimerPointer for Pin<&'a mut T>
{
type TimerHandle = PinMutHrTimerHandle<'a, T>;
- unsafe fn start(mut self, expires: Instant) -> Self::TimerHandle {
+ unsafe fn start(mut self, expires: Instant<C>) -> Self::TimerHandle {
// SAFETY:
// - We promise not to move out of `self`. We only pass `self`
// back to the caller as a `Pin<&mut self>`.
diff --git a/rust/kernel/time/hrtimer/tbox.rs b/rust/kernel/time/hrtimer/tbox.rs
index 3df4e359e9bb..4212756c7494 100644
--- a/rust/kernel/time/hrtimer/tbox.rs
+++ b/rust/kernel/time/hrtimer/tbox.rs
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
+use super::ClockSource;
use super::HasHrTimer;
use super::HrTimer;
use super::HrTimerCallback;
@@ -56,7 +57,7 @@ fn drop(&mut self) {
}
}
-impl<T, A> HrTimerPointer for Pin<Box<T, A>>
+impl<T, A, C: ClockSource> HrTimerPointer<C> for Pin<Box<T, A>>
where
T: 'static,
T: Send + Sync,
@@ -66,7 +67,7 @@ impl<T, A> HrTimerPointer for Pin<Box<T, A>>
{
type TimerHandle = BoxHrTimerHandle<T, A>;
- fn start(self, expires: Instant) -> Self::TimerHandle {
+ fn start(self, expires: Instant<C>) -> Self::TimerHandle {
// SAFETY:
// - We will not move out of this box during timer callback (we pass an
// immutable reference to the callback).
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v1 3/3] rust: time: add ktime_get() to ClockSource trait
2025-04-13 10:56 [PATCH v1 0/3] rust: time: Introduce typed clock sources and generalize Instant FUJITA Tomonori
2025-04-13 10:56 ` [PATCH v1 1/3] rust: time: replace ClockId enum with ClockSource trait FUJITA Tomonori
2025-04-13 10:56 ` [PATCH v1 2/3] rust: time: make Instant generic over ClockSource FUJITA Tomonori
@ 2025-04-13 10:56 ` FUJITA Tomonori
2025-04-22 13:14 ` Andreas Hindborg
2 siblings, 1 reply; 9+ messages in thread
From: FUJITA Tomonori @ 2025-04-13 10:56 UTC (permalink / raw)
To: rust-for-linux
Cc: boqun.feng, a.hindborg, ojeda, alex.gaynor, gary, bjorn3_gh,
benno.lossin, aliceryhl, tmgross, dakr, frederic, lyude, tglx,
anna-maria, jstultz, sboyd
Introduce the ktime_get() associated function to the ClockSource
trait, allowing each clock source to specify how it retrieves the
current time. This enables Instant::now() to be implemented
generically using the type-level ClockSource abstraction.
This change enhances the type safety and extensibility of timekeeping
by statically associating time retrieval mechanisms with their
respective clock types. It also reduces the reliance on hardcoded
clock logic within Instant.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
---
rust/helpers/time.c | 16 ++++++++++++++++
rust/kernel/time.rs | 32 ++++++++++++++++++++++++++++----
2 files changed, 44 insertions(+), 4 deletions(-)
diff --git a/rust/helpers/time.c b/rust/helpers/time.c
index 7ae64ad8141d..613475c529d4 100644
--- a/rust/helpers/time.c
+++ b/rust/helpers/time.c
@@ -1,8 +1,24 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/delay.h>
+#include <linux/timekeeping.h>
void rust_helper_fsleep(unsigned long usecs)
{
fsleep(usecs);
}
+
+ktime_t rust_helper_ktime_get_real(void)
+{
+ return ktime_get_with_offset(TK_OFFS_REAL);
+}
+
+ktime_t rust_helper_ktime_get_boottime(void)
+{
+ return ktime_get_with_offset(TK_OFFS_BOOT);
+}
+
+ktime_t rust_helper_ktime_get_clocktai(void)
+{
+ return ktime_get_with_offset(TK_OFFS_TAI);
+}
diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
index db9a783631ec..4b9b61eed628 100644
--- a/rust/kernel/time.rs
+++ b/rust/kernel/time.rs
@@ -63,6 +63,11 @@ pub trait ClockSource {
///
/// This constant corresponds to the C side `clockid_t` value.
const ID: bindings::clockid_t;
+
+ /// Get the current time fro the clock source.
+ ///
+ /// The function must return a value in the range from 0 to `KTIME_MAX`.
+ fn ktime_get() -> bindings::ktime_t;
}
/// A monotonically increasing clock.
@@ -80,6 +85,11 @@ pub trait ClockSource {
impl ClockSource for Monotonic {
const ID: bindings::clockid_t = bindings::CLOCK_MONOTONIC as bindings::clockid_t;
+
+ fn ktime_get() -> bindings::ktime_t {
+ // SAFETY: It is always safe to call `ktime_get()` outside of NMI context.
+ unsafe { bindings::ktime_get() }
+ }
}
/// A settable system-wide clock that measures real (i.e., wall-clock) time.
@@ -100,6 +110,11 @@ impl ClockSource for Monotonic {
impl ClockSource for RealTime {
const ID: bindings::clockid_t = bindings::CLOCK_REALTIME as bindings::clockid_t;
+
+ fn ktime_get() -> bindings::ktime_t {
+ // SAFETY: It is always safe to call `ktime_get_real()` outside of NMI context.
+ unsafe { bindings::ktime_get_real() }
+ }
}
/// A monotonic that ticks while system is suspended.
@@ -113,6 +128,11 @@ impl ClockSource for RealTime {
impl ClockSource for BootTime {
const ID: bindings::clockid_t = bindings::CLOCK_BOOTTIME as bindings::clockid_t;
+
+ fn ktime_get() -> bindings::ktime_t {
+ // SAFETY: It is always safe to call `ktime_get_boottime()` outside of NMI context.
+ unsafe { bindings::ktime_get_boottime() }
+ }
}
/// International Atomic Time.
@@ -130,6 +150,11 @@ impl ClockSource for BootTime {
impl ClockSource for Tai {
const ID: bindings::clockid_t = bindings::CLOCK_TAI as bindings::clockid_t;
+
+ fn ktime_get() -> bindings::ktime_t {
+ // SAFETY: It is always safe to call `ktime_get_tai()` outside of NMI context.
+ unsafe { bindings::ktime_get_clocktai() }
+ }
}
/// A specific point in time.
@@ -153,14 +178,13 @@ fn clone(&self) -> Self {
impl<C: ClockSource> Copy for Instant<C> {}
impl<C: ClockSource> Instant<C> {
- /// Get the current time using `CLOCK_MONOTONIC`.
+ /// Get the current time from the clock source.
#[inline]
pub fn now() -> Self {
- // INVARIANT: The `ktime_get()` function returns a value in the range
+ // INVARIANT: The `ClockSource::ktime_get()` function returns a value in the range
// from 0 to `KTIME_MAX`.
Self {
- // SAFETY: It is always safe to call `ktime_get()` outside of NMI context.
- inner: unsafe { bindings::ktime_get() },
+ inner: C::ktime_get(),
_c: PhantomData,
}
}
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v1 1/3] rust: time: replace ClockId enum with ClockSource trait
2025-04-13 10:56 ` [PATCH v1 1/3] rust: time: replace ClockId enum with ClockSource trait FUJITA Tomonori
@ 2025-04-22 12:51 ` Andreas Hindborg
0 siblings, 0 replies; 9+ messages in thread
From: Andreas Hindborg @ 2025-04-22 12:51 UTC (permalink / raw)
To: FUJITA Tomonori
Cc: rust-for-linux, boqun.feng, ojeda, alex.gaynor, gary, bjorn3_gh,
benno.lossin, aliceryhl, tmgross, dakr, frederic, lyude, tglx,
anna-maria, jstultz, sboyd
"FUJITA Tomonori" <fujita.tomonori@gmail.com> writes:
> Replace the ClockId enum with a trait-based abstraction called
> ClockSource. This change enables expressing clock sources as types and
> leveraging the Rust type system to enforce clock correctness at
> compile time.
>
> This also sets the stage for future generic abstractions over Instant
> types such as Instant<C>.
>
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Best regards,
Andreas Hindborg
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 2/3] rust: time: make Instant generic over ClockSource
2025-04-13 10:56 ` [PATCH v1 2/3] rust: time: make Instant generic over ClockSource FUJITA Tomonori
@ 2025-04-22 13:11 ` Andreas Hindborg
2025-04-22 22:12 ` FUJITA Tomonori
0 siblings, 1 reply; 9+ messages in thread
From: Andreas Hindborg @ 2025-04-22 13:11 UTC (permalink / raw)
To: FUJITA Tomonori
Cc: rust-for-linux, boqun.feng, ojeda, alex.gaynor, gary, bjorn3_gh,
benno.lossin, aliceryhl, tmgross, dakr, frederic, lyude, tglx,
anna-maria, jstultz, sboyd
"FUJITA Tomonori" <fujita.tomonori@gmail.com> writes:
> Refactor the Instant type to be generic over a ClockSource type
> parameter, enabling static enforcement of clock correctness across
> APIs that deal with time. Previously, the clock source was implicitly
> fixed (typically CLOCK_MONOTONIC), and developers had to ensure
> compatibility manually.
>
> This design eliminates runtime mismatches between clock sources, and
> enables stronger type-level guarantees throughout the timer subsystem.
>
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
I think this patch will allow creating an `HrTimer` with one
`CockSource` and starting it with an instant that uses another
`ClockSource`. There is nothing tying the generic `U` in `HrTimer::new`
to the generic `C` in `HrTimerPointer`, right?
Best regards,
Andreas Hindborg
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 3/3] rust: time: add ktime_get() to ClockSource trait
2025-04-13 10:56 ` [PATCH v1 3/3] rust: time: add ktime_get() to ClockSource trait FUJITA Tomonori
@ 2025-04-22 13:14 ` Andreas Hindborg
2025-04-22 22:47 ` FUJITA Tomonori
0 siblings, 1 reply; 9+ messages in thread
From: Andreas Hindborg @ 2025-04-22 13:14 UTC (permalink / raw)
To: FUJITA Tomonori
Cc: rust-for-linux, boqun.feng, ojeda, alex.gaynor, gary, bjorn3_gh,
benno.lossin, aliceryhl, tmgross, dakr, frederic, lyude, tglx,
anna-maria, jstultz, sboyd
"FUJITA Tomonori" <fujita.tomonori@gmail.com> writes:
> Introduce the ktime_get() associated function to the ClockSource
> trait, allowing each clock source to specify how it retrieves the
> current time. This enables Instant::now() to be implemented
> generically using the type-level ClockSource abstraction.
>
> This change enhances the type safety and extensibility of timekeeping
> by statically associating time retrieval mechanisms with their
> respective clock types. It also reduces the reliance on hardcoded
> clock logic within Instant.
>
> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
> ---
> rust/helpers/time.c | 16 ++++++++++++++++
> rust/kernel/time.rs | 32 ++++++++++++++++++++++++++++----
> 2 files changed, 44 insertions(+), 4 deletions(-)
>
> diff --git a/rust/helpers/time.c b/rust/helpers/time.c
> index 7ae64ad8141d..613475c529d4 100644
> --- a/rust/helpers/time.c
> +++ b/rust/helpers/time.c
> @@ -1,8 +1,24 @@
> // SPDX-License-Identifier: GPL-2.0
>
> #include <linux/delay.h>
> +#include <linux/timekeeping.h>
>
> void rust_helper_fsleep(unsigned long usecs)
> {
> fsleep(usecs);
> }
> +
> +ktime_t rust_helper_ktime_get_real(void)
> +{
> + return ktime_get_with_offset(TK_OFFS_REAL);
> +}
> +
> +ktime_t rust_helper_ktime_get_boottime(void)
> +{
> + return ktime_get_with_offset(TK_OFFS_BOOT);
> +}
> +
> +ktime_t rust_helper_ktime_get_clocktai(void)
> +{
> + return ktime_get_with_offset(TK_OFFS_TAI);
> +}
> diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
> index db9a783631ec..4b9b61eed628 100644
> --- a/rust/kernel/time.rs
> +++ b/rust/kernel/time.rs
> @@ -63,6 +63,11 @@ pub trait ClockSource {
> ///
> /// This constant corresponds to the C side `clockid_t` value.
> const ID: bindings::clockid_t;
> +
> + /// Get the current time fro the clock source.
Typo fro -> from.
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Best regards,
Andreas Hindborg
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 2/3] rust: time: make Instant generic over ClockSource
2025-04-22 13:11 ` Andreas Hindborg
@ 2025-04-22 22:12 ` FUJITA Tomonori
0 siblings, 0 replies; 9+ messages in thread
From: FUJITA Tomonori @ 2025-04-22 22:12 UTC (permalink / raw)
To: a.hindborg
Cc: fujita.tomonori, rust-for-linux, boqun.feng, ojeda, alex.gaynor,
gary, bjorn3_gh, benno.lossin, aliceryhl, tmgross, dakr, frederic,
lyude, tglx, anna-maria, jstultz, sboyd
On Tue, 22 Apr 2025 15:11:29 +0200
Andreas Hindborg <a.hindborg@kernel.org> wrote:
> "FUJITA Tomonori" <fujita.tomonori@gmail.com> writes:
>
>> Refactor the Instant type to be generic over a ClockSource type
>> parameter, enabling static enforcement of clock correctness across
>> APIs that deal with time. Previously, the clock source was implicitly
>> fixed (typically CLOCK_MONOTONIC), and developers had to ensure
>> compatibility manually.
>>
>> This design eliminates runtime mismatches between clock sources, and
>> enables stronger type-level guarantees throughout the timer subsystem.
>>
>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
>
> I think this patch will allow creating an `HrTimer` with one
> `CockSource` and starting it with an instant that uses another
> `ClockSource`. There is nothing tying the generic `U` in `HrTimer::new`
> to the generic `C` in `HrTimerPointer`, right?
Right. My plan was to make HrTimer generic over a ClockSource when
refactoring HrTimer to use Instance and Delta types.
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v1 3/3] rust: time: add ktime_get() to ClockSource trait
2025-04-22 13:14 ` Andreas Hindborg
@ 2025-04-22 22:47 ` FUJITA Tomonori
0 siblings, 0 replies; 9+ messages in thread
From: FUJITA Tomonori @ 2025-04-22 22:47 UTC (permalink / raw)
To: a.hindborg
Cc: fujita.tomonori, rust-for-linux, boqun.feng, ojeda, alex.gaynor,
gary, bjorn3_gh, benno.lossin, aliceryhl, tmgross, dakr, frederic,
lyude, tglx, anna-maria, jstultz, sboyd
On Tue, 22 Apr 2025 15:14:46 +0200
Andreas Hindborg <a.hindborg@kernel.org> wrote:
> "FUJITA Tomonori" <fujita.tomonori@gmail.com> writes:
>
>> Introduce the ktime_get() associated function to the ClockSource
>> trait, allowing each clock source to specify how it retrieves the
>> current time. This enables Instant::now() to be implemented
>> generically using the type-level ClockSource abstraction.
>>
>> This change enhances the type safety and extensibility of timekeeping
>> by statically associating time retrieval mechanisms with their
>> respective clock types. It also reduces the reliance on hardcoded
>> clock logic within Instant.
>>
>> Signed-off-by: FUJITA Tomonori <fujita.tomonori@gmail.com>
>> ---
>> rust/helpers/time.c | 16 ++++++++++++++++
>> rust/kernel/time.rs | 32 ++++++++++++++++++++++++++++----
>> 2 files changed, 44 insertions(+), 4 deletions(-)
>>
>> diff --git a/rust/helpers/time.c b/rust/helpers/time.c
>> index 7ae64ad8141d..613475c529d4 100644
>> --- a/rust/helpers/time.c
>> +++ b/rust/helpers/time.c
>> @@ -1,8 +1,24 @@
>> // SPDX-License-Identifier: GPL-2.0
>>
>> #include <linux/delay.h>
>> +#include <linux/timekeeping.h>
>>
>> void rust_helper_fsleep(unsigned long usecs)
>> {
>> fsleep(usecs);
>> }
>> +
>> +ktime_t rust_helper_ktime_get_real(void)
>> +{
>> + return ktime_get_with_offset(TK_OFFS_REAL);
>> +}
>> +
>> +ktime_t rust_helper_ktime_get_boottime(void)
>> +{
>> + return ktime_get_with_offset(TK_OFFS_BOOT);
>> +}
>> +
>> +ktime_t rust_helper_ktime_get_clocktai(void)
>> +{
>> + return ktime_get_with_offset(TK_OFFS_TAI);
>> +}
>> diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs
>> index db9a783631ec..4b9b61eed628 100644
>> --- a/rust/kernel/time.rs
>> +++ b/rust/kernel/time.rs
>> @@ -63,6 +63,11 @@ pub trait ClockSource {
>> ///
>> /// This constant corresponds to the C side `clockid_t` value.
>> const ID: bindings::clockid_t;
>> +
>> + /// Get the current time fro the clock source.
>
> Typo fro -> from.
Oops, fixed.
>
> Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Thanks!
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-04-22 22:47 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-13 10:56 [PATCH v1 0/3] rust: time: Introduce typed clock sources and generalize Instant FUJITA Tomonori
2025-04-13 10:56 ` [PATCH v1 1/3] rust: time: replace ClockId enum with ClockSource trait FUJITA Tomonori
2025-04-22 12:51 ` Andreas Hindborg
2025-04-13 10:56 ` [PATCH v1 2/3] rust: time: make Instant generic over ClockSource FUJITA Tomonori
2025-04-22 13:11 ` Andreas Hindborg
2025-04-22 22:12 ` FUJITA Tomonori
2025-04-13 10:56 ` [PATCH v1 3/3] rust: time: add ktime_get() to ClockSource trait FUJITA Tomonori
2025-04-22 13:14 ` Andreas Hindborg
2025-04-22 22:47 ` FUJITA Tomonori
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).