Skip to content

Commit 193e6e3

Browse files
committed
adds specialized impl of sleep_until for unix and wasi
1 parent 3dbb4da commit 193e6e3

File tree

11 files changed

+140
-35
lines changed

11 files changed

+140
-35
lines changed

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ impl Thread {
7878
}
7979
}
8080

81+
pub fn sleep_until(deadline: Instant) {
82+
let now = Instant::now();
83+
84+
if let Some(delay) = deadline.checked_duration_since(now) {
85+
sleep(delay);
86+
}
87+
}
88+
8189
pub fn join(self) {
8290
unsafe {
8391
let _ = abi::join(self.tid);

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,14 @@ impl Thread {
209209
}
210210
}
211211

212+
pub fn sleep_until(deadline: Instant) {
213+
let now = Instant::now();
214+
215+
if let Some(delay) = deadline.checked_duration_since(now) {
216+
sleep(delay);
217+
}
218+
}
219+
212220
pub fn join(self) {
213221
// Safety: `ThreadInner` is alive at this point
214222
let inner = unsafe { self.p_inner.as_ref() };

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,14 @@ impl Thread {
137137
usercalls::wait_timeout(0, dur, || true);
138138
}
139139

140+
pub fn sleep_until(deadline: Instant) {
141+
let now = Instant::now();
142+
143+
if let Some(delay) = deadline.checked_duration_since(now) {
144+
sleep(delay);
145+
}
146+
}
147+
140148
pub fn join(self) {
141149
self.0.wait();
142150
}

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

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,54 @@ impl Thread {
265265
}
266266
}
267267

268+
#[cfg(not(any(
269+
target_os = "freebsd",
270+
target_os = "netbsd",
271+
target_os = "linux",
272+
target_os = "android",
273+
target_os = "solaris",
274+
target_os = "illumos",
275+
)))]
276+
pub fn sleep_until(deadline: Instant) {
277+
let now = Instant::now();
278+
279+
if let Some(delay) = deadline.checked_duration_since(now) {
280+
sleep(delay);
281+
}
282+
}
283+
284+
// Note depends on clock_nanosleep (not supported on macos/ios/watchos/tvos)
285+
#[cfg(any(
286+
target_os = "freebsd",
287+
target_os = "netbsd",
288+
target_os = "linux",
289+
target_os = "android",
290+
target_os = "solaris",
291+
target_os = "illumos",
292+
))]
293+
pub fn sleep_until(deadline: crate::time::Instant) {
294+
let mut ts = deadline
295+
.into_inner()
296+
.into_timespec()
297+
.to_timespec()
298+
.expect("Timespec is narrower then libc::timespec thus conversion can't fail");
299+
let ts_ptr = &mut ts as *mut _;
300+
301+
// If we're awoken with a signal and the return value is -1
302+
// clock_nanosleep needs to be called again.
303+
unsafe {
304+
while libc::clock_nanosleep(libc::CLOCK_MONOTONIC, libc::TIMER_ABSTIME, ts_ptr, ts_ptr)
305+
== -1
306+
{
307+
assert_eq!(
308+
os::errno(),
309+
libc::EINTR,
310+
"clock nanosleep should only return an error if interrupted"
311+
);
312+
}
313+
}
314+
}
315+
268316
pub fn join(self) {
269317
unsafe {
270318
let ret = libc::pthread_join(self.id, ptr::null_mut());

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,10 @@ impl Instant {
318318
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
319319
Some(Instant { t: self.t.checked_sub_duration(other)? })
320320
}
321+
322+
pub(in crate::sys::unix) fn into_timespec(self) -> Timespec {
323+
self.t
324+
}
321325
}
322326

323327
impl fmt::Debug for Instant {

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

Lines changed: 39 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::io;
33
use crate::mem;
44
use crate::num::NonZeroUsize;
55
use crate::sys::unsupported;
6-
use crate::time::Duration;
6+
use crate::time::{Duration, Instant};
77

88
cfg_if::cfg_if! {
99
if #[cfg(target_feature = "atomics")] {
@@ -138,35 +138,18 @@ impl Thread {
138138
let nanos = dur.as_nanos();
139139
assert!(nanos <= u64::MAX as u128);
140140

141-
const USERDATA: wasi::Userdata = 0x0123_45678;
142-
143-
let clock = wasi::SubscriptionClock {
144-
id: wasi::CLOCKID_MONOTONIC,
145-
timeout: nanos as u64,
146-
precision: 0,
147-
flags: 0,
148-
};
149-
150-
let in_ = wasi::Subscription {
151-
userdata: USERDATA,
152-
u: wasi::SubscriptionU { tag: 0, u: wasi::SubscriptionUU { clock } },
153-
};
154-
unsafe {
155-
let mut event: wasi::Event = mem::zeroed();
156-
let res = wasi::poll_oneoff(&in_, &mut event, 1);
157-
match (res, event) {
158-
(
159-
Ok(1),
160-
wasi::Event {
161-
userdata: USERDATA,
162-
error: wasi::ERRNO_SUCCESS,
163-
type_: wasi::EVENTTYPE_CLOCK,
164-
..
165-
},
166-
) => {}
167-
_ => panic!("thread::sleep(): unexpected result of poll_oneoff"),
168-
}
169-
}
141+
sleep_with(nanos as u64, wasi::CLOCKID_MONOTONIC, 0);
142+
}
143+
144+
pub fn sleep_until(deadline: Instant) {
145+
let nanos = deadline.into_inner().into_inner().as_nanos();
146+
assert!(nanos <= u64::MAX as u128);
147+
148+
sleep_with(
149+
nanos as u64,
150+
wasi::CLOCKID_MONOTONIC,
151+
wasi::SUBCLOCKFLAGS_SUBSCRIPTION_CLOCK_ABSTIME,
152+
);
170153
}
171154

172155
pub fn join(self) {
@@ -186,6 +169,32 @@ impl Thread {
186169
}
187170
}
188171

172+
fn sleep_with(nanos: u64, clock_id: wasi::Clockid, flags: u16) {
173+
let clock = wasi::SubscriptionClock { id: clock_id, timeout: nanos, precision: 0, flags };
174+
175+
const USERDATA: wasi::Userdata = 0x0123_45678;
176+
let in_ = wasi::Subscription {
177+
userdata: USERDATA,
178+
u: wasi::SubscriptionU { tag: 0, u: wasi::SubscriptionUU { clock } },
179+
};
180+
unsafe {
181+
let mut event: wasi::Event = mem::zeroed();
182+
let res = wasi::poll_oneoff(&in_, &mut event, 1);
183+
match (res, event) {
184+
(
185+
Ok(1),
186+
wasi::Event {
187+
userdata: USERDATA,
188+
error: wasi::ERRNO_SUCCESS,
189+
type_: wasi::EVENTTYPE_CLOCK,
190+
..
191+
},
192+
) => {}
193+
_ => panic!("thread::sleep(): unexpected result of poll_oneoff"),
194+
}
195+
}
196+
}
197+
189198
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
190199
unsupported()
191200
}

library/std/src/sys/wasi/time.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ impl Instant {
3636
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Instant> {
3737
Some(Instant(self.0.checked_sub(*other)?))
3838
}
39+
40+
pub(crate) fn into_inner(self) -> Duration {
41+
self.0
42+
}
3943
}
4044

4145
impl SystemTime {

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,14 @@ impl Thread {
101101
}
102102
}
103103

104+
pub fn sleep_until(deadline: Instant) {
105+
let now = Instant::now();
106+
107+
if let Some(delay) = deadline.checked_duration_since(now) {
108+
sleep(delay);
109+
}
110+
}
111+
104112
pub fn handle(&self) -> &Handle {
105113
&self.handle
106114
}

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,14 @@ impl Thread {
123123
}
124124
}
125125

126+
pub fn sleep_until(deadline: Instant) {
127+
let now = Instant::now();
128+
129+
if let Some(delay) = deadline.checked_duration_since(now) {
130+
sleep(delay);
131+
}
132+
}
133+
126134
pub fn join(self) {
127135
join_thread(self.tid).unwrap();
128136
}

library/std/src/thread/mod.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -943,11 +943,7 @@ pub fn sleep(dur: Duration) {
943943
/// ```
944944
#[unstable(feature = "thread_sleep_until", issue = "113752")]
945945
pub fn sleep_until(deadline: Instant) {
946-
let now = Instant::now();
947-
948-
if let Some(delay) = deadline.checked_duration_since(now) {
949-
sleep(delay);
950-
}
946+
imp::Thread::sleep_until(deadline)
951947
}
952948

953949
/// Used to ensure that `park` and `park_timeout` do not unwind, as that can

library/std/src/time.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,10 @@ impl Instant {
403403
pub fn checked_sub(&self, duration: Duration) -> Option<Instant> {
404404
self.0.checked_sub_duration(&duration).map(Instant)
405405
}
406+
407+
pub(crate) fn into_inner(self) -> time::Instant {
408+
self.0
409+
}
406410
}
407411

408412
#[stable(feature = "time2", since = "1.8.0")]

0 commit comments

Comments
 (0)