@@ -9,13 +9,7 @@ use core::{cmp::min, time::Duration};
9
9
10
10
const MILLIS_PER_SEC : u64 = 1_000 ;
11
11
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 {
19
13
let milli_as_nanos = Duration :: MILLISECOND . subsec_nanos ( ) ;
20
14
21
15
// Rounds the nanosecond component of `duration` up to the nearest millisecond.
@@ -27,6 +21,84 @@ pub fn coarse_sleep(duration: Duration) {
27
21
u64:: from ( core:: ffi:: c_uint:: MAX ) ,
28
22
) as core:: ffi:: c_uint ;
29
23
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 ) {
30
55
// 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
+ }
32
104
}
0 commit comments