diff options
| author | Miguel Ojeda <ojeda@kernel.org> | 2026-10-11 18:57:10 +0200 |
|---|---|---|
| committer | Miguel Ojeda <ojeda@kernel.org> | 2026-10-11 19:23:24 +0200 |
| commit | 0d6d7ab3d4f42b840dfa6057b9c7026d2b8018f8 (patch) | |
| tree | aa1a1ecd332a4e3fceffbeeb60b9425123644434 /rust | |
| parent | 334238e68398bd4e1e84a0b2931a71129100ef6a (diff) | |
| parent | 2ea0119f72dba597aa8a98cbdb72c564bfc5cb38 (diff) | |
Merge tag 'rust-timekeeping-for-v7.4-rc1' of https://github.com/Rust-for-Linux/linux into rust-next
Pull timekeeping updates from Andreas Hindborg:
- Warn and assert when passing out-of-range inputs to 'fsleep' and
'udelay'.
- Rename 'ClockSource' to 'ClockId' to better align with naming
conventions in C kernel.
- Make 'CONFIG_HZ' value available as 'bindings::HZ'.
- Add a conversion method to convert 'Delta' to 'jiffies' for use in
timeout arguments.
- Add implementation detail documentation for 'HrTimer'.
* tag 'rust-timekeeping-for-v7.4-rc1' of https://github.com/Rust-for-Linux/linux:
rust: hrtimer: document handle based design rationale
rust: time: add Delta::to_jiffies_timeout() for timeout conversion
rust: bindings: set HZ to CONFIG_HZ
rust: time: rename ClockSource trait to ClockId
rust: time: warn and assert out-of-range input in fsleep() and udelay()
Diffstat (limited to 'rust')
| -rw-r--r-- | rust/bindings/lib.rs | 5 | ||||
| -rw-r--r-- | rust/helpers/helpers.c | 1 | ||||
| -rw-r--r-- | rust/helpers/math.c | 8 | ||||
| -rw-r--r-- | rust/kernel/Kconfig.test | 10 | ||||
| -rw-r--r-- | rust/kernel/time.rs | 139 | ||||
| -rw-r--r-- | rust/kernel/time/delay.rs | 17 | ||||
| -rw-r--r-- | rust/kernel/time/hrtimer.rs | 95 |
7 files changed, 211 insertions, 64 deletions
diff --git a/rust/bindings/lib.rs b/rust/bindings/lib.rs index 439ab88a5da1..98313fc31024 100644 --- a/rust/bindings/lib.rs +++ b/rust/bindings/lib.rs @@ -83,3 +83,8 @@ pub const compat_ptr_ioctl: Option< None } }; + +// `bindgen` keeps the first definition of a macro and ignores a later `#undef`. +// The generated `HZ` is therefore `__USER_HZ` from +// `include/uapi/asm-generic/param.h`, not `CONFIG_HZ`. +pub const HZ: u32 = CONFIG_HZ; diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c index 440fb7638e3c..08374b163774 100644 --- a/rust/helpers/helpers.c +++ b/rust/helpers/helpers.c @@ -73,6 +73,7 @@ #include "kunit.c" #include "list.c" #include "maple_tree.c" +#include "math.c" #include "mm.c" #include "mutex.c" #include "net/genetlink.c" diff --git a/rust/helpers/math.c b/rust/helpers/math.c new file mode 100644 index 000000000000..e2ee29bcce0f --- /dev/null +++ b/rust/helpers/math.c @@ -0,0 +1,8 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <linux/math64.h> + +__rust_helper u64 rust_helper_mul_u64_add_u64_div_u64(u64 a, u64 b, u64 c, u64 d) +{ + return mul_u64_add_u64_div_u64(a, b, c, d); +} diff --git a/rust/kernel/Kconfig.test b/rust/kernel/Kconfig.test index 966b07872ba1..3bf4194f28c7 100644 --- a/rust/kernel/Kconfig.test +++ b/rust/kernel/Kconfig.test @@ -94,4 +94,14 @@ config RUST_BUG_KUNIT_TEST If unsure, say N. +config RUST_TIME_KUNIT_TEST + bool "KUnit tests for the Rust time API" if !KUNIT_ALL_TESTS + default KUNIT_ALL_TESTS + help + This option enables KUnit tests for the Rust time API. + These are only for development and testing, not for regular + kernel use cases. + + If unsure, say N. + endif diff --git a/rust/kernel/time.rs b/rust/kernel/time.rs index 6c0a5e8090d0..5ae377e70dd8 100644 --- a/rust/kernel/time.rs +++ b/rust/kernel/time.rs @@ -39,6 +39,10 @@ pub const NSEC_PER_MSEC: i64 = bindings::NSEC_PER_MSEC as i64; /// The number of nanoseconds per second. pub const NSEC_PER_SEC: i64 = bindings::NSEC_PER_SEC as i64; +/// The C side `MAX_JIFFY_OFFSET`, i.e. `((LONG_MAX >> 1) - 1)`. It is the upper +/// bound the kernel uses for a jiffies span, not a wait-forever value. +const MAX_JIFFY_OFFSET: isize = (isize::MAX >> 1) - 1; + /// The time unit of Linux kernel. One jiffy equals (1/HZ) second. pub type Jiffies = crate::ffi::c_ulong; @@ -53,9 +57,9 @@ pub fn msecs_to_jiffies(msecs: Msecs) -> Jiffies { unsafe { bindings::__msecs_to_jiffies(msecs) } } -/// Trait for clock sources. +/// Trait for kernel clock identifiers. /// -/// Selection of the clock source depends on the use case. In some cases the usage of a +/// 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 [`Monotonic`] is the best choice as it @@ -66,13 +70,13 @@ pub fn msecs_to_jiffies(msecs: Msecs) -> Jiffies { /// Implementers must ensure that `ktime_get()` returns a value in the inclusive range /// `0..=KTIME_MAX` (i.e., greater than or equal to 0 and less than or equal to /// `KTIME_MAX`, where `KTIME_MAX` equals `i64::MAX`). -pub unsafe trait ClockSource { - /// The kernel clock ID associated with this clock source. +pub unsafe trait ClockId { + /// The kernel clock ID associated with this clock. /// /// This constant corresponds to the C side `clockid_t` value. const ID: bindings::clockid_t; - /// Get the current time from the clock source. + /// Get the current time from the clock. /// /// The function must return a value in the range `0..=KTIME_MAX`. fn ktime_get() -> bindings::ktime_t; @@ -93,7 +97,7 @@ pub struct Monotonic; // SAFETY: The kernel's `ktime_get()` is guaranteed to return a value // in `0..=KTIME_MAX`. -unsafe impl ClockSource for Monotonic { +unsafe impl ClockId for Monotonic { const ID: bindings::clockid_t = bindings::CLOCK_MONOTONIC as bindings::clockid_t; fn ktime_get() -> bindings::ktime_t { @@ -120,7 +124,7 @@ pub struct RealTime; // SAFETY: The kernel's `ktime_get_real()` is guaranteed to return a value // in `0..=KTIME_MAX`. -unsafe impl ClockSource for RealTime { +unsafe impl ClockId for RealTime { const ID: bindings::clockid_t = bindings::CLOCK_REALTIME as bindings::clockid_t; fn ktime_get() -> bindings::ktime_t { @@ -140,7 +144,7 @@ pub struct BootTime; // SAFETY: The kernel's `ktime_get_boottime()` is guaranteed to return a value // in `0..=KTIME_MAX`. -unsafe impl ClockSource for BootTime { +unsafe impl ClockId for BootTime { const ID: bindings::clockid_t = bindings::CLOCK_BOOTTIME as bindings::clockid_t; fn ktime_get() -> bindings::ktime_t { @@ -164,7 +168,7 @@ pub struct Tai; // SAFETY: The kernel's `ktime_get_clocktai()` is guaranteed to return a value // in `0..=KTIME_MAX`. -unsafe impl ClockSource for Tai { +unsafe impl ClockId for Tai { const ID: bindings::clockid_t = bindings::CLOCK_TAI as bindings::clockid_t; fn ktime_get() -> bindings::ktime_t { @@ -180,24 +184,24 @@ unsafe impl ClockSource for Tai { /// The `inner` value is in the range from 0 to `KTIME_MAX`. #[repr(transparent)] #[derive(PartialEq, PartialOrd, Eq, Ord)] -pub struct Instant<C: ClockSource> { +pub struct Instant<C: ClockId> { inner: bindings::ktime_t, _c: PhantomData<C>, } -impl<C: ClockSource> Clone for Instant<C> { +impl<C: ClockId> Clone for Instant<C> { fn clone(&self) -> Self { *self } } -impl<C: ClockSource> Copy for Instant<C> {} +impl<C: ClockId> Copy for Instant<C> {} -impl<C: ClockSource> Instant<C> { +impl<C: ClockId> Instant<C> { /// Get the current time from the clock source. #[inline] pub fn now() -> Self { - // INVARIANT: The `ClockSource::ktime_get()` function returns a value in the range + // INVARIANT: The `ClockId::ktime_get()` function returns a value in the range // from 0 to `KTIME_MAX`. Self { inner: C::ktime_get(), @@ -239,7 +243,7 @@ impl<C: ClockSource> Instant<C> { } } -impl<C: ClockSource> ops::Sub for Instant<C> { +impl<C: ClockId> ops::Sub for Instant<C> { type Output = Delta; // By the type invariant, it never overflows. @@ -251,7 +255,7 @@ impl<C: ClockSource> ops::Sub for Instant<C> { } } -impl<T: ClockSource> ops::Add<Delta> for Instant<T> { +impl<T: ClockId> ops::Add<Delta> for Instant<T> { type Output = Self; #[inline] @@ -271,7 +275,7 @@ impl<T: ClockSource> ops::Add<Delta> for Instant<T> { } } -impl<T: ClockSource> ops::Sub<Delta> for Instant<T> { +impl<T: ClockId> ops::Sub<Delta> for Instant<T> { type Output = Self; #[inline] @@ -554,6 +558,62 @@ impl Delta { } } + /// Convert this span to a [`Delta<Jiffy>`] suitable for use as a timeout. + /// + /// Unless the result saturates, the value is rounded up to the next whole + /// jiffy, so the resulting timeout is never shorter than `self`. + /// + /// A negative span saturates at zero jiffies, i.e. an immediate timeout. + /// + /// A span that does not fit saturates at the kernel's [`MAX_JIFFY_OFFSET`], + /// the upper bound for a jiffies span. That is a finite timeout, so a + /// saturated result can be shorter than the requested span. It is derived + /// from `long`, so only 32 bit can reach it, at about 12 days with `HZ=1000`. + /// + /// # Examples + /// + /// ``` + /// use kernel::time::Delta; + /// + /// // A negative span is an immediate timeout. + /// assert_eq!(Delta::from_millis(-1).to_jiffies_timeout().as_jiffies(), 0); + /// + /// // A span shorter than a jiffy still waits, i.e. the timeout is never + /// // shorter than the span. + /// assert!(Delta::from_nanos(1).to_jiffies_timeout().as_jiffies() >= 1); + /// ``` + /// + /// [`MAX_JIFFY_OFFSET`]: srctree/include/linux/jiffies.h + #[inline] + pub fn to_jiffies_timeout(self) -> Delta<Jiffy> { + const HZ: u64 = bindings::HZ as u64; + + // The quotient `(nsecs * HZ + NSEC_PER_SEC - 1) / NSEC_PER_SEC` has to fit in + // `u64`; `nsecs * HZ` does not. With `HZ <= NSEC_PER_SEC` the numerator is at + // most `(nsecs + 1) * NSEC_PER_SEC - 1`, so the quotient is at most `nsecs`. + crate::static_assert!(HZ <= NSEC_PER_SEC as u64); + + // CAST: `i64::max()` makes the value non-negative, so the cast keeps it. + let nsecs = i64::max(self.as_nanos(), 0) as u64; + + // SAFETY: `mul_u64_add_u64_div_u64()` must not be called with a zero divisor, + // and its result must fit in `u64`. `NSEC_PER_SEC` is a non-zero constant, and + // the assertion above bounds the quotient by `nsecs`. + let jiffies = unsafe { + bindings::mul_u64_add_u64_div_u64( + nsecs, + HZ, + (NSEC_PER_SEC - 1) as u64, + NSEC_PER_SEC as u64, + ) + }; + + // CAST: `jiffies` is clamped to `MAX_JIFFY_OFFSET`, which is `<= isize::MAX`. + let jiffies = u64::min(jiffies, MAX_JIFFY_OFFSET as u64) as isize; + + Delta::<Jiffy>::from_jiffies(jiffies) + } + /// 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 @@ -580,3 +640,48 @@ impl Delta { } } } + +#[cfg(CONFIG_RUST_TIME_KUNIT_TEST)] +#[macros::kunit_tests(rust_kernel_time)] +mod tests { + use super::*; + + #[test] + fn to_jiffies_timeout_converts() { + const HZ: isize = bindings::HZ as isize; + + // One second is exactly `HZ` jiffies, and the round-up must not add one. + assert_eq!(Delta::from_secs(1).to_jiffies_timeout().as_jiffies(), HZ); + + // One nanosecond more has to round up to the next whole jiffy. + assert_eq!( + Delta::from_nanos(NSEC_PER_SEC + 1) + .to_jiffies_timeout() + .as_jiffies(), + HZ + 1 + ); + } + + #[test] + fn to_jiffies_timeout_saturates() { + // The result never exceeds `MAX_JIFFY_OFFSET`. On 32 bit with `HZ=1000` this + // span is 2147483647 jiffies, so the clamp is what keeps it in range; on 64 + // bit it fits and the check holds for every possible return value. + let clamped = Delta::from_millis(i64::from(i32::MAX)).to_jiffies_timeout(); + assert!(clamped.as_jiffies() <= MAX_JIFFY_OFFSET); + + // `MAX_JIFFY_OFFSET` is derived from `long`, so only 32 bit can reach it. On + // 64 bit `i64::MAX` nanoseconds is about 292 years, which is 9223372036855 + // jiffies with `HZ=1000`, far below the limit. + #[cfg(not(CONFIG_64BIT))] + { + // An overlong span is clamped to `MAX_JIFFY_OFFSET`. + let overlong = Delta::from_nanos(i64::MAX).to_jiffies_timeout(); + assert_eq!(overlong.as_jiffies(), MAX_JIFFY_OFFSET); + } + + // A negative span is an immediate timeout, however long it is. + let negative = Delta::from_nanos(i64::MIN).to_jiffies_timeout(); + assert_eq!(negative.as_jiffies(), 0); + } +} diff --git a/rust/kernel/time/delay.rs b/rust/kernel/time/delay.rs index b5b1b42797a0..4debe23731bf 100644 --- a/rust/kernel/time/delay.rs +++ b/rust/kernel/time/delay.rs @@ -8,7 +8,10 @@ //! C header: [`include/linux/delay.h`](srctree/include/linux/delay.h). use super::Delta; -use crate::prelude::*; +use crate::{ + pr_warn_once, + prelude::*, // +}; /// Sleeps for a given duration at least. /// @@ -18,8 +21,7 @@ use crate::prelude::*; /// `delta` must be within `[0, i32::MAX]` microseconds; /// otherwise, it is erroneous behavior. That is, it is considered a bug /// to call this function with an out-of-range value, in which case the function -/// will sleep for at least the maximum value in the range and may warn -/// in the future. +/// will sleep for at least the maximum value in the range and warns once. /// /// The behavior above differs from the C side [`fsleep()`] for which out-of-range /// values mean "infinite timeout" instead. @@ -32,10 +34,13 @@ pub fn fsleep(delta: Delta) { // overflow inside fsleep, which could lead to unintentional infinite sleep. const MAX_DELTA: Delta = Delta::from_micros(i32::MAX as i64); + debug_assert!(delta.as_nanos() >= 0); + debug_assert!(delta <= MAX_DELTA); + let delta = if (Delta::ZERO..=MAX_DELTA).contains(&delta) { delta } else { - // TODO: Add WARN_ONCE() when it's supported. + pr_warn_once!("attempted to fsleep() with out of range delta\n"); MAX_DELTA }; @@ -54,7 +59,8 @@ pub fn fsleep(delta: Delta) { /// /// `delta` must be within `[0, MAX_UDELAY_MS]` in milliseconds; /// otherwise, it is erroneous behavior. That is, it is considered a bug to -/// call this function with an out-of-range value. +/// call this function with an out-of-range value, in which case the function +/// will delay for at least the maximum value in the range and warns once. /// /// The behavior above differs from the C side [`udelay()`] for which out-of-range /// values could lead to an overflow and unexpected behavior. @@ -69,6 +75,7 @@ pub fn udelay(delta: Delta) { let delta = if (Delta::ZERO..=MAX_UDELAY_DELTA).contains(&delta) { delta } else { + pr_warn_once!("attempted to udelay() with out of range delta\n"); MAX_UDELAY_DELTA }; diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs index 2d7f1131a813..c0180b8ca5d3 100644 --- a/rust/kernel/time/hrtimer.rs +++ b/rust/kernel/time/hrtimer.rs @@ -402,15 +402,26 @@ //! ``` //! //! [`Arc`]: kernel::sync::Arc - -use super::{ClockSource, Delta, Instant}; +// Implementation details +// +// The reasoning for adopting a handle based approach: +// - If we explicitly drop the target of a timer callback in the timer callback, we +// may get a dangling reference. +// - If the callback owns the last reference to the target, target may be dropped +// in non-sleepable context when the callback is finished. +// - When dropping an object that is the target of an armed timer, we may drop +// fields accessed by the timer callback before we cancel the timer (drop order). +// +// By using a handle, we can make the handle own the callback target and avoid these problems. + +use super::{ClockId, Delta, Instant}; use crate::{prelude::*, types::Opaque}; use core::{marker::PhantomData, ptr::NonNull}; use pin_init::PinInit; /// A type-alias to refer to the [`Instant<C>`] for a given `T` from [`HrTimer<T>`]. /// -/// Where `C` is the [`ClockSource`] of the [`HrTimer`]. +/// Where `C` is the [`ClockId`] of the [`HrTimer`]. pub type HrTimerInstant<T> = Instant<<<T as HasHrTimer<T>>::TimerMode as HrTimerMode>::Clock>; /// A timer backed by a C `struct hrtimer`. @@ -855,7 +866,7 @@ pub trait HrTimerExpires { fn as_nanos(&self) -> i64; } -impl<C: ClockSource> HrTimerExpires for Instant<C> { +impl<C: ClockId> HrTimerExpires for Instant<C> { #[inline] fn as_nanos(&self) -> i64 { Instant::<C>::as_nanos(self) @@ -870,22 +881,22 @@ impl HrTimerExpires for Delta { } mod private { - use crate::time::ClockSource; + use crate::time::ClockId; pub trait Sealed {} - impl<C: ClockSource> Sealed for super::AbsoluteMode<C> {} - impl<C: ClockSource> Sealed for super::RelativeMode<C> {} - impl<C: ClockSource> Sealed for super::AbsolutePinnedMode<C> {} - impl<C: ClockSource> Sealed for super::RelativePinnedMode<C> {} - impl<C: ClockSource> Sealed for super::AbsoluteSoftMode<C> {} - impl<C: ClockSource> Sealed for super::RelativeSoftMode<C> {} - impl<C: ClockSource> Sealed for super::AbsolutePinnedSoftMode<C> {} - impl<C: ClockSource> Sealed for super::RelativePinnedSoftMode<C> {} - impl<C: ClockSource> Sealed for super::AbsoluteHardMode<C> {} - impl<C: ClockSource> Sealed for super::RelativeHardMode<C> {} - impl<C: ClockSource> Sealed for super::AbsolutePinnedHardMode<C> {} - impl<C: ClockSource> Sealed for super::RelativePinnedHardMode<C> {} + impl<C: ClockId> Sealed for super::AbsoluteMode<C> {} + impl<C: ClockId> Sealed for super::RelativeMode<C> {} + impl<C: ClockId> Sealed for super::AbsolutePinnedMode<C> {} + impl<C: ClockId> Sealed for super::RelativePinnedMode<C> {} + impl<C: ClockId> Sealed for super::AbsoluteSoftMode<C> {} + impl<C: ClockId> Sealed for super::RelativeSoftMode<C> {} + impl<C: ClockId> Sealed for super::AbsolutePinnedSoftMode<C> {} + impl<C: ClockId> Sealed for super::RelativePinnedSoftMode<C> {} + impl<C: ClockId> Sealed for super::AbsoluteHardMode<C> {} + impl<C: ClockId> Sealed for super::RelativeHardMode<C> {} + impl<C: ClockId> Sealed for super::AbsolutePinnedHardMode<C> {} + impl<C: ClockId> Sealed for super::RelativePinnedHardMode<C> {} } /// Operational mode of [`HrTimer`]. @@ -894,16 +905,16 @@ pub trait HrTimerMode: private::Sealed { const C_MODE: bindings::hrtimer_mode; /// Type representing the clock source. - type Clock: ClockSource; + type Clock: ClockId; /// Type representing the expiration specification (absolute or relative time). type Expires: HrTimerExpires; } /// Timer that expires at a fixed point in time. -pub struct AbsoluteMode<C: ClockSource>(PhantomData<C>); +pub struct AbsoluteMode<C: ClockId>(PhantomData<C>); -impl<C: ClockSource> HrTimerMode for AbsoluteMode<C> { +impl<C: ClockId> HrTimerMode for AbsoluteMode<C> { const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS; type Clock = C; @@ -911,9 +922,9 @@ impl<C: ClockSource> HrTimerMode for AbsoluteMode<C> { } /// Timer that expires after a delay from now. -pub struct RelativeMode<C: ClockSource>(PhantomData<C>); +pub struct RelativeMode<C: ClockId>(PhantomData<C>); -impl<C: ClockSource> HrTimerMode for RelativeMode<C> { +impl<C: ClockId> HrTimerMode for RelativeMode<C> { const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL; type Clock = C; @@ -921,8 +932,8 @@ impl<C: ClockSource> HrTimerMode for RelativeMode<C> { } /// Timer with absolute expiration time, pinned to its current CPU. -pub struct AbsolutePinnedMode<C: ClockSource>(PhantomData<C>); -impl<C: ClockSource> HrTimerMode for AbsolutePinnedMode<C> { +pub struct AbsolutePinnedMode<C: ClockId>(PhantomData<C>); +impl<C: ClockId> HrTimerMode for AbsolutePinnedMode<C> { const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS_PINNED; type Clock = C; @@ -930,8 +941,8 @@ impl<C: ClockSource> HrTimerMode for AbsolutePinnedMode<C> { } /// Timer with relative expiration time, pinned to its current CPU. -pub struct RelativePinnedMode<C: ClockSource>(PhantomData<C>); -impl<C: ClockSource> HrTimerMode for RelativePinnedMode<C> { +pub struct RelativePinnedMode<C: ClockId>(PhantomData<C>); +impl<C: ClockId> HrTimerMode for RelativePinnedMode<C> { const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL_PINNED; type Clock = C; @@ -939,8 +950,8 @@ impl<C: ClockSource> HrTimerMode for RelativePinnedMode<C> { } /// Timer with absolute expiration, handled in soft irq context. -pub struct AbsoluteSoftMode<C: ClockSource>(PhantomData<C>); -impl<C: ClockSource> HrTimerMode for AbsoluteSoftMode<C> { +pub struct AbsoluteSoftMode<C: ClockId>(PhantomData<C>); +impl<C: ClockId> HrTimerMode for AbsoluteSoftMode<C> { const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS_SOFT; type Clock = C; @@ -948,8 +959,8 @@ impl<C: ClockSource> HrTimerMode for AbsoluteSoftMode<C> { } /// Timer with relative expiration, handled in soft irq context. -pub struct RelativeSoftMode<C: ClockSource>(PhantomData<C>); -impl<C: ClockSource> HrTimerMode for RelativeSoftMode<C> { +pub struct RelativeSoftMode<C: ClockId>(PhantomData<C>); +impl<C: ClockId> HrTimerMode for RelativeSoftMode<C> { const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL_SOFT; type Clock = C; @@ -957,8 +968,8 @@ impl<C: ClockSource> HrTimerMode for RelativeSoftMode<C> { } /// Timer with absolute expiration, pinned to CPU and handled in soft irq context. -pub struct AbsolutePinnedSoftMode<C: ClockSource>(PhantomData<C>); -impl<C: ClockSource> HrTimerMode for AbsolutePinnedSoftMode<C> { +pub struct AbsolutePinnedSoftMode<C: ClockId>(PhantomData<C>); +impl<C: ClockId> HrTimerMode for AbsolutePinnedSoftMode<C> { const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS_PINNED_SOFT; type Clock = C; @@ -966,8 +977,8 @@ impl<C: ClockSource> HrTimerMode for AbsolutePinnedSoftMode<C> { } /// Timer with absolute expiration, pinned to CPU and handled in soft irq context. -pub struct RelativePinnedSoftMode<C: ClockSource>(PhantomData<C>); -impl<C: ClockSource> HrTimerMode for RelativePinnedSoftMode<C> { +pub struct RelativePinnedSoftMode<C: ClockId>(PhantomData<C>); +impl<C: ClockId> HrTimerMode for RelativePinnedSoftMode<C> { const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL_PINNED_SOFT; type Clock = C; @@ -975,8 +986,8 @@ impl<C: ClockSource> HrTimerMode for RelativePinnedSoftMode<C> { } /// Timer with absolute expiration, handled in hard irq context. -pub struct AbsoluteHardMode<C: ClockSource>(PhantomData<C>); -impl<C: ClockSource> HrTimerMode for AbsoluteHardMode<C> { +pub struct AbsoluteHardMode<C: ClockId>(PhantomData<C>); +impl<C: ClockId> HrTimerMode for AbsoluteHardMode<C> { const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS_HARD; type Clock = C; @@ -984,8 +995,8 @@ impl<C: ClockSource> HrTimerMode for AbsoluteHardMode<C> { } /// Timer with relative expiration, handled in hard irq context. -pub struct RelativeHardMode<C: ClockSource>(PhantomData<C>); -impl<C: ClockSource> HrTimerMode for RelativeHardMode<C> { +pub struct RelativeHardMode<C: ClockId>(PhantomData<C>); +impl<C: ClockId> HrTimerMode for RelativeHardMode<C> { const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL_HARD; type Clock = C; @@ -993,8 +1004,8 @@ impl<C: ClockSource> HrTimerMode for RelativeHardMode<C> { } /// Timer with absolute expiration, pinned to CPU and handled in hard irq context. -pub struct AbsolutePinnedHardMode<C: ClockSource>(PhantomData<C>); -impl<C: ClockSource> HrTimerMode for AbsolutePinnedHardMode<C> { +pub struct AbsolutePinnedHardMode<C: ClockId>(PhantomData<C>); +impl<C: ClockId> HrTimerMode for AbsolutePinnedHardMode<C> { const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_ABS_PINNED_HARD; type Clock = C; @@ -1002,8 +1013,8 @@ impl<C: ClockSource> HrTimerMode for AbsolutePinnedHardMode<C> { } /// Timer with relative expiration, pinned to CPU and handled in hard irq context. -pub struct RelativePinnedHardMode<C: ClockSource>(PhantomData<C>); -impl<C: ClockSource> HrTimerMode for RelativePinnedHardMode<C> { +pub struct RelativePinnedHardMode<C: ClockId>(PhantomData<C>); +impl<C: ClockId> HrTimerMode for RelativePinnedHardMode<C> { const C_MODE: bindings::hrtimer_mode = bindings::hrtimer_mode_HRTIMER_MODE_REL_PINNED_HARD; type Clock = C; |
