about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-08-21 21:33:31 +0000
committerbors <bors@rust-lang.org>2024-08-21 21:33:31 +0000
commita32d4a0e822a29a6682e08b75a8df4c29c7fa9f1 (patch)
tree83ae19d9c47cdab62a6c3495215d2659fc21bd82 /library/std/src
parent6b678c57b63b3062fb97130b3617b82657f59c80 (diff)
parent00e109f3d4c495015020fce604f3c2eb79b0d3ee (diff)
downloadrust-a32d4a0e822a29a6682e08b75a8df4c29c7fa9f1.tar.gz
rust-a32d4a0e822a29a6682e08b75a8df4c29c7fa9f1.zip
Auto merge of #129370 - matthiaskrgr:rollup-g9117ee, r=matthiaskrgr
Rollup of 6 pull requests

Successful merges:

 - #128727 (bump conflicting_repr_hints lint to be shown in dependencies)
 - #129232 (Fix `thread::sleep` Duration-handling for ESP-IDF)
 - #129321 (Change neutral element of <fNN as iter::Sum> to neg_zero)
 - #129353 (llvm-wrapper: adapt for LLVM 20 API changes)
 - #129363 (Force `LC_ALL=C` for all run-make tests)
 - #129364 (safe transmute: gracefully bubble-up layout errors)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/sys/pal/unix/thread.rs30
1 files changed, 24 insertions, 6 deletions
diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index 0fa610eebb4..c9dcc5ad97a 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -267,14 +267,32 @@ impl Thread {
 
     #[cfg(target_os = "espidf")]
     pub fn sleep(dur: Duration) {
-        let mut micros = dur.as_micros();
-        unsafe {
-            while micros > 0 {
-                let st = if micros > u32::MAX as u128 { u32::MAX } else { micros as u32 };
+        // ESP-IDF does not have `nanosleep`, so we use `usleep` instead.
+        // As per the documentation of `usleep`, it is expected to support
+        // sleep times as big as at least up to 1 second.
+        //
+        // ESP-IDF does support almost up to `u32::MAX`, but due to a potential integer overflow in its
+        // `usleep` implementation
+        // (https://github.com/espressif/esp-idf/blob/d7ca8b94c852052e3bc33292287ef4dd62c9eeb1/components/newlib/time.c#L210),
+        // we limit the sleep time to the maximum one that would not cause the underlying `usleep` implementation to overflow
+        // (`portTICK_PERIOD_MS` can be anything between 1 to 1000, and is 10 by default).
+        const MAX_MICROS: u32 = u32::MAX - 1_000_000 - 1;
+
+        // Add any nanoseconds smaller than a microsecond as an extra microsecond
+        // so as to comply with the `std::thread::sleep` contract which mandates
+        // implementations to sleep for _at least_ the provided `dur`.
+        // We can't overflow `micros` as it is a `u128`, while `Duration` is a pair of
+        // (`u64` secs, `u32` nanos), where the nanos are strictly smaller than 1 second
+        // (i.e. < 1_000_000_000)
+        let mut micros = dur.as_micros() + if dur.subsec_nanos() % 1_000 > 0 { 1 } else { 0 };
+
+        while micros > 0 {
+            let st = if micros > MAX_MICROS as u128 { MAX_MICROS } else { micros as u32 };
+            unsafe {
                 libc::usleep(st);
-
-                micros -= st as u128;
             }
+
+            micros -= st as u128;
         }
     }