summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcheloha <cheloha@cvs.openbsd.org>2018-12-31 18:54:01 +0000
committercheloha <cheloha@cvs.openbsd.org>2018-12-31 18:54:01 +0000
commit52d52069eefa32868f5c64d3f02cc8f4e55975fe (patch)
treef3ed9a1e00d4a5c5275ca961a70884fe973c56d5
parentecfb99b9f02fa8472d59ce2c3363c84ad6fc5255 (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.29
-rw-r--r--sys/kern/kern_time.c23
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);