xref: /linux/rust/kernel/time.rs (revision daff0977b2e36c777a00b4ca9fabc019834e60aa)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! Time related primitives.
4 //!
5 //! This module contains the kernel APIs related to time and timers that
6 //! have been ported or wrapped for usage by Rust code in the kernel.
7 //!
8 //! There are two types in this module:
9 //!
10 //! - The [`Instant`] type represents a specific point in time.
11 //! - The [`Delta`] type represents a span of time.
12 //!
13 //! Note that the C side uses `ktime_t` type to represent both. However, timestamp
14 //! and timedelta are different. To avoid confusion, we use two different types.
15 //!
16 //! A [`Instant`] object can be created by calling the [`Instant::now()`] function.
17 //! It represents a point in time at which the object was created.
18 //! By calling the [`Instant::elapsed()`] method, a [`Delta`] object representing
19 //! the elapsed time can be created. The [`Delta`] object can also be created
20 //! by subtracting two [`Instant`] objects.
21 //!
22 //! A [`Delta`] type supports methods to retrieve the duration in various units.
23 //!
24 //! C header: [`include/linux/jiffies.h`](srctree/include/linux/jiffies.h).
25 //! C header: [`include/linux/ktime.h`](srctree/include/linux/ktime.h).
26 
27 use core::marker::PhantomData;
28 use core::ops;
29 
30 pub mod delay;
31 pub mod hrtimer;
32 
33 /// The number of nanoseconds per microsecond.
34 pub const NSEC_PER_USEC: i64 = bindings::NSEC_PER_USEC as i64;
35 
36 /// The number of nanoseconds per millisecond.
37 pub const NSEC_PER_MSEC: i64 = bindings::NSEC_PER_MSEC as i64;
38 
39 /// The number of nanoseconds per second.
40 pub const NSEC_PER_SEC: i64 = bindings::NSEC_PER_SEC as i64;
41 
42 /// The C side `MAX_JIFFY_OFFSET`, i.e. `((LONG_MAX >> 1) - 1)`. It is the upper
43 /// bound the kernel uses for a jiffies span, not a wait-forever value.
44 const MAX_JIFFY_OFFSET: isize = (isize::MAX >> 1) - 1;
45 
46 /// The time unit of Linux kernel. One jiffy equals (1/HZ) second.
47 pub type Jiffies = crate::ffi::c_ulong;
48 
49 /// The millisecond time unit.
50 pub type Msecs = crate::ffi::c_uint;
51 
52 /// Converts milliseconds to jiffies.
53 #[inline]
54 pub fn msecs_to_jiffies(msecs: Msecs) -> Jiffies {
55     // SAFETY: The `__msecs_to_jiffies` function is always safe to call no
56     // matter what the argument is.
57     unsafe { bindings::__msecs_to_jiffies(msecs) }
58 }
59 
60 /// Trait for kernel clock identifiers.
61 ///
62 /// Selection of the clock depends on the use case. In some cases the usage of a
63 /// particular clock is mandatory, e.g. in network protocols, filesystems. In other
64 /// cases the user of the clock has to decide which clock is best suited for the
65 /// purpose. In most scenarios clock [`Monotonic`] is the best choice as it
66 /// provides a accurate monotonic notion of time (leap second smearing ignored).
67 ///
68 /// # Safety
69 ///
70 /// Implementers must ensure that `ktime_get()` returns a value in the inclusive range
71 /// `0..=KTIME_MAX` (i.e., greater than or equal to 0 and less than or equal to
72 /// `KTIME_MAX`, where `KTIME_MAX` equals `i64::MAX`).
73 pub unsafe trait ClockId {
74     /// The kernel clock ID associated with this clock.
75     ///
76     /// This constant corresponds to the C side `clockid_t` value.
77     const ID: bindings::clockid_t;
78 
79     /// Get the current time from the clock.
80     ///
81     /// The function must return a value in the range `0..=KTIME_MAX`.
82     fn ktime_get() -> bindings::ktime_t;
83 }
84 
85 /// A monotonically increasing clock.
86 ///
87 /// A nonsettable system-wide clock that represents monotonic time since as
88 /// described by POSIX, "some unspecified point in the past". On Linux, that
89 /// point corresponds to the number of seconds that the system has been
90 /// running since it was booted.
91 ///
92 /// The CLOCK_MONOTONIC clock is not affected by discontinuous jumps in the
93 /// CLOCK_REAL (e.g., if the system administrator manually changes the
94 /// clock), but is affected by frequency adjustments. This clock does not
95 /// count time that the system is suspended.
96 pub struct Monotonic;
97 
98 // SAFETY: The kernel's `ktime_get()` is guaranteed to return a value
99 // in `0..=KTIME_MAX`.
100 unsafe impl ClockId for Monotonic {
101     const ID: bindings::clockid_t = bindings::CLOCK_MONOTONIC as bindings::clockid_t;
102 
103     fn ktime_get() -> bindings::ktime_t {
104         // SAFETY: It is always safe to call `ktime_get()` outside of NMI context.
105         unsafe { bindings::ktime_get() }
106     }
107 }
108 
109 /// A settable system-wide clock that measures real (i.e., wall-clock) time.
110 ///
111 /// Setting this clock requires appropriate privileges. This clock is
112 /// affected by discontinuous jumps in the system time (e.g., if the system
113 /// administrator manually changes the clock), and by frequency adjustments
114 /// performed by NTP and similar applications via adjtime(3), adjtimex(2),
115 /// clock_adjtime(2), and ntp_adjtime(3). This clock normally counts the
116 /// number of seconds since 1970-01-01 00:00:00 Coordinated Universal Time
117 /// (UTC) except that it ignores leap seconds; near a leap second it may be
118 /// adjusted by leap second smearing to stay roughly in sync with UTC. Leap
119 /// second smearing applies frequency adjustments to the clock to speed up
120 /// or slow down the clock to account for the leap second without
121 /// discontinuities in the clock. If leap second smearing is not applied,
122 /// the clock will experience discontinuity around leap second adjustment.
123 pub struct RealTime;
124 
125 // SAFETY: The kernel's `ktime_get_real()` is guaranteed to return a value
126 // in `0..=KTIME_MAX`.
127 unsafe impl ClockId for RealTime {
128     const ID: bindings::clockid_t = bindings::CLOCK_REALTIME as bindings::clockid_t;
129 
130     fn ktime_get() -> bindings::ktime_t {
131         // SAFETY: It is always safe to call `ktime_get_real()` outside of NMI context.
132         unsafe { bindings::ktime_get_real() }
133     }
134 }
135 
136 /// A monotonic that ticks while system is suspended.
137 ///
138 /// A nonsettable system-wide clock that is identical to CLOCK_MONOTONIC,
139 /// except that it also includes any time that the system is suspended. This
140 /// allows applications to get a suspend-aware monotonic clock without
141 /// having to deal with the complications of CLOCK_REALTIME, which may have
142 /// discontinuities if the time is changed using settimeofday(2) or similar.
143 pub struct BootTime;
144 
145 // SAFETY: The kernel's `ktime_get_boottime()` is guaranteed to return a value
146 // in `0..=KTIME_MAX`.
147 unsafe impl ClockId for BootTime {
148     const ID: bindings::clockid_t = bindings::CLOCK_BOOTTIME as bindings::clockid_t;
149 
150     fn ktime_get() -> bindings::ktime_t {
151         // SAFETY: It is always safe to call `ktime_get_boottime()` outside of NMI context.
152         unsafe { bindings::ktime_get_boottime() }
153     }
154 }
155 
156 /// International Atomic Time.
157 ///
158 /// A system-wide clock derived from wall-clock time but counting leap seconds.
159 ///
160 /// This clock is coupled to CLOCK_REALTIME and will be set when CLOCK_REALTIME is
161 /// set, or when the offset to CLOCK_REALTIME is changed via adjtimex(2). This
162 /// usually happens during boot and **should** not happen during normal operations.
163 /// However, if NTP or another application adjusts CLOCK_REALTIME by leap second
164 /// smearing, this clock will not be precise during leap second smearing.
165 ///
166 /// The acronym TAI refers to International Atomic Time.
167 pub struct Tai;
168 
169 // SAFETY: The kernel's `ktime_get_clocktai()` is guaranteed to return a value
170 // in `0..=KTIME_MAX`.
171 unsafe impl ClockId for Tai {
172     const ID: bindings::clockid_t = bindings::CLOCK_TAI as bindings::clockid_t;
173 
174     fn ktime_get() -> bindings::ktime_t {
175         // SAFETY: It is always safe to call `ktime_get_tai()` outside of NMI context.
176         unsafe { bindings::ktime_get_clocktai() }
177     }
178 }
179 
180 /// A specific point in time.
181 ///
182 /// # Invariants
183 ///
184 /// The `inner` value is in the range from 0 to `KTIME_MAX`.
185 #[repr(transparent)]
186 #[derive(PartialEq, PartialOrd, Eq, Ord)]
187 pub struct Instant<C: ClockId> {
188     inner: bindings::ktime_t,
189     _c: PhantomData<C>,
190 }
191 
192 impl<C: ClockId> Clone for Instant<C> {
193     fn clone(&self) -> Self {
194         *self
195     }
196 }
197 
198 impl<C: ClockId> Copy for Instant<C> {}
199 
200 impl<C: ClockId> Instant<C> {
201     /// Get the current time from the clock source.
202     #[inline]
203     pub fn now() -> Self {
204         // INVARIANT: The `ClockId::ktime_get()` function returns a value in the range
205         // from 0 to `KTIME_MAX`.
206         Self {
207             inner: C::ktime_get(),
208             _c: PhantomData,
209         }
210     }
211 
212     /// Return the amount of time elapsed since the [`Instant`].
213     #[inline]
214     pub fn elapsed(&self) -> Delta {
215         Self::now() - *self
216     }
217 
218     #[inline]
219     pub(crate) fn as_nanos(&self) -> i64 {
220         self.inner
221     }
222 
223     /// Create an [`Instant`] from a `ktime_t` without checking if it is non-negative.
224     ///
225     /// # Panics
226     ///
227     /// On debug builds, this function will panic if `ktime` is not in the range from 0 to
228     /// `KTIME_MAX`.
229     ///
230     /// # Safety
231     ///
232     /// The caller promises that `ktime` is in the range from 0 to `KTIME_MAX`.
233     #[inline]
234     pub(crate) unsafe fn from_ktime(ktime: bindings::ktime_t) -> Self {
235         debug_assert!(ktime >= 0);
236 
237         // INVARIANT: Our safety contract ensures that `ktime` is in the range from 0 to
238         // `KTIME_MAX`.
239         Self {
240             inner: ktime,
241             _c: PhantomData,
242         }
243     }
244 }
245 
246 impl<C: ClockId> ops::Sub for Instant<C> {
247     type Output = Delta;
248 
249     // By the type invariant, it never overflows.
250     #[inline]
251     fn sub(self, other: Instant<C>) -> Delta {
252         Delta {
253             value: self.inner - other.inner,
254         }
255     }
256 }
257 
258 impl<T: ClockId> ops::Add<Delta> for Instant<T> {
259     type Output = Self;
260 
261     #[inline]
262     fn add(self, rhs: Delta) -> Self::Output {
263         // INVARIANT: With arithmetic over/underflow checks enabled, this will panic if we overflow
264         // (e.g. go above `KTIME_MAX`)
265         let res = self.inner + rhs.value;
266 
267         // INVARIANT: With overflow checks enabled, we verify here that the value is >= 0
268         #[cfg(CONFIG_RUST_OVERFLOW_CHECKS)]
269         assert!(res >= 0);
270 
271         Self {
272             inner: res,
273             _c: PhantomData,
274         }
275     }
276 }
277 
278 impl<T: ClockId> ops::Sub<Delta> for Instant<T> {
279     type Output = Self;
280 
281     #[inline]
282     fn sub(self, rhs: Delta) -> Self::Output {
283         // INVARIANT: With arithmetic over/underflow checks enabled, this will panic if we overflow
284         // (e.g. go above `KTIME_MAX`)
285         let res = self.inner - rhs.value;
286 
287         // INVARIANT: With overflow checks enabled, we verify here that the value is >= 0
288         #[cfg(CONFIG_RUST_OVERFLOW_CHECKS)]
289         assert!(res >= 0);
290 
291         Self {
292             inner: res,
293             _c: PhantomData,
294         }
295     }
296 }
297 
298 mod private {
299     pub trait Sealed {}
300 
301     impl Sealed for super::Nsec {}
302     impl Sealed for super::Jiffy {}
303 }
304 
305 /// A trait for time units.
306 pub trait TimeUnit: private::Sealed {
307     /// The underlying representation of the time unit.
308     type Repr: Copy + Clone + PartialEq + PartialOrd + Eq + Ord + core::fmt::Debug;
309 
310     /// The zero value of [`Self::Repr`].
311     const ZERO: Self::Repr;
312 }
313 
314 /// A time unit of nanoseconds.
315 ///
316 /// A [`Delta<Nsec>`] stores its value as [`i64`] nanoseconds and can represent
317 /// any [`i64`] value, including negative, zero, and positive numbers.
318 #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
319 pub enum Nsec {}
320 
321 impl TimeUnit for Nsec {
322     type Repr = i64;
323     const ZERO: Self::Repr = 0;
324 }
325 
326 /// A time unit of jiffies.
327 ///
328 /// A [`Delta<Jiffy>`] stores its value as [`isize`] jiffies and can represent
329 /// any [`isize`] value, including negative, zero, and positive numbers.
330 #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
331 pub enum Jiffy {}
332 
333 impl TimeUnit for Jiffy {
334     type Repr = isize;
335     const ZERO: Self::Repr = 0;
336 }
337 
338 /// A span of time.
339 ///
340 /// The span is stored in the unit given by the type parameter `U` (see
341 /// [`TimeUnit`]); its value has type `U::Repr`. `U` defaults to [`Nsec`], so a
342 /// plain [`Delta`] is a span in nanoseconds. The value can be negative, zero, or
343 /// positive.
344 #[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug)]
345 pub struct Delta<U: TimeUnit = Nsec> {
346     value: U::Repr,
347 }
348 
349 impl<U: TimeUnit> Delta<U> {
350     /// A span of time equal to zero.
351     pub const ZERO: Self = Self { value: U::ZERO };
352 }
353 
354 impl Delta<Jiffy> {
355     /// Create a new [`Delta`] from a number of jiffies.
356     #[inline]
357     pub const fn from_jiffies(jiffies: isize) -> Self {
358         Self { value: jiffies }
359     }
360 
361     /// Return the number of jiffies in the [`Delta`].
362     #[inline]
363     pub const fn as_jiffies(self) -> isize {
364         self.value
365     }
366 
367     /// Return the number of jiffies in the [`Delta`] as an unsigned value.
368     ///
369     /// If the number of jiffies is negative, zero is returned.
370     ///
371     /// # Examples
372     ///
373     /// ```
374     /// use kernel::time::Delta;
375     ///
376     /// // A negative span returns zero.
377     /// assert_eq!(Delta::from_jiffies(-1).as_jiffies_unsigned(), 0);
378     ///
379     /// // A positive span returns its value.
380     /// assert_eq!(Delta::from_jiffies(1).as_jiffies_unsigned(), 1);
381     /// ```
382     #[inline]
383     pub fn as_jiffies_unsigned(self) -> usize {
384         // CAST: `isize::max()` makes the value non-negative, so the cast keeps it.
385         isize::max(self.value, 0) as usize
386     }
387 }
388 
389 impl ops::Add for Delta {
390     type Output = Self;
391 
392     #[inline]
393     fn add(self, rhs: Self) -> Self {
394         Self {
395             value: self.value + rhs.value,
396         }
397     }
398 }
399 
400 impl ops::AddAssign for Delta {
401     #[inline]
402     fn add_assign(&mut self, rhs: Self) {
403         self.value += rhs.value;
404     }
405 }
406 
407 impl ops::Sub for Delta {
408     type Output = Self;
409 
410     #[inline]
411     fn sub(self, rhs: Self) -> Self::Output {
412         Self {
413             value: self.value - rhs.value,
414         }
415     }
416 }
417 
418 impl ops::SubAssign for Delta {
419     #[inline]
420     fn sub_assign(&mut self, rhs: Self) {
421         self.value -= rhs.value;
422     }
423 }
424 
425 impl ops::Mul<i64> for Delta {
426     type Output = Self;
427 
428     #[inline]
429     fn mul(self, rhs: i64) -> Self::Output {
430         Self {
431             value: self.value * rhs,
432         }
433     }
434 }
435 
436 impl ops::MulAssign<i64> for Delta {
437     #[inline]
438     fn mul_assign(&mut self, rhs: i64) {
439         self.value *= rhs;
440     }
441 }
442 
443 impl ops::Div for Delta {
444     type Output = i64;
445 
446     #[inline]
447     fn div(self, rhs: Self) -> Self::Output {
448         #[cfg(CONFIG_64BIT)]
449         {
450             self.value / rhs.value
451         }
452 
453         #[cfg(not(CONFIG_64BIT))]
454         {
455             // SAFETY: This function is always safe to call regardless of the input values
456             unsafe { bindings::div64_s64(self.value, rhs.value) }
457         }
458     }
459 }
460 
461 impl Delta {
462     /// Create a new [`Delta`] from a number of nanoseconds.
463     #[inline]
464     pub const fn from_nanos(nanos: i64) -> Self {
465         Self { value: nanos }
466     }
467 
468     /// Create a new [`Delta`] from a number of microseconds.
469     ///
470     /// The `micros` can range from -9_223_372_036_854_775 to 9_223_372_036_854_775.
471     /// If `micros` is outside this range, `i64::MIN` is used for negative values,
472     /// and `i64::MAX` is used for positive values due to saturation.
473     #[inline]
474     pub const fn from_micros(micros: i64) -> Self {
475         Self {
476             value: micros.saturating_mul(NSEC_PER_USEC),
477         }
478     }
479 
480     /// Create a new [`Delta`] from a number of milliseconds.
481     ///
482     /// The `millis` can range from -9_223_372_036_854 to 9_223_372_036_854.
483     /// If `millis` is outside this range, `i64::MIN` is used for negative values,
484     /// and `i64::MAX` is used for positive values due to saturation.
485     #[inline]
486     pub const fn from_millis(millis: i64) -> Self {
487         Self {
488             value: millis.saturating_mul(NSEC_PER_MSEC),
489         }
490     }
491 
492     /// Create a new [`Delta`] from a number of seconds.
493     ///
494     /// The `secs` can range from -9_223_372_036 to 9_223_372_036.
495     /// If `secs` is outside this range, `i64::MIN` is used for negative values,
496     /// and `i64::MAX` is used for positive values due to saturation.
497     #[inline]
498     pub const fn from_secs(secs: i64) -> Self {
499         Self {
500             value: secs.saturating_mul(NSEC_PER_SEC),
501         }
502     }
503 
504     /// Return `true` if the [`Delta`] spans no time.
505     #[inline]
506     pub fn is_zero(self) -> bool {
507         self.as_nanos() == 0
508     }
509 
510     /// Return `true` if the [`Delta`] spans a negative amount of time.
511     #[inline]
512     pub fn is_negative(self) -> bool {
513         self.as_nanos() < 0
514     }
515 
516     /// Return the number of nanoseconds in the [`Delta`].
517     #[inline]
518     pub const fn as_nanos(self) -> i64 {
519         self.value
520     }
521 
522     /// Return the smallest number of microseconds greater than or equal
523     /// to the value in the [`Delta`].
524     #[inline]
525     pub fn as_micros_ceil(self) -> i64 {
526         // Only positive values need to be rounded up: truncating division already
527         // rounds towards zero, i.e. up, for negative values.
528         //
529         // The usual `(nanos + d - 1) / d` is not used because the addition overflows
530         // once `nanos` exceeds `i64::MAX - (d - 1)`; saturating the addition instead
531         // would drop the rounding bias and return a result one unit too small.
532         let n = self.as_nanos();
533 
534         let (n, add) = if n > 0 { (n - 1, 1) } else { (n, 0) };
535 
536         #[cfg(CONFIG_64BIT)]
537         {
538             n / NSEC_PER_USEC + add
539         }
540 
541         #[cfg(not(CONFIG_64BIT))]
542         // SAFETY: It is always safe to call `ktime_to_us()` with any value.
543         unsafe {
544             bindings::ktime_to_us(n) + add
545         }
546     }
547 
548     /// Return the number of milliseconds in the [`Delta`].
549     #[inline]
550     pub fn as_millis(self) -> i64 {
551         #[cfg(CONFIG_64BIT)]
552         {
553             self.as_nanos() / NSEC_PER_MSEC
554         }
555 
556         #[cfg(not(CONFIG_64BIT))]
557         // SAFETY: It is always safe to call `ktime_to_ms()` with any value.
558         unsafe {
559             bindings::ktime_to_ms(self.as_nanos())
560         }
561     }
562 
563     /// Return the smallest number of milliseconds greater than or equal
564     /// to the value in the [`Delta`].
565     #[inline]
566     pub fn as_millis_ceil(self) -> i64 {
567         // Only positive values need to be rounded up: truncating division already
568         // rounds towards zero, i.e. up, for negative values.
569         //
570         // The usual `(nanos + d - 1) / d` is not used because the addition overflows
571         // once `nanos` exceeds `i64::MAX - (d - 1)`; saturating the addition instead
572         // would drop the rounding bias and return a result one unit too small.
573         let n = self.as_nanos();
574 
575         let (n, add) = if n > 0 { (n - 1, 1) } else { (n, 0) };
576 
577         #[cfg(CONFIG_64BIT)]
578         {
579             n / NSEC_PER_MSEC + add
580         }
581 
582         #[cfg(not(CONFIG_64BIT))]
583         // SAFETY: It is always safe to call `ktime_to_ms()` with any value.
584         unsafe {
585             bindings::ktime_to_ms(n) + add
586         }
587     }
588 
589     /// Convert this span to a [`Delta<Jiffy>`] suitable for use as a timeout.
590     ///
591     /// Unless the result saturates, the value is rounded up to the next whole
592     /// jiffy, so the resulting timeout is never shorter than `self`.
593     ///
594     /// A negative span saturates at zero jiffies, i.e. an immediate timeout.
595     ///
596     /// A span that does not fit saturates at the kernel's [`MAX_JIFFY_OFFSET`],
597     /// the upper bound for a jiffies span. That is a finite timeout, so a
598     /// saturated result can be shorter than the requested span. It is derived
599     /// from `long`, so only 32 bit can reach it, at about 12 days with `HZ=1000`.
600     ///
601     /// # Examples
602     ///
603     /// ```
604     /// use kernel::time::Delta;
605     ///
606     /// // A negative span is an immediate timeout.
607     /// assert_eq!(Delta::from_millis(-1).to_jiffies_timeout().as_jiffies(), 0);
608     ///
609     /// // A span shorter than a jiffy still waits, i.e. the timeout is never
610     /// // shorter than the span.
611     /// assert!(Delta::from_nanos(1).to_jiffies_timeout().as_jiffies() >= 1);
612     /// ```
613     ///
614     /// [`MAX_JIFFY_OFFSET`]: srctree/include/linux/jiffies.h
615     #[inline]
616     pub fn to_jiffies_timeout(self) -> Delta<Jiffy> {
617         const HZ: u64 = bindings::HZ as u64;
618 
619         // The quotient `(nsecs * HZ + NSEC_PER_SEC - 1) / NSEC_PER_SEC` has to fit in
620         // `u64`; `nsecs * HZ` does not. With `HZ <= NSEC_PER_SEC` the numerator is at
621         // most `(nsecs + 1) * NSEC_PER_SEC - 1`, so the quotient is at most `nsecs`.
622         crate::static_assert!(HZ <= NSEC_PER_SEC as u64);
623 
624         // CAST: `i64::max()` makes the value non-negative, so the cast keeps it.
625         let nsecs = i64::max(self.as_nanos(), 0) as u64;
626 
627         // SAFETY: `mul_u64_add_u64_div_u64()` must not be called with a zero divisor,
628         // and its result must fit in `u64`. `NSEC_PER_SEC` is a non-zero constant, and
629         // the assertion above bounds the quotient by `nsecs`.
630         let jiffies = unsafe {
631             bindings::mul_u64_add_u64_div_u64(
632                 nsecs,
633                 HZ,
634                 (NSEC_PER_SEC - 1) as u64,
635                 NSEC_PER_SEC as u64,
636             )
637         };
638 
639         // CAST: `jiffies` is clamped to `MAX_JIFFY_OFFSET`, which is `<= isize::MAX`.
640         let jiffies = u64::min(jiffies, MAX_JIFFY_OFFSET as u64) as isize;
641 
642         Delta::<Jiffy>::from_jiffies(jiffies)
643     }
644 
645     /// Return `self % dividend` where `dividend` is in nanoseconds.
646     ///
647     /// The kernel doesn't have any emulation for `s64 % s64` on 32 bit platforms, so this is
648     /// limited to 32 bit dividends.
649     #[inline]
650     pub fn rem_nanos(self, dividend: i32) -> Self {
651         #[cfg(CONFIG_64BIT)]
652         {
653             Self {
654                 value: self.as_nanos() % i64::from(dividend),
655             }
656         }
657 
658         #[cfg(not(CONFIG_64BIT))]
659         {
660             let mut rem = 0;
661 
662             // SAFETY: `rem` is in the stack, so we can always provide a valid pointer to it.
663             unsafe { bindings::div_s64_rem(self.as_nanos(), dividend, &mut rem) };
664 
665             Self {
666                 value: i64::from(rem),
667             }
668         }
669     }
670 }
671 
672 #[cfg(CONFIG_RUST_TIME_KUNIT_TEST)]
673 #[macros::kunit_tests(rust_kernel_time)]
674 mod tests {
675     use super::*;
676 
677     #[test]
678     fn to_jiffies_timeout_converts() {
679         const HZ: isize = bindings::HZ as isize;
680 
681         // One second is exactly `HZ` jiffies, and the round-up must not add one.
682         assert_eq!(Delta::from_secs(1).to_jiffies_timeout().as_jiffies(), HZ);
683 
684         // One nanosecond more has to round up to the next whole jiffy.
685         assert_eq!(
686             Delta::from_nanos(NSEC_PER_SEC + 1)
687                 .to_jiffies_timeout()
688                 .as_jiffies(),
689             HZ + 1
690         );
691     }
692 
693     #[test]
694     fn to_jiffies_timeout_saturates() {
695         // The result never exceeds `MAX_JIFFY_OFFSET`. On 32 bit with `HZ=1000` this
696         // span is 2147483647 jiffies, so the clamp is what keeps it in range; on 64
697         // bit it fits and the check holds for every possible return value.
698         let clamped = Delta::from_millis(i64::from(i32::MAX)).to_jiffies_timeout();
699         assert!(clamped.as_jiffies() <= MAX_JIFFY_OFFSET);
700 
701         // `MAX_JIFFY_OFFSET` is derived from `long`, so only 32 bit can reach it. On
702         // 64 bit `i64::MAX` nanoseconds is about 292 years, which is 9223372036855
703         // jiffies with `HZ=1000`, far below the limit.
704         #[cfg(not(CONFIG_64BIT))]
705         {
706             // An overlong span is clamped to `MAX_JIFFY_OFFSET`.
707             let overlong = Delta::from_nanos(i64::MAX).to_jiffies_timeout();
708             assert_eq!(overlong.as_jiffies(), MAX_JIFFY_OFFSET);
709         }
710 
711         // A negative span is an immediate timeout, however long it is.
712         let negative = Delta::from_nanos(i64::MIN).to_jiffies_timeout();
713         assert_eq!(negative.as_jiffies(), 0);
714     }
715 }
716