Merge branch 'sleep-intr' into 'master'
Make nanosleep and sleep handle interrupts correctly, plus fix alarm See merge request redox-os/relibc!605
This commit is contained in:
@@ -84,11 +84,13 @@ pub extern "C" fn alarm(seconds: c_uint) -> c_uint {
|
||||
},
|
||||
..Default::default()
|
||||
};
|
||||
let mut otimer = sys_time::itimerval::default();
|
||||
|
||||
let errno_backup = platform::ERRNO.get();
|
||||
let secs = if unsafe { sys_time::setitimer(sys_time::ITIMER_REAL, &timer, &mut timer) } < 0 {
|
||||
let secs = if unsafe { sys_time::setitimer(sys_time::ITIMER_REAL, &timer, &mut otimer) } < 0 {
|
||||
0
|
||||
} else {
|
||||
timer.it_value.tv_sec as c_uint + if timer.it_value.tv_usec > 0 { 1 } else { 0 }
|
||||
otimer.it_value.tv_sec as c_uint + if otimer.it_value.tv_usec > 0 { 1 } else { 0 }
|
||||
};
|
||||
platform::ERRNO.set(errno_backup);
|
||||
|
||||
@@ -788,9 +790,18 @@ pub extern "C" fn sleep(seconds: c_uint) -> c_uint {
|
||||
tv_sec: seconds as time_t,
|
||||
tv_nsec: 0,
|
||||
};
|
||||
let rmtp = ptr::null_mut();
|
||||
unsafe { Sys::nanosleep(&rqtp, rmtp).map(|()| 0).or_minus_one_errno() };
|
||||
0
|
||||
let mut rmtp = timespec {
|
||||
tv_sec: 0,
|
||||
tv_nsec: 0,
|
||||
};
|
||||
|
||||
// If sleep() returns because the requested time has elapsed, the value returned shall be 0.
|
||||
// If sleep() returns due to delivery of a signal, the return value shall be the "unslept" amount
|
||||
// (the requested time minus the time actually slept) in seconds.
|
||||
match unsafe { Sys::nanosleep(&rqtp, &mut rmtp) } {
|
||||
Err(Errno(EINTR)) => rmtp.tv_sec as c_uint,
|
||||
r => 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
||||
@@ -18,8 +18,8 @@ use crate::{
|
||||
header::{
|
||||
dirent::dirent,
|
||||
errno::{
|
||||
EBADF, EBADFD, EBADR, EINVAL, EIO, ENAMETOOLONG, ENOENT, ENOMEM, ENOSYS, EOPNOTSUPP,
|
||||
EPERM, ERANGE,
|
||||
EBADF, EBADFD, EBADR, EINTR, EINVAL, EIO, ENAMETOOLONG, ENOENT, ENOMEM, ENOSYS,
|
||||
EOPNOTSUPP, EPERM, ERANGE,
|
||||
},
|
||||
fcntl, limits,
|
||||
sys_mman::{MAP_ANONYMOUS, MAP_FAILED, PROT_READ, PROT_WRITE},
|
||||
@@ -698,14 +698,19 @@ impl Pal for Sys {
|
||||
} else {
|
||||
redox_rmtp = unsafe { redox_timespec::from(&*rmtp) };
|
||||
}
|
||||
syscall::nanosleep(&redox_rqtp, &mut redox_rmtp)?;
|
||||
unsafe {
|
||||
if !rmtp.is_null() {
|
||||
(*rmtp).tv_sec = redox_rmtp.tv_sec as time_t;
|
||||
(*rmtp).tv_nsec = redox_rmtp.tv_nsec as c_long;
|
||||
match syscall::nanosleep(&redox_rqtp, &mut redox_rmtp) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(Error { errno: EINTR }) => {
|
||||
unsafe {
|
||||
if !rmtp.is_null() {
|
||||
(*rmtp).tv_sec = redox_rmtp.tv_sec as time_t;
|
||||
(*rmtp).tv_nsec = redox_rmtp.tv_nsec as c_long;
|
||||
}
|
||||
};
|
||||
Err(Errno(EINTR))
|
||||
}
|
||||
Err(Error { errno: e }) => Err(Errno(e)),
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn open(path: CStr, oflag: c_int, mode: mode_t) -> Result<c_int> {
|
||||
|
||||
+23
-1
@@ -1,14 +1,36 @@
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include "test_helpers.h"
|
||||
|
||||
int main(void) {
|
||||
int usleep(useconds_t);
|
||||
|
||||
void handler(int _s)
|
||||
{
|
||||
(void)_s;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// sleep has no error codes and doesn't set errno
|
||||
unsigned int unslept = sleep(2);
|
||||
printf("unslept: %u\n", unslept);
|
||||
|
||||
struct sigaction sa;
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = handler;
|
||||
sigaction(SIGALRM, &sa, NULL);
|
||||
alarm(2);
|
||||
|
||||
unslept = sleep(10);
|
||||
if (unslept < 7)
|
||||
{
|
||||
printf("after alarm, unslept too short: %u\n", unslept);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int us_status = usleep(1000);
|
||||
ERROR_IF(usleep, us_status, == -1);
|
||||
UNEXP_IF(usleep, us_status, != 0);
|
||||
|
||||
Reference in New Issue
Block a user