Skip to content

Commit 94817f8

Browse files
committed
Auto merge of #141829 - dvdsk:sleep_until_linux, r=cuviper
Specialize sleep_until implementation for unix (except mac) related tracking issue: #113752 Supersedes #118480 for the reasons see: #113752 (comment) Replaces the generic catch all implementation with target_os specific ones for: linux/netbsd/freebsd/android/solaris/illumos etc. Other platforms like wasi, macos/ios/tvos/watchos and windows will follow in later separate PR's (once this is merged).
2 parents 25face9 + dd0a1e6 commit 94817f8

File tree

15 files changed

+218
-25
lines changed

15 files changed

+218
-25
lines changed

library/std/src/sys/pal/hermit/thread.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use super::hermit_abi;
44
use crate::ffi::CStr;
55
use crate::mem::ManuallyDrop;
66
use crate::num::NonZero;
7-
use crate::time::Duration;
7+
use crate::time::{Duration, Instant};
88
use crate::{io, ptr};
99

1010
pub type Tid = hermit_abi::Tid;
@@ -86,6 +86,14 @@ impl Thread {
8686
}
8787
}
8888

89+
pub fn sleep_until(deadline: Instant) {
90+
let now = Instant::now();
91+
92+
if let Some(delay) = deadline.checked_duration_since(now) {
93+
Self::sleep(delay);
94+
}
95+
}
96+
8997
pub fn join(self) {
9098
unsafe {
9199
let _ = hermit_abi::join(self.tid);

library/std/src/sys/pal/itron/thread.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use crate::mem::ManuallyDrop;
1010
use crate::num::NonZero;
1111
use crate::ptr::NonNull;
1212
use crate::sync::atomic::{Atomic, AtomicUsize, Ordering};
13-
use crate::time::Duration;
13+
use crate::time::{Duration, Instant};
1414
use crate::{hint, io};
1515

1616
pub struct Thread {
@@ -205,6 +205,14 @@ impl Thread {
205205
}
206206
}
207207

208+
pub fn sleep_until(deadline: Instant) {
209+
let now = Instant::now();
210+
211+
if let Some(delay) = deadline.checked_duration_since(now) {
212+
Self::sleep(delay);
213+
}
214+
}
215+
208216
pub fn join(self) {
209217
// Safety: `ThreadInner` is alive at this point
210218
let inner = unsafe { self.p_inner.as_ref() };

library/std/src/sys/pal/sgx/thread.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use super::unsupported;
55
use crate::ffi::CStr;
66
use crate::io;
77
use crate::num::NonZero;
8-
use crate::time::Duration;
8+
use crate::time::{Duration, Instant};
99

1010
pub struct Thread(task_queue::JoinHandle);
1111

@@ -132,6 +132,14 @@ impl Thread {
132132
usercalls::wait_timeout(0, dur, || true);
133133
}
134134

135+
pub fn sleep_until(deadline: Instant) {
136+
let now = Instant::now();
137+
138+
if let Some(delay) = deadline.checked_duration_since(now) {
139+
Self::sleep(delay);
140+
}
141+
}
142+
135143
pub fn join(self) {
136144
self.0.wait();
137145
}

library/std/src/sys/pal/teeos/thread.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::ffi::CStr;
22
use crate::mem::{self, ManuallyDrop};
33
use crate::num::NonZero;
44
use crate::sys::os;
5-
use crate::time::Duration;
5+
use crate::time::{Duration, Instant};
66
use crate::{cmp, io, ptr};
77

88
pub const DEFAULT_MIN_STACK_SIZE: usize = 8 * 1024;
@@ -109,6 +109,14 @@ impl Thread {
109109
}
110110
}
111111

112+
pub fn sleep_until(deadline: Instant) {
113+
let now = Instant::now();
114+
115+
if let Some(delay) = deadline.checked_duration_since(now) {
116+
Self::sleep(delay);
117+
}
118+
}
119+
112120
/// must join, because no pthread_detach supported
113121
pub fn join(self) {
114122
let id = self.into_id();

library/std/src/sys/pal/uefi/thread.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::ffi::CStr;
33
use crate::io;
44
use crate::num::NonZero;
55
use crate::ptr::NonNull;
6-
use crate::time::Duration;
6+
use crate::time::{Duration, Instant};
77

88
pub struct Thread(!);
99

@@ -39,6 +39,14 @@ impl Thread {
3939
}
4040
}
4141

42+
pub fn sleep_until(deadline: Instant) {
43+
let now = Instant::now();
44+
45+
if let Some(delay) = deadline.checked_duration_since(now) {
46+
Self::sleep(delay);
47+
}
48+
}
49+
4250
pub fn join(self) {
4351
self.0
4452
}

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

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::sys::weak::dlsym;
66
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto",))]
77
use crate::sys::weak::weak;
88
use crate::sys::{os, stack_overflow};
9-
use crate::time::Duration;
9+
use crate::time::{Duration, Instant};
1010
use crate::{cmp, io, ptr};
1111
#[cfg(not(any(
1212
target_os = "l4re",
@@ -296,6 +296,75 @@ impl Thread {
296296
}
297297
}
298298

299+
// Any unix that has clock_nanosleep
300+
#[cfg(any(
301+
target_os = "freebsd",
302+
target_os = "netbsd",
303+
target_os = "linux",
304+
target_os = "android",
305+
target_os = "solaris",
306+
target_os = "illumos",
307+
target_os = "dragonfly",
308+
target_os = "hurd",
309+
target_os = "fuchsia",
310+
target_os = "vxworks",
311+
))]
312+
pub fn sleep_until(deadline: Instant) {
313+
let Some(ts) = deadline.into_inner().into_timespec().to_timespec() else {
314+
// The deadline is further in the future then can be passed to
315+
// clock_nanosleep. We have to use Self::sleep intead. This might
316+
// happen on 32 bit platforms, especially closer to 2038.
317+
let now = Instant::now();
318+
if let Some(delay) = deadline.checked_duration_since(now) {
319+
Self::sleep(delay);
320+
}
321+
return;
322+
};
323+
324+
unsafe {
325+
// When we get interrupted (res = EINTR) call clock_nanosleep again
326+
loop {
327+
let res = libc::clock_nanosleep(
328+
super::time::Instant::CLOCK_ID,
329+
libc::TIMER_ABSTIME,
330+
&ts,
331+
core::ptr::null_mut(), // not required with TIMER_ABSTIME
332+
);
333+
334+
if res == 0 {
335+
break;
336+
} else {
337+
assert_eq!(
338+
res,
339+
libc::EINTR,
340+
"timespec is in range,
341+
clockid is valid and kernel should support it"
342+
);
343+
}
344+
}
345+
}
346+
}
347+
348+
// Any unix that does not have clock_nanosleep
349+
#[cfg(not(any(
350+
target_os = "freebsd",
351+
target_os = "netbsd",
352+
target_os = "linux",
353+
target_os = "android",
354+
target_os = "solaris",
355+
target_os = "illumos",
356+
target_os = "dragonfly",
357+
target_os = "hurd",
358+
target_os = "fuchsia",
359+
target_os = "vxworks",
360+
)))]
361+
pub fn sleep_until(deadline: Instant) {
362+
let now = Instant::now();
363+
if let Some(delay) = deadline.checked_duration_since(now) {
364+
Self::sleep(delay);
365+
}
366+
}
367+
299368
pub fn join(self) {
300369
let id = self.into_id();
301370
let ret = unsafe { libc::pthread_join(id, ptr::null_mut()) };

library/std/src/sys/pal/unix/time.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,10 @@ pub struct Instant {
261261
}
262262

263263
impl Instant {
264+
#[cfg(target_vendor = "apple")]
265+
pub(crate) const CLOCK_ID: libc::clockid_t = libc::CLOCK_UPTIME_RAW;
266+
#[cfg(not(target_vendor = "apple"))]
267+
pub(crate) const CLOCK_ID: libc::clockid_t = libc::CLOCK_MONOTONIC;
264268
pub fn now() -> Instant {
265269
// https://www.manpagez.com/man/3/clock_gettime/
266270
//
@@ -273,11 +277,7 @@ impl Instant {
273277
//
274278
// Instant on macos was historically implemented using mach_absolute_time;
275279
// we preserve this value domain out of an abundance of caution.
276-
#[cfg(target_vendor = "apple")]
277-
const clock_id: libc::clockid_t = libc::CLOCK_UPTIME_RAW;
278-
#[cfg(not(target_vendor = "apple"))]
279-
const clock_id: libc::clockid_t = libc::CLOCK_MONOTONIC;
280-
Instant { t: Timespec::now(clock_id) }
280+
Instant { t: Timespec::now(Self::CLOCK_ID) }
281281
}
282282

283283
pub fn checked_sub_instant(&self, other: &Instant) -> Option<Duration> {
@@ -291,6 +291,14 @@ impl Instant {
291291
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
292292
Some(Instant { t: self.t.checked_sub_duration(other)? })
293293
}
294+
295+
#[cfg_attr(
296+
not(target_os = "linux"),
297+
allow(unused, reason = "needed by the `sleep_until` on some unix platforms")
298+
)]
299+
pub(crate) fn into_timespec(self) -> Timespec {
300+
self.t
301+
}
294302
}
295303

296304
impl fmt::Debug for Instant {

library/std/src/sys/pal/unsupported/thread.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::unsupported;
22
use crate::ffi::CStr;
33
use crate::io;
44
use crate::num::NonZero;
5-
use crate::time::Duration;
5+
use crate::time::{Duration, Instant};
66

77
pub struct Thread(!);
88

@@ -26,6 +26,10 @@ impl Thread {
2626
panic!("can't sleep");
2727
}
2828

29+
pub fn sleep_until(_deadline: Instant) {
30+
panic!("can't sleep");
31+
}
32+
2933
pub fn join(self) {
3034
self.0
3135
}

library/std/src/sys/pal/wasi/thread.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
use crate::ffi::CStr;
44
use crate::num::NonZero;
5-
use crate::time::Duration;
5+
use crate::time::{Duration, Instant};
66
use crate::{io, mem};
77

88
cfg_if::cfg_if! {
@@ -171,6 +171,14 @@ impl Thread {
171171
}
172172
}
173173

174+
pub fn sleep_until(deadline: Instant) {
175+
let now = Instant::now();
176+
177+
if let Some(delay) = deadline.checked_duration_since(now) {
178+
Self::sleep(delay);
179+
}
180+
}
181+
174182
pub fn join(self) {
175183
cfg_if::cfg_if! {
176184
if #[cfg(target_feature = "atomics")] {

library/std/src/sys/pal/wasm/atomics/thread.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::ffi::CStr;
22
use crate::io;
33
use crate::num::NonZero;
44
use crate::sys::unsupported;
5-
use crate::time::Duration;
5+
use crate::time::{Duration, Instant};
66

77
pub struct Thread(!);
88

@@ -41,6 +41,14 @@ impl Thread {
4141
}
4242
}
4343

44+
pub fn sleep_until(deadline: Instant) {
45+
let now = Instant::now();
46+
47+
if let Some(delay) = deadline.checked_duration_since(now) {
48+
Self::sleep(delay);
49+
}
50+
}
51+
4452
pub fn join(self) {}
4553
}
4654

library/std/src/sys/pal/windows/thread.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::os::windows::io::{AsRawHandle, HandleOrNull};
88
use crate::sys::handle::Handle;
99
use crate::sys::{c, stack_overflow};
1010
use crate::sys_common::FromInner;
11-
use crate::time::Duration;
11+
use crate::time::{Duration, Instant};
1212
use crate::{io, ptr};
1313

1414
pub const DEFAULT_MIN_STACK_SIZE: usize = 2 * 1024 * 1024;
@@ -106,6 +106,14 @@ impl Thread {
106106
}
107107
}
108108

109+
pub fn sleep_until(deadline: Instant) {
110+
let now = Instant::now();
111+
112+
if let Some(delay) = deadline.checked_duration_since(now) {
113+
Self::sleep(delay);
114+
}
115+
}
116+
109117
pub fn handle(&self) -> &Handle {
110118
&self.handle
111119
}

library/std/src/sys/pal/xous/thread.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::os::xous::ffi::{
88
map_memory, update_memory_flags,
99
};
1010
use crate::os::xous::services::{TicktimerScalar, ticktimer_server};
11-
use crate::time::Duration;
11+
use crate::time::{Duration, Instant};
1212

1313
pub struct Thread {
1414
tid: ThreadId,
@@ -128,6 +128,14 @@ impl Thread {
128128
}
129129
}
130130

131+
pub fn sleep_until(deadline: Instant) {
132+
let now = Instant::now();
133+
134+
if let Some(delay) = deadline.checked_duration_since(now) {
135+
Self::sleep(delay);
136+
}
137+
}
138+
131139
pub fn join(self) {
132140
join_thread(self.tid).unwrap();
133141
}

0 commit comments

Comments
 (0)