Skip to content

Commit 1655912

Browse files
committed
Auto merge of #151521 - jhpratt:rollup-PFh8sRJ, r=jhpratt
Rollup of 4 pull requests Successful merges: - #151450 (std: use `clock_nanosleep` for `sleep` where available) - #151494 (std: ensure that the deadline has passed in `sleep_until`) - #151498 (global.rs: improve readability of re-entrance section) - #151504 (Reorganizing tests/ui/issues 11 tests [3/N]) r? @ghost
2 parents d10ac47 + 3086257 commit 1655912

21 files changed

Lines changed: 115 additions & 60 deletions

library/core/src/alloc/global.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,12 +118,12 @@ use crate::{cmp, ptr};
118118
///
119119
/// # Re-entrance
120120
///
121-
/// When implementing a global allocator one has to be careful not to create an infinitely recursive
121+
/// When implementing a global allocator, one has to be careful not to create an infinitely recursive
122122
/// implementation by accident, as many constructs in the Rust standard library may allocate in
123-
/// their implementation. For example, on some platforms [`std::sync::Mutex`] may allocate, so using
123+
/// their implementation. For example, on some platforms, [`std::sync::Mutex`] may allocate, so using
124124
/// it is highly problematic in a global allocator.
125125
///
126-
/// Generally speaking for this reason one should stick to library features available through
126+
/// For this reason, one should generally stick to library features available through
127127
/// [`core`], and avoid using [`std`] in a global allocator. A few features from [`std`] are
128128
/// guaranteed to not use `#[global_allocator]` to allocate:
129129
///

library/std/src/sys/thread/mod.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,16 @@ cfg_select! {
139139
pub fn sleep_until(deadline: crate::time::Instant) {
140140
use crate::time::Instant;
141141

142-
let now = Instant::now();
143-
144-
if let Some(delay) = deadline.checked_duration_since(now) {
142+
// The clock source used for `sleep` might not be the same used for `Instant`.
143+
// Since this function *must not* return before the deadline, we recheck the
144+
// time after every call to `sleep`. See #149935 for an example of this
145+
// occurring on older Windows systems.
146+
while let Some(delay) = deadline.checked_duration_since(Instant::now()) {
147+
// Sleep for the estimated time remaining until the deadline.
148+
//
149+
// If your system has a better way of estimating the delay time or
150+
// provides a way to sleep until an absolute time, specialize this
151+
// function for your system.
145152
sleep(delay);
146153
}
147154
}

library/std/src/sys/thread/unix.rs

Lines changed: 48 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -528,8 +528,51 @@ pub fn set_name(name: &CStr) {
528528
debug_assert_eq!(res, libc::OK);
529529
}
530530

531-
#[cfg(not(any(target_os = "espidf", target_os = "wasi")))]
531+
#[cfg(not(target_os = "espidf"))]
532532
pub fn sleep(dur: Duration) {
533+
cfg_select! {
534+
// Any unix that has clock_nanosleep
535+
// If this list changes update the MIRI chock_nanosleep shim
536+
any(
537+
target_os = "freebsd",
538+
target_os = "netbsd",
539+
target_os = "linux",
540+
target_os = "android",
541+
target_os = "solaris",
542+
target_os = "illumos",
543+
target_os = "dragonfly",
544+
target_os = "hurd",
545+
target_os = "fuchsia",
546+
target_os = "vxworks",
547+
target_os = "wasi",
548+
) => {
549+
// POSIX specifies that `nanosleep` uses CLOCK_REALTIME, but is not
550+
// affected by clock adjustments. The timing of `sleep` however should
551+
// be tied to `Instant` where possible. Thus, we use `clock_nanosleep`
552+
// with a relative time interval instead, which allows explicitly
553+
// specifying the clock.
554+
//
555+
// In practice, most systems (like e.g. Linux) actually use
556+
// CLOCK_MONOTONIC for `nanosleep` anyway, but others like FreeBSD don't
557+
// so it's better to be safe.
558+
//
559+
// wasi-libc prior to WebAssembly/wasi-libc#696 has a broken implementation
560+
// of `nanosleep` which used `CLOCK_REALTIME` even though it is unsupported
561+
// on WASIp2. Using `clock_nanosleep` directly bypasses the issue.
562+
unsafe fn nanosleep(rqtp: *const libc::timespec, rmtp: *mut libc::timespec) -> libc::c_int {
563+
unsafe { libc::clock_nanosleep(crate::sys::time::Instant::CLOCK_ID, 0, rqtp, rmtp) }
564+
}
565+
}
566+
_ => {
567+
unsafe fn nanosleep(rqtp: *const libc::timespec, rmtp: *mut libc::timespec) -> libc::c_int {
568+
let r = unsafe { libc::nanosleep(rqtp, rmtp) };
569+
// `clock_nanosleep` returns the error number directly, so mimic
570+
// that behaviour to make the shared code below simpler.
571+
if r == 0 { 0 } else { sys::io::errno() }
572+
}
573+
}
574+
}
575+
533576
let mut secs = dur.as_secs();
534577
let mut nsecs = dur.subsec_nanos() as _;
535578

@@ -543,8 +586,9 @@ pub fn sleep(dur: Duration) {
543586
};
544587
secs -= ts.tv_sec as u64;
545588
let ts_ptr = &raw mut ts;
546-
if libc::nanosleep(ts_ptr, ts_ptr) == -1 {
547-
assert_eq!(sys::io::errno(), libc::EINTR);
589+
let r = nanosleep(ts_ptr, ts_ptr);
590+
if r != 0 {
591+
assert_eq!(r, libc::EINTR);
548592
secs += ts.tv_sec as u64;
549593
nsecs = ts.tv_nsec;
550594
} else {
@@ -554,13 +598,7 @@ pub fn sleep(dur: Duration) {
554598
}
555599
}
556600

557-
#[cfg(any(
558-
target_os = "espidf",
559-
// wasi-libc prior to WebAssembly/wasi-libc#696 has a broken implementation
560-
// of `nanosleep`, used above by most platforms, so use `usleep` until
561-
// that fix propagates throughout the ecosystem.
562-
target_os = "wasi",
563-
))]
601+
#[cfg(target_os = "espidf")]
564602
pub fn sleep(dur: Duration) {
565603
// ESP-IDF does not have `nanosleep`, so we use `usleep` instead.
566604
// As per the documentation of `usleep`, it is expected to support
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//! regression test for <https://github.com/rust-lang/rust/issues/16819>
12
//@ run-pass
23
#![allow(unused_variables)]
34
// `#[cfg]` on struct field permits empty unusable struct

tests/ui/issues/issue-74564-if-expr-stack-overflow.rs renamed to tests/ui/expr/if/expr-stack-overflow.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//! regression test for <https://github.com/rust-lang/rust/issues/74564>
12
//@ build-pass
23
// ignore-tidy-filelength
34
#![crate_type = "rlib"]

tests/ui/issues/issue-47715.rs renamed to tests/ui/impl-trait/impl-trait-in-generic-param.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
//! regression test for <https://github.com/rust-lang/rust/issues/47715>
2+
13
trait Foo {}
24

35
trait Bar<T> {}

tests/ui/issues/issue-47715.stderr renamed to tests/ui/impl-trait/impl-trait-in-generic-param.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
error[E0562]: `impl Trait` is not allowed in generics
2-
--> $DIR/issue-47715.rs:9:37
2+
--> $DIR/impl-trait-in-generic-param.rs:11:37
33
|
44
LL | struct Container<T: Iterable<Item = impl Foo>> {
55
| ^^^^^^^^
66
|
77
= note: `impl Trait` is only allowed in arguments and return types of functions and methods
88

99
error[E0562]: `impl Trait` is not allowed in generics
10-
--> $DIR/issue-47715.rs:14:30
10+
--> $DIR/impl-trait-in-generic-param.rs:16:30
1111
|
1212
LL | enum Enum<T: Iterable<Item = impl Foo>> {
1313
| ^^^^^^^^
1414
|
1515
= note: `impl Trait` is only allowed in arguments and return types of functions and methods
1616

1717
error[E0562]: `impl Trait` is not allowed in generics
18-
--> $DIR/issue-47715.rs:19:32
18+
--> $DIR/impl-trait-in-generic-param.rs:21:32
1919
|
2020
LL | union Union<T: Iterable<Item = impl Foo> + Copy> {
2121
| ^^^^^^^^
2222
|
2323
= note: `impl Trait` is only allowed in arguments and return types of functions and methods
2424

2525
error[E0562]: `impl Trait` is not allowed in generics
26-
--> $DIR/issue-47715.rs:24:30
26+
--> $DIR/impl-trait-in-generic-param.rs:26:30
2727
|
2828
LL | type Type<T: Iterable<Item = impl Foo>> = T;
2929
| ^^^^^^^^

tests/ui/issues/auxiliary/issue-11529.rs

Lines changed: 0 additions & 1 deletion
This file was deleted.

tests/ui/issues/issue-11529.rs

Lines changed: 0 additions & 10 deletions
This file was deleted.

tests/ui/issues/issue-49934-errors.rs

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)