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