Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys A couple of tweaks to the previous re-factor:



details:   https://anonhg.NetBSD.org/src/rev/3db9a5e4516c
branches:  trunk
changeset: 946771:3db9a5e4516c
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Tue Dec 08 04:09:38 2020 +0000

description:
A couple of tweaks to the previous re-factor:

- Some of what was defined as "generic itimer" behavior turned out to be
  ptimer-specific.  As such, everything related to the "fired timer queue"
  is now specific to ptimers, and the queue and softint handle fields of
  itimer_ops are not needed.

- Split itimer_fini() into 2 parts: itimer_poision() marks the timer as
  dead and attempts to cancel it.  itimer_fini() is then just responsible
  for freeing itimer resources and releasing the lock.  They are split
  into two parts, as ptimers require an addition processing step between
  those two operations, but other kinds of itimers do not necessarily require
  that.

- Export a few more itimer-related symbols that other itimer types will
  need.

Riding previous kernel version bump since there are no external uses of
this code since the version bump that accompanied the original change.

diffstat:

 sys/kern/kern_time.c |  98 ++++++++++++++++++++++++++-------------------------
 sys/sys/timevar.h    |  27 ++++++-------
 2 files changed, 63 insertions(+), 62 deletions(-)

diffs (truncated from 302 to 300 lines):

diff -r c00c0638d9e1 -r 3db9a5e4516c sys/kern/kern_time.c
--- a/sys/kern/kern_time.c      Tue Dec 08 00:50:04 2020 +0000
+++ b/sys/kern/kern_time.c      Tue Dec 08 04:09:38 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_time.c,v 1.209 2020/12/07 03:01:15 christos Exp $ */
+/*     $NetBSD: kern_time.c,v 1.210 2020/12/08 04:09:38 thorpej Exp $  */
 
 /*-
  * Copyright (c) 2000, 2004, 2005, 2007, 2008, 2009, 2020
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.209 2020/12/07 03:01:15 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.210 2020/12/08 04:09:38 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/resourcevar.h>
@@ -79,12 +79,12 @@
 #include <sys/syscallargs.h>
 #include <sys/cpu.h>
 
-static kmutex_t        itimer_mutex __cacheline_aligned;
+kmutex_t       itimer_mutex __cacheline_aligned;       /* XXX static */
 static struct itlist itimer_realtime_changed_notify;
 
 static void    ptimer_intr(void *);
 static void    *ptimer_sih __read_mostly;
-static struct itqueue ptimer_queue;
+static TAILQ_HEAD(, ptimer) ptimer_queue;
 
 #define        CLOCK_VIRTUAL_P(clockid)        \
        ((clockid) == CLOCK_VIRTUAL || (clockid) == CLOCK_PROF)
@@ -165,7 +165,7 @@
  *     Check that the interval timer lock is held for diagnostic
  *     assertions.
  */
-static inline bool __diagused
+inline bool __diagused
 itimer_lock_held(void)
 {
        return mutex_owned(&itimer_mutex);
@@ -652,7 +652,7 @@
  *
  *     Initialize the common data for an interval timer.
  */
-static void
+void
 itimer_init(struct itimer * const it, const struct itimer_ops * const ops,
     clockid_t const id, struct itlist * const itl)
 {
@@ -664,7 +664,6 @@
        it->it_ops = ops;
        it->it_clockid = id;
        it->it_overruns = 0;
-       it->it_queued = false;
        it->it_dying = false;
        if (!CLOCK_VIRTUAL_P(id)) {
                KASSERT(itl == NULL);
@@ -681,14 +680,13 @@
 }
 
 /*
- * itimer_fini:
- *
- *     Release resources used by an interval timer.
+ * itimer_poison:
  *
- *     N.B. itimer_lock must be held on entry, and is released on exit.
+ *     Poison an interval timer, preventing it from being scheduled
+ *     or processed, in preparation for freeing the timer.
  */
-static void
-itimer_fini(struct itimer * const it)
+void
+itimer_poison(struct itimer * const it)
 {
 
        KASSERT(itimer_lock_held());
@@ -710,14 +708,22 @@
                        LIST_REMOVE(it, it_rtchgq);
                }
        }
+}
 
-       /* Remove it from the queue to be signalled.  */
-       if (it->it_queued) {
-               TAILQ_REMOVE(it->it_ops->ito_queue, it, it_chain);
-               it->it_queued = false;
-       }
+/*
+ * itimer_fini:
+ *
+ *     Release resources used by an interval timer.
+ *
+ *     N.B. itimer_lock must be held on entry, and is released on exit.
+ */
+void
+itimer_fini(struct itimer * const it)
+{
 
-       /* All done with the global state.  */
+       KASSERT(itimer_lock_held());
+
+       /* All done with the global state. */
        itimer_unlock();
 
        /* Destroy the callout, if needed. */
@@ -776,25 +782,6 @@
        return true;
 }
 
-/*
- * itimer_fire:
- *
- *     An interval timer has fired.  Enqueue it for processing, if
- *     needed.
- */
-void
-itimer_fire(struct itimer * const it)
-{
-
-       KASSERT(itimer_lock_held());
-
-       if (!it->it_queued) {
-               TAILQ_INSERT_TAIL(it->it_ops->ito_queue, it, it_chain);
-               it->it_queued = true;
-               softint_schedule(*it->it_ops->ito_sihp);
-       }
-}
-
 static void itimer_callout(void *);
 
 /*
@@ -1024,6 +1011,18 @@
        it = pts->pts_timers[index];
        pt = container_of(it, struct ptimer, pt_itimer);
        pts->pts_timers[index] = NULL;
+       itimer_poison(it);
+
+       /*
+        * Remove it from the queue to be signalled.  Must be done
+        * after itimer is poisoned, because we may have had to wait
+        * for the callout to complete.
+        */
+       if (pt->pt_queued) {
+               TAILQ_REMOVE(&ptimer_queue, pt, pt_chain);
+               pt->pt_queued = false;
+       }
+
        itimer_fini(it);        /* releases itimer_lock */
        kmem_free(pt, sizeof(*pt));
 }
@@ -1150,16 +1149,19 @@
        if (pt->pt_ev.sigev_notify != SIGEV_SIGNAL) {
                return;
        }
-       itimer_fire(it);
+
+       if (!pt->pt_queued) {
+               TAILQ_INSERT_TAIL(&ptimer_queue, pt, pt_chain);
+               pt->pt_queued = true;
+               softint_schedule(ptimer_sih);
+       }
 }
 
 /*
  * Operations vector for per-process timers (BSD and POSIX).
  */
 static const struct itimer_ops ptimer_itimer_ops = {
-       .ito_queue = &ptimer_queue,
-       .ito_sihp = &ptimer_sih,
-       .ito_fire = &ptimer_fire,
+       .ito_fire = ptimer_fire,
 };
 
 /*
@@ -1256,6 +1258,7 @@
        pt->pt_proc = p;
        pt->pt_poverruns = 0;
        pt->pt_entry = timerid;
+       pt->pt_queued = false;
 
        pts->pts_timers[timerid] = &pt->pt_itimer;
        itimer_unlock();
@@ -1740,13 +1743,12 @@
        
        mutex_enter(&proc_lock);
        itimer_lock();
-       while ((it = TAILQ_FIRST(&ptimer_queue)) != NULL) {
-               TAILQ_REMOVE(&ptimer_queue, it, it_chain);
-               KASSERT(it->it_ops->ito_queue == &ptimer_queue);
-               KASSERT(it->it_queued);
-               it->it_queued = false;
+       while ((pt = TAILQ_FIRST(&ptimer_queue)) != NULL) {
+               it = &pt->pt_itimer;
 
-               pt = container_of(it, struct ptimer, pt_itimer);
+               TAILQ_REMOVE(&ptimer_queue, pt, pt_chain);
+               KASSERT(pt->pt_queued);
+               pt->pt_queued = false;
 
                p = pt->pt_proc;
                if (p->p_timers == NULL) {
diff -r c00c0638d9e1 -r 3db9a5e4516c sys/sys/timevar.h
--- a/sys/sys/timevar.h Tue Dec 08 00:50:04 2020 +0000
+++ b/sys/sys/timevar.h Tue Dec 08 04:09:38 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: timevar.h,v 1.45 2020/12/05 18:17:01 thorpej Exp $     */
+/*     $NetBSD: timevar.h,v 1.46 2020/12/08 04:09:38 thorpej Exp $     */
 
 /*
  *  Copyright (c) 2005, 2008, 2020 The NetBSD Foundation, Inc.
@@ -64,9 +64,9 @@
 #include <sys/queue.h>
 #include <sys/signal.h>
 #include <sys/systm.h>
+#include <sys/mutex.h>
 
 struct itimer;
-TAILQ_HEAD(itqueue, itimer);
 LIST_HEAD(itlist, itimer);
 
 /*
@@ -74,15 +74,9 @@
  *
  * Required fields:
  *
- *     - ito_queue: The queue onto which an itimer is added when it
- *       fires.
- *
- *     - ito_sihp: A pointer to a software interrupt handle that is
- *       scheduled to run when an itimer is added to ito_queue.
- *
  *     - ito_fire: A function to be called when the itimer fires.
  *       The timer implementation should perform whatever processing
- *       is necessary for that timer type and then call itimer_fire().
+ *       is necessary for that timer type.
  *
  * Optional fields:
  *
@@ -90,8 +84,6 @@
  *       time (CLOCK_REALTIME) is called.
  */
 struct itimer_ops {
-       struct itqueue *ito_queue;
-       void    **ito_sihp;
        void    (*ito_fire)(struct itimer *);
        void    (*ito_realtime_changed)(struct itimer *);
 };
@@ -112,11 +104,9 @@
                } it_virtual;
        };
        const struct itimer_ops *it_ops;
-       TAILQ_ENTRY(itimer) it_chain;
        struct itimerspec it_time;
        clockid_t it_clockid;
        int     it_overruns;    /* Overruns currently accumulating */
-       bool    it_queued;
        bool    it_dying;
 };
 
@@ -133,10 +123,12 @@
 struct ptimer {
        struct itimer pt_itimer;/* common interval timer data */
 
+       TAILQ_ENTRY(ptimer) pt_chain; /* link in signalling queue */
        struct  sigevent pt_ev; /* event notification info */
        int     pt_poverruns;   /* Overruns associated w/ a delivery */
        int     pt_entry;       /* slot in proc's timer table */
        struct proc *pt_proc;   /* associated process */
+       bool    pt_queued;      /* true if linked into signalling queue */
 };
 
 #define        TIMER_MIN       4       /* [0..3] are reserved for setitimer(2) */
@@ -151,6 +143,8 @@
        struct itimer *pts_timers[TIMER_MAX];
 };
 
+extern kmutex_t        itimer_mutex;   /* XXX */
+
 /*
  * Functions for looking at our clock: [get]{bin,nano,micro}[up]time()
  *
@@ -229,11 +223,16 @@
 void   time_init(void);
 bool   time_wraps(struct timespec *, struct timespec *);
 
+void   itimer_init(struct itimer *, const struct itimer_ops *,
+           clockid_t, struct itlist *);
+void   itimer_poison(struct itimer *);
+void   itimer_fini(struct itimer *);
+
 void   itimer_lock(void);
 void   itimer_unlock(void);
+bool   itimer_lock_held(void);         /* for diagnostic assertions only */
 int    itimer_settime(struct itimer *);
 void   itimer_gettime(const struct itimer *, struct itimerspec *);
-void   itimer_fire(struct itimer *);
 



Home | Main Index | Thread Index | Old Index