Module Name: src
Committed By: thorpej
Date: Thu Oct 21 01:11:21 UTC 2021
Modified Files:
src/sys/kern: kern_event.c
Log Message:
Re-factor the code that computes the EVFILT_TIMER value into its own
function.
NFC.
To generate a diff of this commit:
cvs rdiff -u -r1.133 -r1.134 src/sys/kern/kern_event.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/kern/kern_event.c
diff -u src/sys/kern/kern_event.c:1.133 src/sys/kern/kern_event.c:1.134
--- src/sys/kern/kern_event.c:1.133 Thu Oct 21 00:54:15 2021
+++ src/sys/kern/kern_event.c Thu Oct 21 01:11:21 2021
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_event.c,v 1.133 2021/10/21 00:54:15 thorpej Exp $ */
+/* $NetBSD: kern_event.c,v 1.134 2021/10/21 01:11:21 thorpej Exp $ */
/*-
* Copyright (c) 2008, 2009, 2021 The NetBSD Foundation, Inc.
@@ -63,7 +63,7 @@
#endif /* _KERNEL_OPT */
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.133 2021/10/21 00:54:15 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.134 2021/10/21 01:11:21 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -1153,32 +1153,13 @@ knote_proc_exit(struct proc *p)
#define FILT_TIMER_NOSCHED ((uintptr_t)-1)
-static void
-filt_timerexpire(void *knx)
-{
- struct knote *kn = knx;
- struct kqueue *kq = kn->kn_kq;
-
- mutex_spin_enter(&kq->kq_lock);
- kn->kn_data++;
- knote_activate_locked(kn);
- if (kn->kn_sdata != FILT_TIMER_NOSCHED) {
- KASSERT(kn->kn_sdata > 0 && kn->kn_sdata <= INT_MAX);
- callout_schedule((callout_t *)kn->kn_hook,
- (int)kn->kn_sdata);
- }
- mutex_spin_exit(&kq->kq_lock);
-}
-
static int
-filt_timerattach(struct knote *kn)
+filt_timercompute(struct kevent *kev, uintptr_t *tticksp)
{
- callout_t *calloutp;
- struct kqueue *kq;
struct timespec ts;
- int tticks, flags = 0;
+ uintptr_t tticks;
- if (kn->kn_sfflags & ~(NOTE_TIMER_UNITMASK | NOTE_ABSTIME)) {
+ if (kev->fflags & ~(NOTE_TIMER_UNITMASK | NOTE_ABSTIME)) {
return EINVAL;
}
@@ -1186,32 +1167,32 @@ filt_timerattach(struct knote *kn)
* Convert the event 'data' to a timespec, then convert the
* timespec to callout ticks.
*/
- switch (kn->kn_sfflags & NOTE_TIMER_UNITMASK) {
+ switch (kev->fflags & NOTE_TIMER_UNITMASK) {
case NOTE_SECONDS:
- ts.tv_sec = kn->kn_sdata;
+ ts.tv_sec = kev->data;
ts.tv_nsec = 0;
break;
case NOTE_MSECONDS: /* == historical value 0 */
- ts.tv_sec = kn->kn_sdata / 1000;
- ts.tv_nsec = (kn->kn_sdata % 1000) * 1000000;
+ ts.tv_sec = kev->data / 1000;
+ ts.tv_nsec = (kev->data % 1000) * 1000000;
break;
case NOTE_USECONDS:
- ts.tv_sec = kn->kn_sdata / 1000000;
- ts.tv_nsec = (kn->kn_sdata % 1000000) * 1000;
+ ts.tv_sec = kev->data / 1000000;
+ ts.tv_nsec = (kev->data % 1000000) * 1000;
break;
case NOTE_NSECONDS:
- ts.tv_sec = kn->kn_sdata / 1000000000;
- ts.tv_nsec = kn->kn_sdata % 1000000000;
+ ts.tv_sec = kev->data / 1000000000;
+ ts.tv_nsec = kev->data % 1000000000;
break;
default:
return EINVAL;
}
- if (kn->kn_sfflags & NOTE_ABSTIME) {
+ if (kev->fflags & NOTE_ABSTIME) {
struct timespec deadline = ts;
/*
@@ -1222,35 +1203,81 @@ filt_timerattach(struct knote *kn)
*/
nanotime(&ts);
+ /* Absolute timers do not repeat. */
+ kev->data = FILT_TIMER_NOSCHED;
+
/* If we're past the deadline, then the event will fire. */
if (timespeccmp(&deadline, &ts, <=)) {
- kn->kn_data = 1;
- return 0;
+ tticks = FILT_TIMER_NOSCHED;
+ goto out;
}
/* Calculate how much time is left. */
timespecsub(&deadline, &ts, &ts);
} else {
/* EV_CLEAR automatically set for relative timers. */
- flags |= EV_CLEAR;
+ kev->flags |= EV_CLEAR;
}
tticks = tstohz(&ts);
/* if the supplied value is under our resolution, use 1 tick */
if (tticks == 0) {
- if (kn->kn_sdata == 0)
+ if (kev->data == 0)
return EINVAL;
tticks = 1;
+ } else if (tticks > INT_MAX) {
+ return EINVAL;
}
- if ((kn->kn_flags & EV_ONESHOT) != 0 ||
- (kn->kn_sfflags & NOTE_ABSTIME) != 0) {
+ if ((kev->flags & EV_ONESHOT) != 0) {
/* Timer does not repeat. */
- kn->kn_sdata = FILT_TIMER_NOSCHED;
+ kev->data = FILT_TIMER_NOSCHED;
} else {
KASSERT((uintptr_t)tticks != FILT_TIMER_NOSCHED);
- kn->kn_sdata = tticks;
+ kev->data = tticks;
+ }
+
+ out:
+ *tticksp = tticks;
+
+ return 0;
+}
+
+static void
+filt_timerexpire(void *knx)
+{
+ struct knote *kn = knx;
+ struct kqueue *kq = kn->kn_kq;
+
+ mutex_spin_enter(&kq->kq_lock);
+ kn->kn_data++;
+ knote_activate_locked(kn);
+ if (kn->kn_sdata != FILT_TIMER_NOSCHED) {
+ KASSERT(kn->kn_sdata > 0 && kn->kn_sdata <= INT_MAX);
+ callout_schedule((callout_t *)kn->kn_hook,
+ (int)kn->kn_sdata);
+ }
+ mutex_spin_exit(&kq->kq_lock);
+}
+
+static int
+filt_timerattach(struct knote *kn)
+{
+ callout_t *calloutp;
+ struct kqueue *kq;
+ uintptr_t tticks;
+ int error;
+
+ struct kevent kev = {
+ .flags = kn->kn_flags,
+ .fflags = kn->kn_sfflags,
+ .data = kn->kn_sdata,
+ };
+
+ error = filt_timercompute(&kev, &tticks);
+ if (error) {
+ return error;
}
if (atomic_inc_uint_nv(&kq_ncallouts) >= kq_calloutmax ||
@@ -1262,11 +1289,20 @@ filt_timerattach(struct knote *kn)
kq = kn->kn_kq;
mutex_spin_enter(&kq->kq_lock);
- kn->kn_flags |= flags;
+
+ kn->kn_sdata = kev.data;
+ kn->kn_flags = kev.flags;
+ KASSERT(kn->kn_sfflags == kev.fflags);
kn->kn_hook = calloutp;
- mutex_spin_exit(&kq->kq_lock);
- callout_reset(calloutp, tticks, filt_timerexpire, kn);
+ if (__predict_false(tticks == FILT_TIMER_NOSCHED)) {
+ kn->kn_data = 1;
+ } else {
+ KASSERT(tticks <= INT_MAX);
+ callout_reset(calloutp, (int)tticks, filt_timerexpire, kn);
+ }
+
+ mutex_spin_exit(&kq->kq_lock);
return (0);
}