diff options
author | cheloha <cheloha@cvs.openbsd.org> | 2019-07-01 16:52:03 +0000 |
---|---|---|
committer | cheloha <cheloha@cvs.openbsd.org> | 2019-07-01 16:52:03 +0000 |
commit | 20a0715b777196e6a209fa53966e0c744e9a06d6 (patch) | |
tree | dc87a88be6fd982108370a896b1807629e26973b /sys/kern | |
parent | bfb389930c282b20ada970197741f276fdd7d797 (diff) |
kevent(2): remove 24hr timeout limit
As with nanosleep(2), poll(2), and select(2), here we can chip away at
the timespec until it's empty. This lets us support the full range of
the timespec regardless of the kernel's HZ.
Update the manpage accordingly.
ok visa@
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_event.c | 73 |
1 files changed, 27 insertions, 46 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 8077bbb64b8..ad4a856e895 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_event.c,v 1.104 2019/05/04 14:52:45 mpi Exp $ */ +/* $OpenBSD: kern_event.c,v 1.105 2019/07/01 16:52:02 cheloha Exp $ */ /*- * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> @@ -55,7 +55,7 @@ #include <sys/timeout.h> int kqueue_scan(struct kqueue *kq, int maxevents, - struct kevent *ulistp, const struct timespec *timeout, + struct kevent *ulistp, struct timespec *timeout, struct proc *p, int *retval); int kqueue_read(struct file *, struct uio *, int); @@ -484,6 +484,7 @@ sys_kevent(struct proc *p, void *v, register_t *retval) struct kqueue *kq; struct file *fp; struct timespec ts; + struct timespec *tsp = NULL; int i, n, nerrors, error; struct kevent kev[KQ_NEVENTS]; @@ -503,7 +504,7 @@ sys_kevent(struct proc *p, void *v, register_t *retval) if (KTRPOINT(p, KTR_STRUCT)) ktrreltimespec(p, &ts); #endif - SCARG(uap, timeout) = &ts; + tsp = &ts; } kq = fp->f_data; @@ -550,7 +551,7 @@ sys_kevent(struct proc *p, void *v, register_t *retval) KQREF(kq); FRELE(fp, p); error = kqueue_scan(kq, SCARG(uap, nevents), SCARG(uap, eventlist), - SCARG(uap, timeout), p, &n); + tsp, p, &n); KQRELE(kq); *retval = n; return (error); @@ -696,10 +697,10 @@ done: int kqueue_scan(struct kqueue *kq, int maxevents, struct kevent *ulistp, - const struct timespec *tsp, struct proc *p, int *retval) + struct timespec *tsp, struct proc *p, int *retval) { struct kevent *kevp; - struct timespec ats, rts, tts; + struct timespec elapsed, start, stop; struct knote *kn, marker; int s, count, timeout, nkev = 0, error = 0; struct kevent kev[KQ_NEVENTS]; @@ -708,41 +709,12 @@ kqueue_scan(struct kqueue *kq, int maxevents, struct kevent *ulistp, if (count == 0) goto done; - if (tsp != NULL) { - ats = *tsp; - if (!timespecisset(&ats)) { - /* No timeout, just poll */ - timeout = -1; - goto start; - } - if (timespecfix(&ats)) { - error = EINVAL; - goto done; - } - - timeout = ats.tv_sec > 24 * 60 * 60 ? - 24 * 60 * 60 * hz : tstohz(&ats); - - getnanouptime(&rts); - timespecadd(&ats, &rts, &ats); - } else { - timespecclear(&ats); - timeout = 0; + if (tsp != NULL && (tsp->tv_sec < 0 || !timespecisvalid(tsp))) { + error = EINVAL; + goto done; } - goto start; retry: - if (timespecisset(&ats)) { - getnanouptime(&rts); - if (timespeccmp(&rts, &ats, >=)) - goto done; - tts = ats; - timespecsub(&tts, &rts, &tts); - timeout = tts.tv_sec > 24 * 60 * 60 ? - 24 * 60 * 60 * hz : tstohz(&tts); - } - -start: if (kq->kq_state & KQ_DYING) { error = EBADF; goto done; @@ -751,20 +723,29 @@ start: kevp = &kev[0]; s = splhigh(); if (kq->kq_count == 0) { - if (timeout < 0) { - error = EWOULDBLOCK; - } else { - kq->kq_state |= KQ_SLEEP; - error = tsleep(kq, PSOCK | PCATCH, "kqread", timeout); + if (tsp != NULL && !timespecisset(tsp)) { + splx(s); + error = 0; + goto done; + } + kq->kq_state |= KQ_SLEEP; + timeout = (tsp == NULL) ? 0 : tstohz(tsp); + if (tsp != NULL) + getnanouptime(&start); + error = tsleep(kq, PSOCK | PCATCH, "kqread", timeout); + if (tsp != NULL) { + getnanouptime(&stop); + timespecsub(&stop, &start, &elapsed); + timespecsub(tsp, &elapsed, tsp); + if (tsp->tv_sec < 0) + timespecclear(tsp); } splx(s); - if (error == 0) + if (error == 0 || error == EWOULDBLOCK) goto retry; /* don't restart after signals... */ if (error == ERESTART) error = EINTR; - else if (error == EWOULDBLOCK) - error = 0; goto done; } |