diff options
author | Visa Hankala <visa@cvs.openbsd.org> | 2021-04-22 15:30:13 +0000 |
---|---|---|
committer | Visa Hankala <visa@cvs.openbsd.org> | 2021-04-22 15:30:13 +0000 |
commit | 79f88e738b3623129ce0ee77334aa86da0f3395d (patch) | |
tree | 0764de65278b7bf71071e0182b8617bcf0951157 | |
parent | f1739218a01a21e7e86396f517a5af1f114d9ae4 (diff) |
kqueue: Make timer re-addition reset existing timer
When an existing EVFILT_TIMER filter is re-added, cancel the existing
timer and any pending event, and restart the timer using the new timeout
period. This makes the new timeout period take effect immediately and
matches the behaviour of FreeBSD. Previously, the new setting was
applied only after the existing timer expired.
The timer rescheduling is done by using an f_modify callback. The
reading of timer events is moved from f_event to f_process. f_event of
timer_filtops becomes redundant. Unlike most other event sources, timers
activate knotes directly without using a klist and knote(9).
OK mpi@
-rw-r--r-- | lib/libc/sys/kqueue.2 | 9 | ||||
-rw-r--r-- | sys/kern/kern_event.c | 48 |
2 files changed, 49 insertions, 8 deletions
diff --git a/lib/libc/sys/kqueue.2 b/lib/libc/sys/kqueue.2 index 3f4ccee24f6..08cef8fdc1f 100644 --- a/lib/libc/sys/kqueue.2 +++ b/lib/libc/sys/kqueue.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: kqueue.2,v 1.43 2020/11/14 10:16:15 jmc Exp $ +.\" $OpenBSD: kqueue.2,v 1.44 2021/04/22 15:30:12 visa Exp $ .\" .\" Copyright (c) 2000 Jonathan Lemon .\" All rights reserved. @@ -26,7 +26,7 @@ .\" .\" $FreeBSD: src/lib/libc/sys/kqueue.2,v 1.18 2001/02/14 08:48:35 guido Exp $ .\" -.Dd $Mdocdate: November 14 2020 $ +.Dd $Mdocdate: April 22 2021 $ .Dt KQUEUE 2 .Os .Sh NAME @@ -468,6 +468,11 @@ contains the number of times the timeout has expired since the last call to This filter automatically sets the .Dv EV_CLEAR flag internally. +.Pp +If an existing timer is re-added, the existing timer and related pending events +will be cancelled. +The timer will be re-started using the timeout period +.Fa data . .It Dv EVFILT_DEVICE Takes a descriptor as the identifier and the events to watch for in .Fa fflags , diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index fc26f2eba45..7f821a67ed7 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_event.c,v 1.162 2021/02/27 13:43:16 visa Exp $ */ +/* $OpenBSD: kern_event.c,v 1.163 2021/04/22 15:30:12 visa Exp $ */ /*- * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> @@ -135,7 +135,8 @@ int filt_fileattach(struct knote *kn); void filt_timerexpire(void *knx); int filt_timerattach(struct knote *kn); void filt_timerdetach(struct knote *kn); -int filt_timer(struct knote *kn, long hint); +int filt_timermodify(struct kevent *kev, struct knote *kn); +int filt_timerprocess(struct knote *kn, struct kevent *kev); void filt_seltruedetach(struct knote *kn); const struct filterops kqread_filtops = { @@ -163,7 +164,9 @@ const struct filterops timer_filtops = { .f_flags = 0, .f_attach = filt_timerattach, .f_detach = filt_timerdetach, - .f_event = filt_timer, + .f_event = NULL, + .f_modify = filt_timermodify, + .f_process = filt_timerprocess, }; struct pool knote_pool; @@ -444,15 +447,48 @@ filt_timerdetach(struct knote *kn) struct timeout *to; to = (struct timeout *)kn->kn_hook; - timeout_del(to); + timeout_del_barrier(to); free(to, M_KEVENT, sizeof(*to)); kq_ntimeouts--; } int -filt_timer(struct knote *kn, long hint) +filt_timermodify(struct kevent *kev, struct knote *kn) +{ + struct timeout *to = kn->kn_hook; + int s; + + /* Reset the timer. Any pending events are discarded. */ + + timeout_del_barrier(to); + + s = splhigh(); + if (kn->kn_status & KN_QUEUED) + knote_dequeue(kn); + kn->kn_status &= ~KN_ACTIVE; + splx(s); + + kn->kn_data = 0; + knote_modify(kev, kn); + /* Reinit timeout to invoke tick adjustment again. */ + timeout_set(to, filt_timerexpire, kn); + filt_timer_timeout_add(kn); + + return (0); +} + +int +filt_timerprocess(struct knote *kn, struct kevent *kev) { - return (kn->kn_data != 0); + int active, s; + + s = splsoftclock(); + active = (kn->kn_data != 0); + if (active) + knote_submit(kn, kev); + splx(s); + + return (active); } |