diff options
author | cheloha <cheloha@cvs.openbsd.org> | 2018-12-31 18:54:01 +0000 |
---|---|---|
committer | cheloha <cheloha@cvs.openbsd.org> | 2018-12-31 18:54:01 +0000 |
commit | 52d52069eefa32868f5c64d3f02cc8f4e55975fe (patch) | |
tree | f3ed9a1e00d4a5c5275ca961a70884fe973c56d5 | |
parent | ecfb99b9f02fa8472d59ce2c3363c84ad6fc5255 (diff) |
nanosleep: loop tsleep(9) to ensure coverage of the full timeout range.
tsleep(9)'s maximum timeout shrinks as HZ grows, so this ensures we do
not return early from longer timeouts on alpha or on custom kernels.
POSIX says you cannot return early unless a signal is delivered, so
this makes us more compliant with the standard.
While here, remove the 100 million second upper bound. It is an
artifact from itimerfix() and it serves no discernible purpose.
ok tedu@ visa@
-rw-r--r-- | lib/libc/sys/nanosleep.2 | 9 | ||||
-rw-r--r-- | sys/kern/kern_time.c | 23 |
2 files changed, 18 insertions, 14 deletions
diff --git a/lib/libc/sys/nanosleep.2 b/lib/libc/sys/nanosleep.2 index 062597e4163..63e4e4e365b 100644 --- a/lib/libc/sys/nanosleep.2 +++ b/lib/libc/sys/nanosleep.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: nanosleep.2,v 1.15 2015/05/31 23:54:25 schwarze Exp $ +.\" $OpenBSD: nanosleep.2,v 1.16 2018/12/31 18:54:00 cheloha Exp $ .\" $NetBSD: nanosleep.2,v 1.1 1997/04/17 18:12:02 jtc Exp $ .\" .\" Copyright (c) 1986, 1991, 1993 @@ -30,7 +30,7 @@ .\" .\" @(#)sleep.3 8.1 (Berkeley) 6/4/93 .\" -.Dd $Mdocdate: May 31 2015 $ +.Dd $Mdocdate: December 31 2018 $ .Dt NANOSLEEP 2 .Os .Sh NAME @@ -76,8 +76,9 @@ to the corresponding value. was interrupted by the delivery of a signal. .It Bq Er EINVAL .Fa timeout -specified a nanosecond value less than zero or greater than 1000 million, -or a second value less than zero or greater than 100 million. +specified a nanosecond value less than zero or greater than or equal to +1000 million, +or a second value less than zero. .It Bq Er EFAULT Either .Fa timeout diff --git a/sys/kern/kern_time.c b/sys/kern/kern_time.c index c9e54fb141b..1e40e8ccd84 100644 --- a/sys/kern/kern_time.c +++ b/sys/kern/kern_time.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_time.c,v 1.104 2018/12/29 19:02:30 cheloha Exp $ */ +/* $OpenBSD: kern_time.c,v 1.105 2018/12/31 18:54:00 cheloha Exp $ */ /* $NetBSD: kern_time.c,v 1.20 1996/02/18 11:57:06 fvdl Exp $ */ /* @@ -281,26 +281,29 @@ sys_nanosleep(struct proc *p, void *v, register_t *retval) } #endif - if (request.tv_sec > 100000000 || timespecfix(&request)) + if (request.tv_sec < 0 || request.tv_nsec < 0 || + request.tv_nsec >= 1000000000) return (EINVAL); - if (rmtp) + do { getnanouptime(&start); + error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", + MAX(1, tstohz(&request))); + getnanouptime(&stop); + timespecsub(&stop, &start, &elapsed); + timespecsub(&request, &elapsed, &request); + if (error != EWOULDBLOCK) + break; + } while (request.tv_sec >= 0 && timespecisset(&request)); - error = tsleep(&nanowait, PWAIT | PCATCH, "nanosleep", - MAX(1, tstohz(&request))); if (error == ERESTART) error = EINTR; if (error == EWOULDBLOCK) error = 0; if (rmtp) { - getnanouptime(&stop); - memset(&remainder, 0, sizeof(remainder)); - timespecsub(&stop, &start, &elapsed); - timespecsub(&request, &elapsed, &remainder); - + remainder = request; if (remainder.tv_sec < 0) timespecclear(&remainder); |