native: Move from usleep() to nanosleep()

Using nanosleep() allows us to gracefully recover from EINTR because on error it
fills in the second parameter with the remaining time to sleep.

Closes #12689
This commit is contained in:
Alex Crichton 2014-03-04 17:40:45 -08:00
parent 8334dd445f
commit d8bd8de82e
3 changed files with 22 additions and 6 deletions

View file

@ -218,8 +218,15 @@ impl Timer {
}
pub fn sleep(ms: u64) {
// FIXME: this can fail because of EINTR, what do do?
let _ = unsafe { libc::usleep((ms * 1000) as libc::c_uint) };
let mut to_sleep = libc::timespec {
tv_sec: (ms / 1000) as libc::time_t,
tv_nsec: ((ms % 1000) * 1000000) as libc::c_long,
};
while unsafe { libc::nanosleep(&to_sleep, &mut to_sleep) } != 0 {
if os::errno() as int != libc::EINTR as int {
fail!("failed to sleep, but not because of EINTR?");
}
}
}
fn inner(&mut self) -> ~Inner {

View file

@ -23,8 +23,8 @@
//! why).
//!
//! As with timer_other, timers just using sleep() do not use the timerfd at
//! all. They remove the timerfd from the worker thread and then invoke usleep()
//! to block the calling thread.
//! all. They remove the timerfd from the worker thread and then invoke
//! nanosleep() to block the calling thread.
//!
//! As with timer_other, all units in this file are in units of millseconds.
@ -183,8 +183,15 @@ impl Timer {
}
pub fn sleep(ms: u64) {
// FIXME: this can fail because of EINTR, what do do?
let _ = unsafe { libc::usleep((ms * 1000) as libc::c_uint) };
let mut to_sleep = libc::timespec {
tv_sec: (ms / 1000) as libc::time_t,
tv_nsec: ((ms % 1000) * 1000000) as libc::c_long,
};
while unsafe { libc::nanosleep(&to_sleep, &mut to_sleep) } != 0 {
if os::errno() as int != libc::EINTR as int {
fail!("failed to sleep, but not because of EINTR?");
}
}
}
fn remove(&mut self) {

View file

@ -3682,6 +3682,7 @@ pub mod funcs {
use libc::types::common::c95::c_void;
use libc::types::os::arch::c95::{c_char, c_int, c_long, c_uint};
use libc::types::os::arch::c95::{size_t};
use libc::types::os::common::posix01::timespec;
use libc::types::os::arch::posix01::utimbuf;
use libc::types::os::arch::posix88::{gid_t, off_t, pid_t};
use libc::types::os::arch::posix88::{ssize_t, uid_t};
@ -3731,6 +3732,7 @@ pub mod funcs {
pub fn setuid(uid: uid_t) -> c_int;
pub fn sleep(secs: c_uint) -> c_uint;
pub fn usleep(secs: c_uint) -> c_int;
pub fn nanosleep(rqtp: *timespec, rmtp: *mut timespec) -> c_int;
pub fn sysconf(name: c_int) -> c_long;
pub fn tcgetpgrp(fd: c_int) -> pid_t;
pub fn ttyname(fd: c_int) -> *c_char;