Source-Changes-HG archive

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

[src/trunk]: src/sys First steps towards properly serializing access to the T...



details:   https://anonhg.NetBSD.org/src/rev/1e125367185c
branches:  trunk
changeset: 466765:1e125367185c
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Wed Jan 01 21:09:11 2020 +0000

description:
First steps towards properly serializing access to the TOD clock.
- Add a mutex around the TODR, and provide lock/unlock/lock-owned
  functions to manipulate it.
- Rename inittodr() to todr_set_systime() and resettodr() to
  todr_save_systime() to better reflect what they do.  These functions
  are intended to be called with the TODR lock held, which will allow
  for a pattern like:
        -> todr_lock()
        -> todr_save_systime()
        -> [do machine-dependent stuff to sleep/suspend]
        -> [magically awaken]
        -> todr_set_systime(...)
        -> todr_unlock()
- Provide historically-named wrappers inittodr() and resettodr() that
  do the dance of acquiring / releasing the lock around the actual
  substance.

NOTE: resettodr()'s use of the TODR lock is currently disabled (and
todr_save_systime() does not assert it's held) until such time as
issues around shutdown / reboot under duress can be addressed.

diffstat:

 sys/dev/clock_subr.h |   15 ++-
 sys/kern/init_main.c |    9 +-
 sys/kern/kern_todr.c |  161 +++++++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 164 insertions(+), 21 deletions(-)

diffs (truncated from 303 to 300 lines):

diff -r b3b1ddef2174 -r 1e125367185c sys/dev/clock_subr.h
--- a/sys/dev/clock_subr.h      Wed Jan 01 20:13:19 2020 +0000
+++ b/sys/dev/clock_subr.h      Wed Jan 01 21:09:11 2020 +0000
@@ -1,7 +1,7 @@
-/*     $NetBSD: clock_subr.h,v 1.28 2020/01/01 19:24:03 thorpej Exp $  */
+/*     $NetBSD: clock_subr.h,v 1.29 2020/01/01 21:09:11 thorpej Exp $  */
 
 /*-
- * Copyright (c) 1996 The NetBSD Foundation, Inc.
+ * Copyright (c) 1996, 2020 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -93,10 +93,13 @@
 };
 typedef struct todr_chip_handle *todr_chip_handle_t;
 
-/*
- * Machine-dependent function that machine-independent RTC drivers can
- * use to register their todr_chip_handle_t with inittodr()/resettodr().
- */
+void   todr_init(void);
 void   todr_attach(todr_chip_handle_t);
+void   todr_lock(void);
+void   todr_unlock(void);
+bool   todr_lock_owned(void);
+
+void   todr_set_systime(time_t base);
+void   todr_save_systime(void);
 
 #endif /* _DEV_CLOCK_SUBR_H_ */
diff -r b3b1ddef2174 -r 1e125367185c sys/kern/init_main.c
--- a/sys/kern/init_main.c      Wed Jan 01 20:13:19 2020 +0000
+++ b/sys/kern/init_main.c      Wed Jan 01 21:09:11 2020 +0000
@@ -1,7 +1,7 @@
-/*     $NetBSD: init_main.c,v 1.514 2019/12/31 13:07:13 ad Exp $       */
+/*     $NetBSD: init_main.c,v 1.515 2020/01/01 21:09:11 thorpej Exp $  */
 
 /*-
- * Copyright (c) 2008, 2009, 2019 The NetBSD Foundation, Inc.
+ * Copyright (c) 2008, 2009, 2019, The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -97,7 +97,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.514 2019/12/31 13:07:13 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.515 2020/01/01 21:09:11 thorpej Exp $");
 
 #include "opt_ddb.h"
 #include "opt_inet.h"
@@ -204,6 +204,8 @@
 
 #include <sys/pax.h>
 
+#include <dev/clock_subr.h>
+
 #include <secmodel/secmodel.h>
 
 #include <ufs/ufs/quota.h>
@@ -298,6 +300,7 @@
 
        kernel_lock_init();
        once_init();
+       todr_init();
 
        mi_cpu_init();
        kernconfig_lock_init();
diff -r b3b1ddef2174 -r 1e125367185c sys/kern/kern_todr.c
--- a/sys/kern/kern_todr.c      Wed Jan 01 20:13:19 2020 +0000
+++ b/sys/kern/kern_todr.c      Wed Jan 01 21:09:11 2020 +0000
@@ -1,4 +1,33 @@
-/*     $NetBSD: kern_todr.c,v 1.43 2020/01/01 19:24:03 thorpej Exp $   */
+/*     $NetBSD: kern_todr.c,v 1.44 2020/01/01 21:09:11 thorpej Exp $   */
+
+/*-
+ * Copyright (c) 2020 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
 
 /*
  * Copyright (c) 1988 University of Utah.
@@ -41,7 +70,7 @@
 #include "opt_todr.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_todr.c,v 1.43 2020/01/01 19:24:03 thorpej Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_todr.c,v 1.44 2020/01/01 21:09:11 thorpej Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -50,35 +79,98 @@
 #include <sys/timetc.h>
 #include <sys/intr.h>
 #include <sys/rndsource.h>
+#include <sys/mutex.h>
 
 #include <dev/clock_subr.h>    /* hmm.. this should probably move to sys */
 
 static int todr_gettime(todr_chip_handle_t, struct timeval *);
 static int todr_settime(todr_chip_handle_t, struct timeval *);
 
-static todr_chip_handle_t todr_handle = NULL;
+static kmutex_t todr_mutex;
+static todr_chip_handle_t todr_handle;
+static bool todr_initialized;
+
+/*
+ * todr_init:
+ *     Initialize TOD clock data.
+ */
+void
+todr_init(void)
+{
+
+       mutex_init(&todr_mutex, MUTEX_DEFAULT, IPL_NONE);
+       todr_initialized = true;
+}
 
 /*
- * Attach the clock device to todr_handle.
+ * todr_lock:
+ *     Acquire the TODR lock.
+ */
+void
+todr_lock(void)
+{
+
+       mutex_enter(&todr_mutex);
+}
+
+/*
+ * todr_unlock:
+ *     Release the TODR lock.
+ */
+void
+todr_unlock(void)
+{
+
+       mutex_exit(&todr_mutex);
+}
+
+/*
+ * todr_lock_owned:
+ *     Return true if the current thread owns the TODR lock.
+ *     This is to be used by diagnostic assertions only.
+ */
+bool
+todr_lock_owned(void)
+{
+
+       return mutex_owned(&todr_mutex) ? true : false;
+}
+
+/*
+ * todr_attach:
+ *     Attach the clock device to todr_handle.
  */
 void
 todr_attach(todr_chip_handle_t todr)
 {
 
+       /*
+        * todr_init() is called very early in main(), but this is
+        * here to catch a case where todr_attach() is called before
+        * main().
+        */
+       KASSERT(todr_initialized);
+
+       todr_lock();
        if (todr_handle) {
+               todr_unlock();
                printf("todr_attach: TOD already configured\n");
                return;
        }
        todr_handle = todr;
+       todr_unlock();
 }
 
 static bool timeset = false;
 
 /*
- * Set up the system's time, given a `reasonable' time value.
+ * todr_set_systime:
+ *     Set up the system's time.  The "base" argument is a best-guess
+ *     close-enough value to use if the TOD clock is unavailable or
+ *     contains garbage.  Must be called with the TODR lock held.
  */
 void
-inittodr(time_t base)
+todr_set_systime(time_t base)
 {
        bool badbase = false;
        bool waszero = (base == 0);
@@ -87,6 +179,8 @@
        struct timespec ts;
        struct timeval tv;
 
+       KASSERT(todr_lock_owned());
+
        rnd_add_data(NULL, &base, sizeof(base), 0);
 
        if (base < 5 * SECS_PER_COMMON_YEAR) {
@@ -180,17 +274,19 @@
 }
 
 /*
- * Reset the TODR based on the time value; used when the TODR
- * has a preposterous value and also when the time is reset
- * by the stime system call.  Also called when the TODR goes past
- * TODRZERO + 100*(SECS_PER_COMMON_YEAR+2*SECS_PER_DAY)
- * (e.g. on Jan 2 just after midnight) to wrap the TODR around.
+ * todr_save_systime:
+ *     Save the current system time back to the TOD clock.
+ *     Must be called with the TODR lock held.
  */
 void
-resettodr(void)
+todr_save_systime(void)
 {
        struct timeval tv;
 
+#if notyet
+       KASSERT(todr_lock_owned());
+#endif
+
        /*
         * We might have been called by boot() due to a crash early
         * on.  Don't reset the clock chip if we don't know what time
@@ -209,6 +305,47 @@
                        printf("Cannot set TOD clock time\n");
 }
 
+/*
+ * inittodr:
+ *     Legacy wrapper around todr_set_systime().
+ */
+void
+inittodr(time_t base)
+{
+
+       todr_lock();
+       todr_set_systime(base);
+       todr_unlock();
+}
+
+/*
+ * resettodr:
+ *     Legacy wrapper around todr_save_systime().
+ */
+void
+resettodr(void)
+{
+
+#if notyet
+       /*
+        * If we're shutting down, we don't want to get stuck in case
+        * someone was already fiddling with the TOD clock.
+        */
+       if (shutting_down) {
+               if (mutex_tryenter(&todr_mutex) == 0) {
+                       printf("WARNING: Cannot set TOD clock time (busy)\n");
+                       return;
+               }
+       } else {
+               todr_lock();
+       }
+#endif
+       todr_save_systime();
+#if notyet
+       todr_unlock();
+#endif
+}
+



Home | Main Index | Thread Index | Old Index