Module Name:    src
Committed By:   thorpej
Date:           Tue Dec  8 04:09:38 UTC 2020

Modified Files:
        src/sys/kern: kern_time.c
        src/sys/sys: timevar.h

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.209 -r1.210 src/sys/kern/kern_time.c
cvs rdiff -u -r1.45 -r1.46 src/sys/sys/timevar.h

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_time.c
diff -u src/sys/kern/kern_time.c:1.209 src/sys/kern/kern_time.c:1.210
--- src/sys/kern/kern_time.c:1.209	Mon Dec  7 03:01:15 2020
+++ src/sys/kern/kern_time.c	Tue Dec  8 04:09:38 2020
@@ -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 @@ __KERNEL_RCSID(0, "$NetBSD: kern_time.c,
 #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 @@ itimer_unlock(void)
  *	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 @@ adjtime1(const struct timeval *delta, st
  *
  *	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 @@ itimer_init(struct itimer * const it, co
 	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_init(struct itimer * const it, co
 }
 
 /*
- * itimer_fini:
+ * itimer_poison:
  *
- *	Release resources used by an interval timer.
- *
- *	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 @@ itimer_fini(struct itimer * const it)
 			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 @@ itimer_decr(struct itimer *it, int nsec)
 	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 @@ ptimer_free(struct ptimers *pts, int ind
 	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 @@ ptimer_fire(struct itimer *it)
 	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 @@ timer_create1(timer_t *tid, clockid_t id
 	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 @@ ptimer_intr(void *cookie)
 	
 	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) {

Index: src/sys/sys/timevar.h
diff -u src/sys/sys/timevar.h:1.45 src/sys/sys/timevar.h:1.46
--- src/sys/sys/timevar.h:1.45	Sat Dec  5 18:17:01 2020
+++ src/sys/sys/timevar.h	Tue Dec  8 04:09:38 2020
@@ -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 @@ LIST_HEAD(itlist, itimer);
  *
  * 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 @@ LIST_HEAD(itlist, itimer);
  *	  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 @@ struct itimer {
 		} 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 itimer {
 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 ptimers {
 	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	timerupcall(struct lwp *);
 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 *);
 
 void	ptimer_tick(struct lwp *, bool);
 void	ptimers_free(struct proc *, int);

Reply via email to