@@ -267,14 +267,32 @@ impl Thread {
267
267
268
268
#[ cfg( target_os = "espidf" ) ]
269
269
pub fn sleep ( dur : Duration ) {
270
- let mut micros = dur. as_micros ( ) ;
271
- unsafe {
272
- while micros > 0 {
273
- let st = if micros > u32:: MAX as u128 { u32:: MAX } else { micros as u32 } ;
270
+ // ESP-IDF does not have `nanosleep`, so we use `usleep` instead.
271
+ // As per the documentation of `usleep`, it is expected to support
272
+ // sleep times as big as at least up to 1 second.
273
+ //
274
+ // ESP-IDF does support almost up to `u32::MAX`, but due to a potential integer overflow in its
275
+ // `usleep` implementation
276
+ // (https://github.com/espressif/esp-idf/blob/d7ca8b94c852052e3bc33292287ef4dd62c9eeb1/components/newlib/time.c#L210),
277
+ // we limit the sleep time to the maximum one that would not cause the underlying `usleep` implementation to overflow
278
+ // (`portTICK_PERIOD_MS` can be anything between 1 to 1000, and is 10 by default).
279
+ const MAX_MICROS : u32 = u32:: MAX - 1_000_000 - 1 ;
280
+
281
+ // Add any nanoseconds smaller than a microsecond as an extra microsecond
282
+ // so as to comply with the `std::thread::sleep` contract which mandates
283
+ // implementations to sleep for _at least_ the provided `dur`.
284
+ // We can't overflow `micros` as it is a `u128`, while `Duration` is a pair of
285
+ // (`u64` secs, `u32` nanos), where the nanos are strictly smaller than 1 second
286
+ // (i.e. < 1_000_000_000)
287
+ let mut micros = dur. as_micros ( ) + if dur. subsec_nanos ( ) % 1_000 > 0 { 1 } else { 0 } ;
288
+
289
+ while micros > 0 {
290
+ let st = if micros > MAX_MICROS as u128 { MAX_MICROS } else { micros as u32 } ;
291
+ unsafe {
274
292
libc:: usleep ( st) ;
275
-
276
- micros -= st as u128 ;
277
293
}
294
+
295
+ micros -= st as u128 ;
278
296
}
279
297
}
280
298
0 commit comments