New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Specialize sleep_until implementation #118480
base: master
Are you sure you want to change the base?
Changes from all commits
6e992b2
0de580b
93e4ce0
baf7d1d
b752788
d0a4d79
1e36e08
f3c9718
a0f50b6
8bc87ca
83d3fbd
30870b8
dac9893
fa89b9b
592bc55
a45b611
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -264,6 +264,79 @@ impl Thread { | |||||
} | ||||||
} | ||||||
|
||||||
#[cfg(not(any( | ||||||
target_os = "freebsd", | ||||||
target_os = "netbsd", | ||||||
target_os = "linux", | ||||||
target_os = "android", | ||||||
target_os = "solaris", | ||||||
target_os = "illumos", | ||||||
target_os = "macos", | ||||||
target_os = "ios", | ||||||
target_os = "tvos", | ||||||
target_os = "watchos" | ||||||
)))] | ||||||
pub fn sleep_until(deadline: Instant) { | ||||||
let now = Instant::now(); | ||||||
|
||||||
if let Some(delay) = deadline.checked_duration_since(now) { | ||||||
sleep(delay); | ||||||
} | ||||||
} | ||||||
|
||||||
// Note depends on clock_nanosleep (not supported on macos/ios/watchos/tvos) | ||||||
#[cfg(any( | ||||||
target_os = "freebsd", | ||||||
target_os = "netbsd", | ||||||
target_os = "linux", | ||||||
target_os = "android", | ||||||
target_os = "solaris", | ||||||
target_os = "illumos", | ||||||
))] | ||||||
pub fn sleep_until(deadline: crate::time::Instant) { | ||||||
let mut ts = deadline | ||||||
.into_inner() | ||||||
.into_timespec() | ||||||
.to_timespec() | ||||||
.expect("Timespec is narrower then libc::timespec thus conversion can't fail"); | ||||||
let ts_ptr = &mut ts as *mut _; | ||||||
|
||||||
// If we're awoken with a signal and the return value is -1 | ||||||
// clock_nanosleep needs to be called again. | ||||||
unsafe { | ||||||
while libc::clock_nanosleep(libc::CLOCK_MONOTONIC, libc::TIMER_ABSTIME, ts_ptr, ts_ptr) | ||||||
== -1 | ||||||
{ | ||||||
assert_eq!( | ||||||
os::errno(), | ||||||
libc::EINTR, | ||||||
"clock nanosleep should only return an error if interrupted" | ||||||
); | ||||||
} | ||||||
} | ||||||
} | ||||||
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. visionOS was added in #121419.
Suggested change
Same goes for the other cfgs. |
||||||
pub fn sleep_until(deadline: crate::time::Instant) { | ||||||
use super::time::Timespec; | ||||||
use core::mem::MaybeUninit; | ||||||
|
||||||
let Timespec { tv_sec, tv_nsec } = deadline.into_inner().into_timespec(); | ||||||
let nanos = (tv_sec as u64).saturating_mul(1_000_000_000).saturating_add(tv_nsec.0 as u64); | ||||||
|
||||||
let mut info = MaybeUninit::uninit(); | ||||||
unsafe { | ||||||
let ret = mach_timebase_info(info.as_mut_ptr()); | ||||||
assert_eq!(ret, KERN_SUCCESS); | ||||||
|
||||||
let info = info.assume_init(); | ||||||
let ticks = nanos * (info.denom as u64) / (info.numer as u64); | ||||||
|
||||||
mach_wait_until(ticks); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually check the return type of
Suggested change
|
||||||
assert_eq!(ret, KERN_SUCCESS); | ||||||
} | ||||||
} | ||||||
|
||||||
pub fn join(self) { | ||||||
unsafe { | ||||||
let ret = libc::pthread_join(self.id, ptr::null_mut()); | ||||||
|
@@ -283,6 +356,23 @@ impl Thread { | |||||
} | ||||||
} | ||||||
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] | ||||||
const KERN_SUCCESS: libc::c_int = 0; | ||||||
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] | ||||||
#[repr(C)] | ||||||
struct mach_timebase_info_type { | ||||||
numer: u32, | ||||||
denom: u32, | ||||||
} | ||||||
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios", target_os = "tvos", target_os = "watchos"))] | ||||||
extern "C" { | ||||||
fn mach_wait_until(deadline: u64) -> libc::c_int; | ||||||
fn mach_timebase_info(info: *mut mach_timebase_info_type) -> libc::c_int; | ||||||
|
||||||
} | ||||||
|
||||||
impl Drop for Thread { | ||||||
fn drop(&mut self) { | ||||||
let ret = unsafe { libc::pthread_detach(self.id) }; | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -879,8 +879,34 @@ pub fn sleep(dur: Duration) { | |
/// | ||
/// # Platform-specific behavior | ||
/// | ||
/// This function uses [`sleep`] internally, see its platform-specific behaviour. | ||
/// In most cases this function will an call OS specific function. Where that | ||
/// is not supported [`sleep`] is used. Those platforms are referred to as other | ||
/// in the table below. | ||
/// | ||
/// # Underlying System calls | ||
/// | ||
/// The following system calls are [currently] being used: | ||
/// | ||
/// | ||
/// | Platform | System call | | ||
/// |-----------|----------------------------------------------------------------------| | ||
/// | Linux | [clock_nanosleep] (Monotonic clock) | | ||
/// | BSD except OpenBSD | [clock_nanosleep] (Monotonic Clock)] | | ||
/// | Android | [clock_nanosleep] (Monotonic Clock)] | | ||
/// | Solaris | [clock_nanosleep] (Monotonic Clock)] | | ||
/// | Illumos | [clock_nanosleep] (Monotonic Clock)] | | ||
/// | Darwin | [mach_wait_until] | | ||
/// | WASI | [subscription_clock] | | ||
/// | Windows | [SetWaitableTimer] | | ||
/// | Other | `sleep_until` uses [`sleep`] and does not issue a syscall itself | | ||
/// | ||
/// [currently]: crate::io#platform-specific-behavior | ||
/// [clock_nanosleep]: https://linux.die.net/man/3/clock_nanosleep | ||
/// [subscription_clock]: https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#-subscription_clock-record | ||
/// [mach_wait_until]: https://developer.apple.com/library/archive/technotes/tn2169/_index.html | ||
/// [SetWaitableTimer]: https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-setwaitabletimer | ||
/// | ||
/// **Disclaimer:** These system calls might change over time. | ||
/// | ||
/// # Examples | ||
/// | ||
|
@@ -942,11 +968,7 @@ pub fn sleep(dur: Duration) { | |
/// ``` | ||
#[unstable(feature = "thread_sleep_until", issue = "113752")] | ||
pub fn sleep_until(deadline: Instant) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The section on platform-specific behaviour still needs updating. |
||
let now = Instant::now(); | ||
|
||
if let Some(delay) = deadline.checked_duration_since(now) { | ||
sleep(delay); | ||
} | ||
imp::Thread::sleep_until(deadline) | ||
} | ||
|
||
/// Used to ensure that `park` and `park_timeout` do not unwind, as that can | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add
target_os = "dragonfly"
,target_os = "hurd"
andtarget_os = "fuchsia"