Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/kern Re-factor the code that computes the EVFILT_TIMER v...
details: https://anonhg.NetBSD.org/src/rev/5d1b2e82816c
branches: trunk
changeset: 1024376:5d1b2e82816c
user: thorpej <thorpej%NetBSD.org@localhost>
date: Thu Oct 21 01:11:21 2021 +0000
description:
Re-factor the code that computes the EVFILT_TIMER value into its own
function.
NFC.
diffstat:
sys/kern/kern_event.c | 194 +++++++++++++++++++++++++++++--------------------
1 files changed, 115 insertions(+), 79 deletions(-)
diffs (234 lines):
diff -r 535cdfa93ce3 -r 5d1b2e82816c sys/kern/kern_event.c
--- a/sys/kern/kern_event.c Thu Oct 21 00:56:52 2021 +0000
+++ b/sys/kern/kern_event.c Thu Oct 21 01:11:21 2021 +0000
@@ -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,6 +1153,97 @@
#define FILT_TIMER_NOSCHED ((uintptr_t)-1)
+static int
+filt_timercompute(struct kevent *kev, uintptr_t *tticksp)
+{
+ struct timespec ts;
+ uintptr_t tticks;
+
+ if (kev->fflags & ~(NOTE_TIMER_UNITMASK | NOTE_ABSTIME)) {
+ return EINVAL;
+ }
+
+ /*
+ * Convert the event 'data' to a timespec, then convert the
+ * timespec to callout ticks.
+ */
+ switch (kev->fflags & NOTE_TIMER_UNITMASK) {
+ case NOTE_SECONDS:
+ ts.tv_sec = kev->data;
+ ts.tv_nsec = 0;
+ break;
+
+ case NOTE_MSECONDS: /* == historical value 0 */
+ ts.tv_sec = kev->data / 1000;
+ ts.tv_nsec = (kev->data % 1000) * 1000000;
+ break;
+
+ case NOTE_USECONDS:
+ ts.tv_sec = kev->data / 1000000;
+ ts.tv_nsec = (kev->data % 1000000) * 1000;
+ break;
+
+ case NOTE_NSECONDS:
+ ts.tv_sec = kev->data / 1000000000;
+ ts.tv_nsec = kev->data % 1000000000;
+ break;
+
+ default:
+ return EINVAL;
+ }
+
+ if (kev->fflags & NOTE_ABSTIME) {
+ struct timespec deadline = ts;
+
+ /*
+ * Get current time.
+ *
+ * XXX This is CLOCK_REALTIME. There is no way to
+ * XXX specify CLOCK_MONOTONIC.
+ */
+ 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, <=)) {
+ tticks = FILT_TIMER_NOSCHED;
+ goto out;
+ }
+
+ /* Calculate how much time is left. */
+ timespecsub(&deadline, &ts, &ts);
+ } else {
+ /* EV_CLEAR automatically set for relative timers. */
+ kev->flags |= EV_CLEAR;
+ }
+
+ tticks = tstohz(&ts);
+
+ /* if the supplied value is under our resolution, use 1 tick */
+ if (tticks == 0) {
+ if (kev->data == 0)
+ return EINVAL;
+ tticks = 1;
+ } else if (tticks > INT_MAX) {
+ return EINVAL;
+ }
+
+ if ((kev->flags & EV_ONESHOT) != 0) {
+ /* Timer does not repeat. */
+ kev->data = FILT_TIMER_NOSCHED;
+ } else {
+ KASSERT((uintptr_t)tticks != FILT_TIMER_NOSCHED);
+ kev->data = tticks;
+ }
+
+ out:
+ *tticksp = tticks;
+
+ return 0;
+}
+
static void
filt_timerexpire(void *knx)
{
@@ -1175,82 +1266,18 @@
{
callout_t *calloutp;
struct kqueue *kq;
- struct timespec ts;
- int tticks, flags = 0;
-
- if (kn->kn_sfflags & ~(NOTE_TIMER_UNITMASK | NOTE_ABSTIME)) {
- return EINVAL;
- }
-
- /*
- * Convert the event 'data' to a timespec, then convert the
- * timespec to callout ticks.
- */
- switch (kn->kn_sfflags & NOTE_TIMER_UNITMASK) {
- case NOTE_SECONDS:
- ts.tv_sec = kn->kn_sdata;
- 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;
- break;
-
- case NOTE_USECONDS:
- ts.tv_sec = kn->kn_sdata / 1000000;
- ts.tv_nsec = (kn->kn_sdata % 1000000) * 1000;
- break;
-
- case NOTE_NSECONDS:
- ts.tv_sec = kn->kn_sdata / 1000000000;
- ts.tv_nsec = kn->kn_sdata % 1000000000;
- break;
-
- default:
- return EINVAL;
- }
+ uintptr_t tticks;
+ int error;
- if (kn->kn_sfflags & NOTE_ABSTIME) {
- struct timespec deadline = ts;
-
- /*
- * Get current time.
- *
- * XXX This is CLOCK_REALTIME. There is no way to
- * XXX specify CLOCK_MONOTONIC.
- */
- nanotime(&ts);
-
- /* If we're past the deadline, then the event will fire. */
- if (timespeccmp(&deadline, &ts, <=)) {
- kn->kn_data = 1;
- return 0;
- }
+ struct kevent kev = {
+ .flags = kn->kn_flags,
+ .fflags = kn->kn_sfflags,
+ .data = kn->kn_sdata,
+ };
- /* Calculate how much time is left. */
- timespecsub(&deadline, &ts, &ts);
- } else {
- /* EV_CLEAR automatically set for relative timers. */
- 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)
- return EINVAL;
- tticks = 1;
- }
-
- if ((kn->kn_flags & EV_ONESHOT) != 0 ||
- (kn->kn_sfflags & NOTE_ABSTIME) != 0) {
- /* Timer does not repeat. */
- kn->kn_sdata = FILT_TIMER_NOSCHED;
- } else {
- KASSERT((uintptr_t)tticks != FILT_TIMER_NOSCHED);
- kn->kn_sdata = tticks;
+ error = filt_timercompute(&kev, &tticks);
+ if (error) {
+ return error;
}
if (atomic_inc_uint_nv(&kq_ncallouts) >= kq_calloutmax ||
@@ -1262,12 +1289,21 @@
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;
+
+ 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);
- callout_reset(calloutp, tticks, filt_timerexpire, kn);
-
return (0);
}
Home |
Main Index |
Thread Index |
Old Index