Skip to content

Commit 61926cb

Browse files
authored
Merge pull request #833 from ojeda/msleep-tests
rust: delay: add `coarse_sleep` examples and tests
2 parents 982cdac + 50ac9df commit 61926cb

File tree

1 file changed

+80
-8
lines changed

1 file changed

+80
-8
lines changed

rust/kernel/delay.rs

Lines changed: 80 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,7 @@ use core::{cmp::min, time::Duration};
99

1010
const MILLIS_PER_SEC: u64 = 1_000;
1111

12-
/// Sleeps safely even with waitqueue interruptions.
13-
///
14-
/// This function forwards the call to the C side `msleep` function. As a result,
15-
/// `duration` will be rounded up to the nearest millisecond if granularity less
16-
/// than a millisecond is provided. Any [`Duration`] that exceeds
17-
/// [`c_uint::MAX`][core::ffi::c_uint::MAX] in milliseconds is saturated.
18-
pub fn coarse_sleep(duration: Duration) {
12+
fn coarse_sleep_conversion(duration: Duration) -> core::ffi::c_uint {
1913
let milli_as_nanos = Duration::MILLISECOND.subsec_nanos();
2014

2115
// Rounds the nanosecond component of `duration` up to the nearest millisecond.
@@ -27,6 +21,84 @@ pub fn coarse_sleep(duration: Duration) {
2721
u64::from(core::ffi::c_uint::MAX),
2822
) as core::ffi::c_uint;
2923

24+
seconds_as_millis.saturating_add(nanos_as_millis)
25+
}
26+
27+
/// Sleeps safely even with waitqueue interruptions.
28+
///
29+
/// This function forwards the call to the C side `msleep` function. As a result,
30+
/// `duration` will be rounded up to the nearest millisecond if granularity less
31+
/// than a millisecond is provided. Any [`Duration`] that exceeds
32+
/// [`c_uint::MAX`][core::ffi::c_uint::MAX] in milliseconds is saturated.
33+
///
34+
/// # Examples
35+
///
36+
// Keep these in sync with `test_coarse_sleep_examples`.
37+
/// ```
38+
/// # use core::time::Duration;
39+
/// # use kernel::delay::coarse_sleep;
40+
/// coarse_sleep(Duration::ZERO); // Equivalent to `msleep(0)`.
41+
/// coarse_sleep(Duration::from_nanos(1)); // Equivalent to `msleep(1)`.
42+
///
43+
/// coarse_sleep(Duration::from_nanos(1_000_000)); // Equivalent to `msleep(1)`.
44+
/// coarse_sleep(Duration::from_nanos(1_000_001)); // Equivalent to `msleep(2)`.
45+
/// coarse_sleep(Duration::from_nanos(1_999_999)); // Equivalent to `msleep(2)`.
46+
///
47+
/// coarse_sleep(Duration::from_millis(1)); // Equivalent to `msleep(1)`.
48+
/// coarse_sleep(Duration::from_millis(2)); // Equivalent to `msleep(2)`.
49+
///
50+
/// coarse_sleep(Duration::from_secs(1)); // Equivalent to `msleep(1000)`.
51+
/// coarse_sleep(Duration::new(1, 1)); // Equivalent to `msleep(1001)`.
52+
/// coarse_sleep(Duration::new(1, 2)); // Equivalent to `msleep(1001)`.
53+
/// ```
54+
pub fn coarse_sleep(duration: Duration) {
3055
// SAFETY: msleep is safe for all values of an `unsigned int`.
31-
unsafe { bindings::msleep(seconds_as_millis.saturating_add(nanos_as_millis)) }
56+
unsafe { bindings::msleep(coarse_sleep_conversion(duration)) }
57+
}
58+
59+
#[cfg(test)]
60+
mod tests {
61+
use super::{coarse_sleep_conversion, MILLIS_PER_SEC};
62+
use core::time::Duration;
63+
64+
#[test]
65+
fn test_coarse_sleep_examples() {
66+
// Keep these in sync with `coarse_sleep`'s `# Examples` section.
67+
68+
assert_eq!(coarse_sleep_conversion(Duration::ZERO), 0);
69+
assert_eq!(coarse_sleep_conversion(Duration::from_nanos(1)), 1);
70+
71+
assert_eq!(coarse_sleep_conversion(Duration::from_nanos(1_000_000)), 1);
72+
assert_eq!(coarse_sleep_conversion(Duration::from_nanos(1_000_001)), 2);
73+
assert_eq!(coarse_sleep_conversion(Duration::from_nanos(1_999_999)), 2);
74+
75+
assert_eq!(coarse_sleep_conversion(Duration::from_millis(1)), 1);
76+
assert_eq!(coarse_sleep_conversion(Duration::from_millis(2)), 2);
77+
78+
assert_eq!(coarse_sleep_conversion(Duration::from_secs(1)), 1000);
79+
assert_eq!(coarse_sleep_conversion(Duration::new(1, 1)), 1001);
80+
assert_eq!(coarse_sleep_conversion(Duration::new(1, 2)), 1001);
81+
}
82+
83+
#[test]
84+
fn test_coarse_sleep_saturation() {
85+
assert!(
86+
coarse_sleep_conversion(Duration::new(
87+
core::ffi::c_uint::MAX as u64 / MILLIS_PER_SEC,
88+
0
89+
)) < core::ffi::c_uint::MAX
90+
);
91+
assert_eq!(
92+
coarse_sleep_conversion(Duration::new(
93+
core::ffi::c_uint::MAX as u64 / MILLIS_PER_SEC,
94+
999_999_999
95+
)),
96+
core::ffi::c_uint::MAX
97+
);
98+
99+
assert_eq!(
100+
coarse_sleep_conversion(Duration::MAX),
101+
core::ffi::c_uint::MAX
102+
);
103+
}
32104
}

0 commit comments

Comments
 (0)