Source-Changes-HG archive

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

[src/trunk]: src/sys Refactor interval timers to make it possible to support ...



details:   https://anonhg.NetBSD.org/src/rev/b4ccc239d790
branches:  trunk
changeset: 946654:b4ccc239d790
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Sat Dec 05 18:17:01 2020 +0000

description:
Refactor interval timers to make it possible to support types other than
the BSD/POSIX per-process timers:

- "struct ptimer" is split into "struct itimer" (common interval timer
  data) and "struct ptimer" (per-process timer data, which contains a
  "struct itimer").

- Introduce a new "struct itimer_ops" that supplies information about
  the specific kind of interval timer, including it's processing
  queue, the softint handle used to schedule processing, the function
  to call when the timer fires (which adds it to the queue), and an
  optional function to call when the CLOCK_REALTIME clock is changed by
  a call to clock_settime() or settimeofday().

- Rename some fuctions to clearly identify what they're operating on
  (ptimer vs itimer).

- Use kmem(9) to allocate ptimer-related structures, rather than having
  dedicated pools for them.

Welcome to NetBSD 9.99.77.

diffstat:

 sys/kern/init_main.c  |    11 +-
 sys/kern/kern_clock.c |     6 +-
 sys/kern/kern_exec.c  |     6 +-
 sys/kern/kern_exit.c  |     6 +-
 sys/kern/kern_time.c  |  1383 ++++++++++++++++++++++++++++--------------------
 sys/sys/param.h       |     4 +-
 sys/sys/proc.h        |     4 +-
 sys/sys/timevar.h     |   120 ++-
 8 files changed, 894 insertions(+), 646 deletions(-)

diffs (truncated from 2068 to 300 lines):

diff -r 016f18dfe13d -r b4ccc239d790 sys/kern/init_main.c
--- a/sys/kern/init_main.c      Sat Dec 05 18:16:11 2020 +0000
+++ b/sys/kern/init_main.c      Sat Dec 05 18:17:01 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: init_main.c,v 1.533 2020/11/12 07:44:01 simonb Exp $   */
+/*     $NetBSD: init_main.c,v 1.534 2020/12/05 18:17:01 thorpej Exp $  */
 
 /*-
  * Copyright (c) 2008, 2009, 2019 The NetBSD Foundation, Inc.
@@ -97,7 +97,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.533 2020/11/12 07:44:01 simonb Exp $");
+__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.534 2020/12/05 18:17:01 thorpej Exp $");
 
 #include "opt_cnmagic.h"
 #include "opt_ddb.h"
@@ -432,9 +432,6 @@
        /* Charge root for one process. */
        (void)chgproccnt(0, 1);
 
-       /* Initialize timekeeping. */
-       time_init();
-
        /* Initialize the run queues, turnstiles and sleep queues. */
        sched_rqinit();
        turnstile_init();
@@ -452,8 +449,8 @@
        error = mi_cpu_attach(curcpu());
        KASSERT(error == 0);
 
-       /* Initialize timekeeping, part 2. */
-       time_init2();
+       /* Initialize timekeeping. */
+       time_init();
 
        /*
         * Initialize mbuf's.  Do this now because we might attempt to
diff -r 016f18dfe13d -r b4ccc239d790 sys/kern/kern_clock.c
--- a/sys/kern/kern_clock.c     Sat Dec 05 18:16:11 2020 +0000
+++ b/sys/kern/kern_clock.c     Sat Dec 05 18:17:01 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_clock.c,v 1.142 2020/10/11 18:39:09 thorpej Exp $ */
+/*     $NetBSD: kern_clock.c,v 1.143 2020/12/05 18:17:01 thorpej Exp $ */
 
 /*-
  * Copyright (c) 2000, 2004, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -69,7 +69,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_clock.c,v 1.142 2020/10/11 18:39:09 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_clock.c,v 1.143 2020/12/05 18:17:01 thorpej Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_dtrace.h"
@@ -238,7 +238,7 @@
        ci = curcpu();
        l = ci->ci_onproc;
 
-       timer_tick(l, CLKF_USERMODE(frame));
+       ptimer_tick(l, CLKF_USERMODE(frame));
 
        /*
         * If no separate statistics clock is available, run it from here.
diff -r 016f18dfe13d -r b4ccc239d790 sys/kern/kern_exec.c
--- a/sys/kern/kern_exec.c      Sat Dec 05 18:16:11 2020 +0000
+++ b/sys/kern/kern_exec.c      Sat Dec 05 18:17:01 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_exec.c,v 1.503 2020/11/25 21:08:59 wiz Exp $      */
+/*     $NetBSD: kern_exec.c,v 1.504 2020/12/05 18:17:01 thorpej Exp $  */
 
 /*-
  * Copyright (c) 2008, 2019, 2020 The NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.503 2020/11/25 21:08:59 wiz Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.504 2020/12/05 18:17:01 thorpej Exp $");
 
 #include "opt_exec.h"
 #include "opt_execfmt.h"
@@ -1209,7 +1209,7 @@
                lwp_ctl_exit();
 
        /* Remove POSIX timers */
-       timers_free(p, TIMERS_POSIX);
+       ptimers_free(p, TIMERS_POSIX);
 
        /* Set the PaX flags. */
        pax_set_flags(epp, p);
diff -r 016f18dfe13d -r b4ccc239d790 sys/kern/kern_exit.c
--- a/sys/kern/kern_exit.c      Sat Dec 05 18:16:11 2020 +0000
+++ b/sys/kern/kern_exit.c      Sat Dec 05 18:17:01 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_exit.c,v 1.290 2020/05/23 23:42:43 ad Exp $       */
+/*     $NetBSD: kern_exit.c,v 1.291 2020/12/05 18:17:01 thorpej Exp $  */
 
 /*-
  * Copyright (c) 1998, 1999, 2006, 2007, 2008, 2020 The NetBSD Foundation, Inc.
@@ -67,7 +67,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.290 2020/05/23 23:42:43 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.291 2020/12/05 18:17:01 thorpej Exp $");
 
 #include "opt_ktrace.h"
 #include "opt_dtrace.h"
@@ -288,7 +288,7 @@
 
        DPRINTF(("%s: %d.%d exiting.\n", __func__, p->p_pid, l->l_lid));
 
-       timers_free(p, TIMERS_ALL);
+       ptimers_free(p, TIMERS_ALL);
 #if defined(__HAVE_RAS)
        ras_purgeall();
 #endif
diff -r 016f18dfe13d -r b4ccc239d790 sys/kern/kern_time.c
--- a/sys/kern/kern_time.c      Sat Dec 05 18:16:11 2020 +0000
+++ b/sys/kern/kern_time.c      Sat Dec 05 18:17:01 2020 +0000
@@ -1,11 +1,12 @@
-/*     $NetBSD: kern_time.c,v 1.206 2020/10/27 00:07:18 nia Exp $      */
+/*     $NetBSD: kern_time.c,v 1.207 2020/12/05 18:17:01 thorpej Exp $  */
 
 /*-
- * Copyright (c) 2000, 2004, 2005, 2007, 2008, 2009 The NetBSD Foundation, Inc.
+ * Copyright (c) 2000, 2004, 2005, 2007, 2008, 2009, 2020
+ *     The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
- * by Christopher G. Demetriou, and by Andrew Doran.
+ * by Christopher G. Demetriou, by Andrew Doran, and by Jason R. Thorpe.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -61,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.206 2020/10/27 00:07:18 nia Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_time.c,v 1.207 2020/12/05 18:17:01 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/resourcevar.h>
@@ -78,16 +79,12 @@
 #include <sys/syscallargs.h>
 #include <sys/cpu.h>
 
-static void    timer_intr(void *);
-static void    itimerfire(struct ptimer *);
-static void    itimerfree(struct ptimers *, int);
+static kmutex_t        itimer_mutex __cacheline_aligned;
+static struct itlist itimer_realtime_changed_notify;
 
-kmutex_t       timer_lock;
-
-static void    *timer_sih;
-static TAILQ_HEAD(, ptimer) timer_queue;
-
-struct pool ptimer_pool, ptimers_pool;
+static void    ptimer_intr(void *);
+static void    *ptimer_sih __read_mostly;
+static struct itqueue ptimer_queue;
 
 #define        CLOCK_VIRTUAL_P(clockid)        \
        ((clockid) == CLOCK_VIRTUAL || (clockid) == CLOCK_PROF)
@@ -106,23 +103,76 @@
 time_init(void)
 {
 
-       pool_init(&ptimer_pool, sizeof(struct ptimer), 0, 0, 0, "ptimerpl",
-           &pool_allocator_nointr, IPL_NONE);
-       pool_init(&ptimers_pool, sizeof(struct ptimers), 0, 0, 0, "ptimerspl",
-           &pool_allocator_nointr, IPL_NONE);
+       mutex_init(&itimer_mutex, MUTEX_DEFAULT, IPL_SCHED);
+       LIST_INIT(&itimer_realtime_changed_notify);
+
+       TAILQ_INIT(&ptimer_queue);
+       ptimer_sih = softint_establish(SOFTINT_CLOCK | SOFTINT_MPSAFE,
+           ptimer_intr, NULL);
+}
+
+/*
+ * Check if the time will wrap if set to ts.
+ *
+ * ts - timespec describing the new time
+ * delta - the delta between the current time and ts
+ */
+bool
+time_wraps(struct timespec *ts, struct timespec *delta)
+{
+
+       /*
+        * Don't allow the time to be set forward so far it
+        * will wrap and become negative, thus allowing an
+        * attacker to bypass the next check below.  The
+        * cutoff is 1 year before rollover occurs, so even
+        * if the attacker uses adjtime(2) to move the time
+        * past the cutoff, it will take a very long time
+        * to get to the wrap point.
+        */
+       if ((ts->tv_sec > LLONG_MAX - 365*24*60*60) ||
+           (delta->tv_sec < 0 || delta->tv_nsec < 0))
+               return true;
+
+       return false;
 }
 
+/*
+ * itimer_lock:
+ *
+ *     Acquire the interval timer data lock.
+ */
 void
-time_init2(void)
+itimer_lock(void)
 {
-
-       TAILQ_INIT(&timer_queue);
-       mutex_init(&timer_lock, MUTEX_DEFAULT, IPL_SCHED);
-       timer_sih = softint_establish(SOFTINT_CLOCK | SOFTINT_MPSAFE,
-           timer_intr, NULL);
+       mutex_spin_enter(&itimer_mutex);
 }
 
-/* Time of day and interval timer support.
+/*
+ * itimer_unlock:
+ *
+ *     Release the interval timer data lock.
+ */
+void
+itimer_unlock(void)
+{
+       mutex_spin_exit(&itimer_mutex);
+}
+
+/*
+ * itimer_lock_held:
+ *
+ *     Check that the interval timer lock is held for diagnostic
+ *     assertions.
+ */
+static inline bool __diagused
+itimer_lock_held(void)
+{
+       return mutex_owned(&itimer_mutex);
+}
+
+/*
+ * Time of day and interval timer support.
  *
  * These routines provide the kernel entry points to get and set
  * the time-of-day and per-process interval timers.  Subroutines
@@ -144,7 +194,6 @@
        if (ts->tv_sec < 0 || ts->tv_sec > (1LL << 36))
                return (EINVAL);
 
-       /* WHAT DO WE DO ABOUT PENDING REAL-TIME TIMEOUTS??? */
        nanotime(&now);
        timespecsub(ts, &now, &delta);
 
@@ -164,6 +213,23 @@
 
        resettodr();
 
+       /*
+        * Notify pending CLOCK_REALTIME timers about the real time change.
+        * There may be inactive timers on this list, but this happens
+        * comparatively less often than timers firing, and so it's better
+        * to put the extra checks here than to complicate the other code
+        * path.
+        */
+       struct itimer *it;
+       itimer_lock();
+       LIST_FOREACH(it, &itimer_realtime_changed_notify, it_rtchgq) {
+               KASSERT(it->it_ops->ito_realtime_changed != NULL);
+               if (timespecisset(&it->it_time.it_value)) {
+                       (*it->it_ops->ito_realtime_changed)(it);
+               }
+       }
+       itimer_unlock();
+
        return (0);
 }
 
@@ -558,8 +624,379 @@
 }
 
 /*
- * Interval timer support. Both the BSD getitimer() family and the POSIX
- * timer_*() family of routines are supported.
+ * Interval timer support.
+ *
+ * The itimer_*() routines provide generic support for interval timers,
+ * both real (CLOCK_REALTIME, CLOCK_MONOTIME), and virtual (CLOCK_VIRTUAL,



Home | Main Index | Thread Index | Old Index