Author: kib
Date: Sun Dec 25 19:49:35 2016
New Revision: 310554
URL: https://svnweb.freebsd.org/changeset/base/310554

Log:
  Some optimizations for kqueue timers.
  
  There is no need to do two allocations per kqueue timer. Gather all
  data needed by the timer callout into the structure and allocate it at
  once.
  
  Use the structure to preserve the result of timer2sbintime(), to not
  perform repeated 64bit calculations in callout.
  
  Remove tautological casts.
  Remove now unused p_nexttime [1].
  
  Noted by:     markj [1]
  Reviewed by:  markj (previous version)
  Sponsored by: The FreeBSD Foundation
  MFC after:    1 week
  X-MFC note:   do not remove p_nexttime
  Differential revision:        https://reviews.freebsd.org/D8901

Modified:
  head/sys/kern/kern_event.c
  head/sys/sys/event.h

Modified: head/sys/kern/kern_event.c
==============================================================================
--- head/sys/kern/kern_event.c  Sun Dec 25 19:49:09 2016        (r310553)
+++ head/sys/kern/kern_event.c  Sun Dec 25 19:49:35 2016        (r310554)
@@ -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 */

Modified: head/sys/sys/event.h
==============================================================================
--- head/sys/sys/event.h        Sun Dec 25 19:49:09 2016        (r310553)
+++ head/sys/sys/event.h        Sun Dec 25 19:49:35 2016        (r310554)
@@ -231,7 +231,6 @@ struct knote {
                struct          proc *p_proc;   /* proc pointer */
                struct          kaiocb *p_aio;  /* AIO job pointer */
                struct          aioliojob *p_lio;       /* LIO job pointer */
-               sbintime_t      *p_nexttime;    /* next timer event fires at */
                void            *p_v;           /* generic other pointer */
        } kn_ptr;
        struct                  filterops *kn_fop;
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to