From 762d7722438ce9a7fb651868254beaeca46afceb Mon Sep 17 00:00:00 2001 From: kib Date: Sun, 1 Jan 2017 11:19:17 +0000 Subject: MFC r310554: Some optimizations for kqueue timers. --- sys/kern/kern_event.c | 52 +++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index f30b56b..9578536 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -631,23 +631,29 @@ timer2sbintime(intptr_t data, int flags) return (-1); } +struct kq_timer_cb_data { + struct callout c; + sbintime_t next; /* next timer event fires at */ + sbintime_t to; /* precalculated timer period */ +}; + static void filt_timerexpire(void *knx) { - struct callout *calloutp; struct knote *kn; + struct kq_timer_cb_data *kc; kn = knx; kn->kn_data++; KNOTE_ACTIVATE(kn, 0); /* XXX - handle locking */ - if ((kn->kn_flags & EV_ONESHOT) != EV_ONESHOT) { - calloutp = (struct callout *)kn->kn_hook; - *kn->kn_ptr.p_nexttime += timer2sbintime(kn->kn_sdata, - kn->kn_sfflags); - callout_reset_sbt_on(calloutp, *kn->kn_ptr.p_nexttime, 0, - filt_timerexpire, kn, PCPU_GET(cpuid), C_ABSOLUTE); - } + if ((kn->kn_flags & EV_ONESHOT) != 0) + return; + + kc = kn->kn_ptr.p_v; + kc->next += kc->to; + callout_reset_sbt_on(&kc->c, kc->next, 0, filt_timerexpire, kn, + PCPU_GET(cpuid), C_ABSOLUTE); } /* @@ -656,16 +662,16 @@ filt_timerexpire(void *knx) static int filt_timerattach(struct knote *kn) { - struct callout *calloutp; + struct kq_timer_cb_data *kc; sbintime_t to; unsigned int ncallouts; - if ((intptr_t)kn->kn_sdata < 0) + if (kn->kn_sdata < 0) return (EINVAL); - if ((intptr_t)kn->kn_sdata == 0 && (kn->kn_flags & EV_ONESHOT) == 0) + if (kn->kn_sdata == 0 && (kn->kn_flags & EV_ONESHOT) == 0) kn->kn_sdata = 1; /* Only precision unit are supported in flags so far */ - if (kn->kn_sfflags & ~NOTE_TIMER_PRECMASK) + if ((kn->kn_sfflags & ~NOTE_TIMER_PRECMASK) != 0) return (EINVAL); to = timer2sbintime(kn->kn_sdata, kn->kn_sfflags); @@ -680,13 +686,12 @@ filt_timerattach(struct knote *kn) kn->kn_flags |= EV_CLEAR; /* automatically set */ kn->kn_status &= ~KN_DETACHED; /* knlist_add clears it */ - kn->kn_ptr.p_nexttime = malloc(sizeof(sbintime_t), M_KQUEUE, M_WAITOK); - calloutp = malloc(sizeof(*calloutp), M_KQUEUE, M_WAITOK); - callout_init(calloutp, 1); - kn->kn_hook = calloutp; - *kn->kn_ptr.p_nexttime = to + sbinuptime(); - callout_reset_sbt_on(calloutp, *kn->kn_ptr.p_nexttime, 0, - filt_timerexpire, kn, PCPU_GET(cpuid), C_ABSOLUTE); + kn->kn_ptr.p_v = kc = malloc(sizeof(*kc), M_KQUEUE, M_WAITOK); + callout_init(&kc->c, 1); + kc->next = to + sbinuptime(); + kc->to = to; + callout_reset_sbt_on(&kc->c, kc->next, 0, filt_timerexpire, kn, + PCPU_GET(cpuid), C_ABSOLUTE); return (0); } @@ -694,13 +699,12 @@ filt_timerattach(struct knote *kn) static void filt_timerdetach(struct knote *kn) { - struct callout *calloutp; + struct kq_timer_cb_data *kc; unsigned int old; - calloutp = (struct callout *)kn->kn_hook; - callout_drain(calloutp); - free(calloutp, M_KQUEUE); - free(kn->kn_ptr.p_nexttime, M_KQUEUE); + kc = kn->kn_ptr.p_v; + callout_drain(&kc->c); + free(kc, M_KQUEUE); old = atomic_fetchadd_int(&kq_ncallouts, -1); KASSERT(old > 0, ("Number of callouts cannot become negative")); kn->kn_status |= KN_DETACHED; /* knlist_remove sets it */ -- cgit v1.1