Source-Changes-HG archive

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

[src/trunk]: src/external/cddl/osnet/sys/kern Sync with upstream r315983.



details:   https://anonhg.NetBSD.org/src/rev/f44dfd21a6fa
branches:  trunk
changeset: 999522:f44dfd21a6fa
user:      hannken <hannken%NetBSD.org@localhost>
date:      Fri Jun 07 10:31:21 2019 +0000

description:
Sync with upstream r315983.

diffstat:

 external/cddl/osnet/sys/kern/callb.c |  112 +++++-
 external/cddl/osnet/sys/kern/fm.c    |  664 ++++++++++++++++++++++++++++++++--
 2 files changed, 714 insertions(+), 62 deletions(-)

diffs (truncated from 1049 to 300 lines):

diff -r 88bd161751e0 -r f44dfd21a6fa external/cddl/osnet/sys/kern/callb.c
--- a/external/cddl/osnet/sys/kern/callb.c      Fri Jun 07 07:41:22 2019 +0000
+++ b/external/cddl/osnet/sys/kern/callb.c      Fri Jun 07 10:31:21 2019 +0000
@@ -1,12 +1,9 @@
-/*     $NetBSD: callb.c,v 1.1 2009/08/07 20:57:57 haad Exp $   */
-
 /*
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
  *
  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  * or http://www.opensolaris.org/os/licensing.
@@ -22,12 +19,10 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident  "%Z%%M% %I%     %E% SMI"
-
 #include <sys/param.h>
 #include <sys/types.h>
 #include <sys/time.h>
@@ -111,14 +106,24 @@
 callb_fini(void *dummy __unused)
 {
        callb_t *cp;
+       int i;
 
        mutex_enter(&ct->ct_lock);
-       while ((cp = ct->ct_freelist) != NULL) {
-               ct->ct_freelist = cp->c_next;
-               ct->ct_ncallb--;
-               kmem_free(cp, sizeof (callb_t));
+       for (i = 0; i < 16; i++) {
+               while ((cp = ct->ct_freelist) != NULL) {
+                       ct->ct_freelist = cp->c_next;
+                       ct->ct_ncallb--;
+                       kmem_free(cp, sizeof (callb_t));
+               }
+               if (ct->ct_ncallb == 0)
+                       break;
+               /* Not all callbacks finished, waiting for the rest. */
+               mutex_exit(&ct->ct_lock);
+               tsleep(ct, 0, "callb", hz / 4);
+               mutex_enter(&ct->ct_lock);
        }
-       ASSERT(ct->ct_ncallb == 0);
+       if (ct->ct_ncallb > 0)
+               printf("%s: Leaked %d callbacks!\n", __func__, ct->ct_ncallb);
        mutex_exit(&ct->ct_lock);
        mutex_destroy(&callb_safe_mutex);
        mutex_destroy(&callb_table.ct_lock);
@@ -270,7 +275,7 @@
 
 #ifdef CALLB_DEBUG
                printf("callb_execute: name=%s func=%p arg=%p\n",
-                       cp->c_name, (void *)cp->c_func, (void *)cp->c_arg);
+                   cp->c_name, (void *)cp->c_func, (void *)cp->c_arg);
 #endif /* CALLB_DEBUG */
 
                mutex_exit(&ct->ct_lock);
@@ -309,12 +314,14 @@
        switch (code) {
        case CB_CODE_CPR_CHKPT:
                cp->cc_events |= CALLB_CPR_START;
+#ifdef CPR_NOT_THREAD_SAFE
                while (!(cp->cc_events & CALLB_CPR_SAFE))
                        /* cv_timedwait() returns -1 if it times out. */
-                       if ((ret = cv_timedwait(&cp->cc_callb_cv,
-                           cp->cc_lockp,
-                           callb_timeout_sec * hz)) == -1)
+                       if ((ret = cv_reltimedwait(&cp->cc_callb_cv,
+                           cp->cc_lockp, (callb_timeout_sec * hz),
+                           TR_CLOCK_TICK)) == -1)
                                break;
+#endif
                break;
 
        case CB_CODE_CPR_RESUME:
@@ -360,3 +367,74 @@
        cv_broadcast(&ct->ct_busy_cv);
        mutex_exit(&ct->ct_lock);
 }
+
+#ifdef illumos
+/*
+ * Return a boolean value indicating whether a particular kernel thread is
+ * stopped in accordance with the cpr callback protocol.  If returning
+ * false, also return a pointer to the thread name via the 2nd argument.
+ */
+boolean_t
+callb_is_stopped(kthread_id_t tp, caddr_t *thread_name)
+{
+       callb_t *cp;
+       boolean_t ret_val;
+
+       mutex_enter(&ct->ct_lock);
+
+       for (cp = ct->ct_first_cb[CB_CL_CPR_DAEMON];
+           cp != NULL && tp != cp->c_thread; cp = cp->c_next)
+               ;
+
+       ret_val = (cp != NULL);
+       if (ret_val) {
+               /*
+                * We found the thread in the callback table and have
+                * provisionally set the return value to true.  Now
+                * see if it is marked "safe" and is sleeping or stopped.
+                */
+               callb_cpr_t *ccp = (callb_cpr_t *)cp->c_arg;
+
+               *thread_name = cp->c_name;      /* in case not stopped */
+               mutex_enter(ccp->cc_lockp);
+
+               if (ccp->cc_events & CALLB_CPR_SAFE) {
+                       int retry;
+
+                       mutex_exit(ccp->cc_lockp);
+                       for (retry = 0; retry < CALLB_MAX_RETRY; retry++) {
+                               thread_lock(tp);
+                               if (tp->t_state & (TS_SLEEP | TS_STOPPED)) {
+                                       thread_unlock(tp);
+                                       break;
+                               }
+                               thread_unlock(tp);
+                               delay(CALLB_THREAD_DELAY);
+                       }
+                       ret_val = retry < CALLB_MAX_RETRY;
+               } else {
+                       ret_val =
+                           (ccp->cc_events & CALLB_CPR_ALWAYS_SAFE) != 0;
+                       mutex_exit(ccp->cc_lockp);
+               }
+       } else {
+               /*
+                * Thread not found in callback table.  Make the best
+                * attempt to identify the thread in the error message.
+                */
+               ulong_t offset;
+               char *sym = kobj_getsymname((uintptr_t)tp->t_startpc,
+                   &offset);
+
+               *thread_name = sym ? sym : "*unknown*";
+       }
+
+       mutex_exit(&ct->ct_lock);
+       return (ret_val);
+}
+#endif /* illumos */
+
+#if defined(__FreeBSD__) && defined(_KERNEL)
+SYSINIT(sol_callb, SI_SUB_DRIVERS, SI_ORDER_FIRST, callb_init, NULL);
+SYSUNINIT(sol_callb, SI_SUB_DRIVERS, SI_ORDER_FIRST, callb_fini, NULL);
+#endif
diff -r 88bd161751e0 -r f44dfd21a6fa external/cddl/osnet/sys/kern/fm.c
--- a/external/cddl/osnet/sys/kern/fm.c Fri Jun 07 07:41:22 2019 +0000
+++ b/external/cddl/osnet/sys/kern/fm.c Fri Jun 07 10:31:21 2019 +0000
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 /*
@@ -53,18 +52,24 @@
  */
 
 #include <sys/types.h>
-#include <sys/pset.h>
 #include <sys/time.h>
-#include <sys/kernel.h>
-#include <sys/systm.h>
 #include <sys/sysevent.h>
 #include <sys/nvpair.h>
 #include <sys/cmn_err.h>
 #include <sys/cpuvar.h>
 #include <sys/sysmacros.h>
 #include <sys/systm.h>
+#include <sys/compress.h>
+#include <sys/cpuvar.h>
+#include <sys/kobj.h>
+#include <sys/kstat.h>
+#include <sys/processor.h>
+#ifdef __NetBSD__
 #include <sys/cpu.h>
-#include <sys/atomic.h>
+#else
+#include <sys/pcpu.h>
+#endif
+#include <sys/sunddi.h>
 #include <sys/systeminfo.h>
 #include <sys/sysevent/eventdefs.h>
 #include <sys/fm/util.h>
@@ -78,7 +83,11 @@
 static const char *fm_msgid = "SUNOS-8000-0G";
 static char *volatile fm_panicstr = NULL;
 
+#ifdef illumos
 errorq_t *ereport_errorq;
+#endif
+void *ereport_dumpbuf;
+size_t ereport_dumplen;
 
 static uint_t ereport_chanlen = ERPT_EVCH_MAX;
 static evchan_t *ereport_chan = NULL;
@@ -86,6 +95,86 @@
 static size_t ereport_size = 0;
 static int ereport_cols = 80;
 
+extern void fastreboot_disable_highpil(void);
+
+/*
+ * Common fault management kstats to record ereport generation
+ * failures
+ */
+
+struct erpt_kstat {
+       kstat_named_t   erpt_dropped;           /* num erpts dropped on post */
+       kstat_named_t   erpt_set_failed;        /* num erpt set failures */
+       kstat_named_t   fmri_set_failed;        /* num fmri set failures */
+       kstat_named_t   payload_set_failed;     /* num payload set failures */
+};
+
+static struct erpt_kstat erpt_kstat_data = {
+       { "erpt-dropped", KSTAT_DATA_UINT64 },
+       { "erpt-set-failed", KSTAT_DATA_UINT64 },
+       { "fmri-set-failed", KSTAT_DATA_UINT64 },
+       { "payload-set-failed", KSTAT_DATA_UINT64 }
+};
+
+#ifdef illumos
+/*ARGSUSED*/
+static void
+fm_drain(void *private, void *data, errorq_elem_t *eep)
+{
+       nvlist_t *nvl = errorq_elem_nvl(ereport_errorq, eep);
+
+       if (!panicstr)
+               (void) fm_ereport_post(nvl, EVCH_TRYHARD);
+       else
+               fm_nvprint(nvl);
+}
+#endif
+
+void
+fm_init(void)
+{
+       kstat_t *ksp;
+
+#ifdef illumos
+       (void) sysevent_evc_bind(FM_ERROR_CHAN,
+           &ereport_chan, EVCH_CREAT | EVCH_HOLD_PEND);
+
+       (void) sysevent_evc_control(ereport_chan,
+           EVCH_SET_CHAN_LEN, &ereport_chanlen);
+#endif
+
+       if (ereport_qlen == 0)
+               ereport_qlen = ERPT_MAX_ERRS * MAX(max_ncpus, 4);
+
+       if (ereport_size == 0)
+               ereport_size = ERPT_DATA_SZ;
+
+#ifdef illumos
+       ereport_errorq = errorq_nvcreate("fm_ereport_queue",
+           (errorq_func_t)fm_drain, NULL, ereport_qlen, ereport_size,
+           FM_ERR_PIL, ERRORQ_VITAL);
+       if (ereport_errorq == NULL)
+               panic("failed to create required ereport error queue");
+#endif
+
+       ereport_dumpbuf = kmem_alloc(ereport_size, KM_SLEEP);
+       ereport_dumplen = ereport_size;
+
+       /* Initialize ereport allocation and generation kstats */
+       ksp = kstat_create("unix", 0, "fm", "misc", KSTAT_TYPE_NAMED,
+           sizeof (struct erpt_kstat) / sizeof (kstat_named_t),
+           KSTAT_FLAG_VIRTUAL);
+
+       if (ksp != NULL) {
+               ksp->ks_data = &erpt_kstat_data;
+               kstat_install(ksp);
+       } else {
+               cmn_err(CE_NOTE, "failed to create fm/misc kstat\n");
+
+       }
+}



Home | Main Index | Thread Index | Old Index