@@ -9,13 +9,7 @@ use core::{cmp::min, time::Duration};
99
1010const 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