Page MenuHomeFreeBSD

D36610.id114524.diff
No OneTemporary

D36610.id114524.diff

diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
--- a/sys/kern/kern_clock.c
+++ b/sys/kern/kern_clock.c
@@ -834,24 +834,6 @@
static void
watchdog_fire(void)
{
- int nintr;
- uint64_t inttotal;
- u_long *curintr;
- char *curname;
-
- curintr = intrcnt;
- curname = intrnames;
- inttotal = 0;
- nintr = sintrcnt / sizeof(u_long);
-
- printf("interrupt total\n");
- while (--nintr >= 0) {
- if (*curintr)
- printf("%-12s %20lu\n", curname, *curintr);
- curname += strlen(curname) + 1;
- inttotal += *curintr++;
- }
- printf("Total %20ju\n", (uintmax_t)inttotal);
#if defined(KDB) && !defined(KDB_UNATTENDED)
kdb_backtrace();
diff --git a/sys/kern/kern_intr.c b/sys/kern/kern_intr.c
--- a/sys/kern/kern_intr.c
+++ b/sys/kern/kern_intr.c
@@ -3,6 +3,7 @@
*
* Copyright (c) 1997, Stefan Esser <se@freebsd.org>
* All rights reserved.
+ * Copyright © 2022 Elliott Mitchell
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -54,6 +55,7 @@
#include <sys/resourcevar.h>
#include <sys/sched.h>
#include <sys/smp.h>
+#include <sys/sx.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
#include <sys/unistd.h>
@@ -109,8 +111,8 @@
#endif
static TAILQ_HEAD(, intr_event) event_list =
TAILQ_HEAD_INITIALIZER(event_list);
-static struct mtx event_lock;
-MTX_SYSINIT(intr_event_list, &event_lock, "intr event list", MTX_DEF);
+static struct sx event_lock;
+SX_SYSINIT(intr_event_list, &event_lock, "intr event list");
static void intr_event_update(struct intr_event *ie);
static int intr_event_schedule_thread(struct intr_event *ie, struct trapframe *frame);
@@ -297,6 +299,8 @@
ie->ie_assign_cpu = assign_cpu;
ie->ie_flags = flags;
ie->ie_cpu = NOCPU;
+ ie->ie_stray = 0;
+ ie->ie_intrcnt = 0;
CK_SLIST_INIT(&ie->ie_handlers);
mtx_init(&ie->ie_lock, "intr event", NULL, MTX_DEF);
@@ -304,9 +308,9 @@
vsnprintf(ie->ie_name, sizeof(ie->ie_name), fmt, ap);
va_end(ap);
strlcpy(ie->ie_fullname, ie->ie_name, sizeof(ie->ie_fullname));
- mtx_lock(&event_lock);
+ sx_xlock(&event_lock);
TAILQ_INSERT_TAIL(&event_list, ie, ie_list);
- mtx_unlock(&event_lock);
+ sx_xunlock(&event_lock);
if (event != NULL)
*event = ie;
CTR2(KTR_INTR, "%s: created %s", __func__, ie->ie_name);
@@ -515,11 +519,11 @@
if (ie == NULL)
return (EINVAL);
- mtx_lock(&event_lock);
+ sx_xlock(&event_lock);
mtx_lock(&ie->ie_lock);
if (!CK_SLIST_EMPTY(&ie->ie_handlers)) {
mtx_unlock(&ie->ie_lock);
- mtx_unlock(&event_lock);
+ sx_xunlock(&event_lock);
return (EBUSY);
}
TAILQ_REMOVE(&event_list, ie, ie_list);
@@ -530,7 +534,7 @@
}
#endif
mtx_unlock(&ie->ie_lock);
- mtx_unlock(&event_lock);
+ sx_xunlock(&event_lock);
mtx_destroy(&ie->ie_lock);
free(ie, M_ITHREAD);
return (0);
@@ -1330,9 +1334,9 @@
* handlers as their main argument.
* Return value:
* o 0: everything ok.
- * o EINVAL: stray interrupt.
+ * o non-0: stray interrupt, current count.
*/
-int
+u_long
intr_event_handle(struct intr_event *ie, struct trapframe *frame)
{
struct intr_handler *ih;
@@ -1348,9 +1352,16 @@
intr_prof_stack_use(td, frame);
#endif
- /* An interrupt with no event or handlers is a stray interrupt. */
- if (ie == NULL || CK_SLIST_EMPTY(&ie->ie_handlers))
- return (EINVAL);
+ /* An interrupt with no event is a stray interrupt. */
+ if (ie == NULL)
+ return (~0UL);
+
+ /* Increment the interrupt counter. */
+ atomic_add_long(&ie->ie_intrcnt, 1);
+
+ /* An interrupt with no handlers is a stray interrupt. */
+ if (CK_SLIST_EMPTY(&ie->ie_handlers))
+ return (atomic_fetchadd_long(&ie->ie_stray, 1) + 1);
/*
* Execute fast interrupt handlers directly.
@@ -1452,7 +1463,7 @@
#ifdef notyet
/* The interrupt is not aknowledged by any filter and has no ithread. */
if (!thread && !filter)
- return (EINVAL);
+ return (atomic_fetchadd_long(&ie->ie_stray, 1) + 1);
#endif
return (0);
}
@@ -1612,52 +1623,74 @@
/*
* Sysctls used by systat and others: hw.intrnames and hw.intrcnt.
- * The data for this machine dependent, and the declarations are in machine
- * dependent code. The layout of intrnames and intrcnt however is machine
- * independent.
- *
- * We do not know the length of intrcnt and intrnames at compile time, so
- * calculate things at run time.
+ * The data for this machine independent.
*/
-static int
-sysctl_intrnames(SYSCTL_HANDLER_ARGS)
+int
+intr_event_sysctl_intrnames(SYSCTL_HANDLER_ARGS)
{
- return (sysctl_handle_opaque(oidp, intrnames, sintrnames, req));
-}
+ struct intr_event *ie;
+ u_int len;
+ const char straystr[] = "stray ";
+ int error;
-SYSCTL_PROC(_hw, OID_AUTO, intrnames,
- CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
- sysctl_intrnames, "",
- "Interrupt Names");
+ sx_slock(&event_lock);
+ TAILQ_FOREACH(ie, &event_list, ie_list) {
+ len = strnlen(ie->ie_fullname, sizeof(ie->ie_fullname)) + 1;
+ error = SYSCTL_OUT(req, ie->ie_fullname, len);
+ if (error != 0)
+ goto out;
+
+ error = SYSCTL_OUT(req, straystr, sizeof(straystr) - 1);
+ if (error != 0)
+ goto out;
+ error = SYSCTL_OUT(req, ie->ie_fullname, len);
+ if (error != 0)
+ goto out;
+ }
+out:
+ sx_sunlock(&event_lock);
+ return (error);
+}
-static int
-sysctl_intrcnt(SYSCTL_HANDLER_ARGS)
+int
+intr_event_sysctl_intrcnt(SYSCTL_HANDLER_ARGS)
{
+ struct intr_event *ie;
+ int error = 0;
+ int sz = sizeof(ie->ie_intrcnt);
+ u_long val;
+ void *arg = &val;
#ifdef SCTL_MASK32
- uint32_t *intrcnt32;
- unsigned i;
- int error;
+ uint32_t val32;
if (req->flags & SCTL_MASK32) {
- if (!req->oldptr)
- return (sysctl_handle_opaque(oidp, NULL, sintrcnt / 2, req));
- intrcnt32 = malloc(sintrcnt / 2, M_TEMP, M_NOWAIT);
- if (intrcnt32 == NULL)
- return (ENOMEM);
- for (i = 0; i < sintrcnt / sizeof (u_long); i++)
- intrcnt32[i] = intrcnt[i];
- error = sysctl_handle_opaque(oidp, intrcnt32, sintrcnt / 2, req);
- free(intrcnt32, M_TEMP);
- return (error);
+ sz = sizeof(val32);
+ arg = &val32;
}
#endif
- return (sysctl_handle_opaque(oidp, intrcnt, sintrcnt, req));
-}
-SYSCTL_PROC(_hw, OID_AUTO, intrcnt,
- CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
- sysctl_intrcnt, "",
- "Interrupt Counts");
+ sx_slock(&event_lock);
+ TAILQ_FOREACH(ie, &event_list, ie_list) {
+#ifdef SCTL_MASK32
+ val32 =
+#endif
+ val = ie->ie_intrcnt;
+ error = SYSCTL_OUT(req, arg, sz);
+ if (error != 0)
+ goto out;
+
+#ifdef SCTL_MASK32
+ val32 =
+#endif
+ val = ie->ie_stray;
+ error = SYSCTL_OUT(req, arg, sz);
+ if (error != 0)
+ goto out;
+ }
+out:
+ sx_sunlock(&event_lock);
+ return (error);
+}
#ifdef DDB
/*
@@ -1665,19 +1698,11 @@
*/
DB_SHOW_COMMAND_FLAGS(intrcnt, db_show_intrcnt, DB_CMD_MEMSAFE)
{
- u_long *i;
- char *cp;
- u_int j;
-
- cp = intrnames;
- j = 0;
- for (i = intrcnt; j < (sintrcnt / sizeof(u_long)) && !db_pager_quit;
- i++, j++) {
- if (*cp == '\0')
- break;
- if (*i != 0)
- db_printf("%s\t%lu\n", cp, *i);
- cp += strlen(cp) + 1;
- }
+ struct intr_event *ie;
+
+ for (ie = TAILQ_FIRST(&event_list); ie && !db_pager_quit;
+ ie = TAILQ_NEXT(ie, ie_list))
+ db_printf("%s\t%lu\nstray %s\t%lu\n", ie->ie_fullname,
+ ie->ie_intrcnt, ie->ie_fullname, ie->ie_stray);
}
#endif
diff --git a/sys/kern/subr_intr.c b/sys/kern/subr_intr.c
--- a/sys/kern/subr_intr.c
+++ b/sys/kern/subr_intr.c
@@ -152,7 +152,7 @@
char *intrnames;
size_t sintrcnt;
size_t sintrnames;
-static u_int intrcnt_index;
+u_int nintrcnt;
static struct intr_irqsrc *intr_map_get_isrc(u_int res_id);
static void intr_map_set_isrc(u_int res_id, struct intr_irqsrc *isrc);
@@ -166,7 +166,6 @@
static void
intr_irq_init(void *dummy __unused)
{
- u_int intrcnt_count;
SLIST_INIT(&pic_list);
mtx_init(&pic_list_lock, "intr pic list", NULL, MTX_DEF);
@@ -177,17 +176,15 @@
* - 2 counters for each I/O interrupt.
* - MAXCPU counters for each IPI counters for SMP.
*/
- intrcnt_count = intr_nirq * 2;
+ nintrcnt = 1;
#ifdef SMP
- intrcnt_count += INTR_IPI_COUNT * MAXCPU;
+ nintrcnt += INTR_IPI_COUNT * MAXCPU;
#endif
- intrcnt = mallocarray(intrcnt_count, sizeof(u_long), M_INTRNG,
+ intrcnt = mallocarray(nintrcnt, sizeof(u_long), M_INTRNG,
M_WAITOK | M_ZERO);
- intrnames = mallocarray(intrcnt_count, INTRNAME_LEN, M_INTRNG,
+ intrnames = mallocarray(nintrcnt, INTRNAME_LEN, M_INTRNG,
M_WAITOK | M_ZERO);
- sintrcnt = intrcnt_count * sizeof(u_long);
- sintrnames = intrcnt_count * INTRNAME_LEN;
irq_sources = mallocarray(intr_nirq, sizeof(struct intr_irqsrc*),
M_INTRNG, M_WAITOK | M_ZERO);
}
@@ -201,41 +198,7 @@
INTRNAME_LEN - 1, name);
}
-/*
- * Update name for interrupt source with interrupt event.
- */
-static void
-intrcnt_updatename(struct intr_irqsrc *isrc)
-{
-
- /* QQQ: What about stray counter name? */
- mtx_assert(&isrc_table_lock, MA_OWNED);
- intrcnt_setname(isrc->isrc_event->ie_fullname, isrc->isrc_index);
-}
-
-/*
- * Virtualization for interrupt source interrupt counter increment.
- */
-static inline void
-isrc_increment_count(struct intr_irqsrc *isrc)
-{
-
- if (isrc->isrc_flags & INTR_ISRCF_PPI)
- atomic_add_long(&isrc->isrc_count[0], 1);
- else
- isrc->isrc_count[0]++;
-}
-
-/*
- * Virtualization for interrupt source interrupt stray counter increment.
- */
-static inline void
-isrc_increment_straycount(struct intr_irqsrc *isrc)
-{
-
- isrc->isrc_count[1]++;
-}
-
+#ifdef INTR_SOLO
/*
* Virtualization for interrupt source interrupt name update.
*/
@@ -246,47 +209,15 @@
mtx_assert(&isrc_table_lock, MA_OWNED);
- if (name != NULL) {
+ if (name != NULL)
snprintf(str, INTRNAME_LEN, "%s: %s", isrc->isrc_name, name);
- intrcnt_setname(str, isrc->isrc_index);
- snprintf(str, INTRNAME_LEN, "stray %s: %s", isrc->isrc_name,
- name);
- intrcnt_setname(str, isrc->isrc_index + 1);
- } else {
+ else
snprintf(str, INTRNAME_LEN, "%s:", isrc->isrc_name);
- intrcnt_setname(str, isrc->isrc_index);
- snprintf(str, INTRNAME_LEN, "stray %s:", isrc->isrc_name);
- intrcnt_setname(str, isrc->isrc_index + 1);
- }
-}
-
-/*
- * Virtualization for interrupt source interrupt counters setup.
- */
-static void
-isrc_setup_counters(struct intr_irqsrc *isrc)
-{
- u_int index;
- /*
- * XXX - it does not work well with removable controllers and
- * interrupt sources !!!
- */
- index = atomic_fetchadd_int(&intrcnt_index, 2);
- isrc->isrc_index = index;
- isrc->isrc_count = &intrcnt[index];
- isrc_update_name(isrc, NULL);
-}
-
-/*
- * Virtualization for interrupt source interrupt counters release.
- */
-static void
-isrc_release_counters(struct intr_irqsrc *isrc)
-{
-
- panic("%s: not implemented", __func__);
+ strlcpy(isrc->isrc_event->ie_fullname, str,
+ sizeof(isrc->isrc_event->ie_fullname));
}
+#endif
#ifdef SMP
/*
@@ -298,7 +229,12 @@
u_int index, i;
char str[INTRNAME_LEN];
- index = atomic_fetchadd_int(&intrcnt_index, MAXCPU);
+ index = (u_int)(atomic_fetchadd_ptr(&sintrcnt,
+ sizeof(u_long) * MAXCPU) / sizeof(u_long));
+ if (index >= nintrcnt)
+ panic("overflowed IPI interrupt name table size (index=%u)",
+ index);
+ atomic_add_ptr(&sintrnames, INTRNAME_LEN * MAXCPU);
for (i = 0; i < MAXCPU; i++) {
snprintf(str, INTRNAME_LEN, "cpu%d:%s", i, name);
intrcnt_setname(str, index + i);
@@ -368,8 +304,6 @@
KASSERT(isrc != NULL, ("%s: no source", __func__));
- isrc_increment_count(isrc);
-
#ifdef INTR_SOLO
if (isrc->isrc_filter != NULL) {
int error;
@@ -384,7 +318,6 @@
return (0);
}
- isrc_increment_straycount(isrc);
return (EINVAL);
}
@@ -484,13 +417,7 @@
mtx_unlock(&isrc_table_lock);
return (error);
}
- /*
- * Setup interrupt counters, but not for IPI sources. Those are setup
- * later and only for used ones (up to INTR_IPI_COUNT) to not exhaust
- * our counter pool.
- */
- if ((isrc->isrc_flags & INTR_ISRCF_IPI) == 0)
- isrc_setup_counters(isrc);
+
mtx_unlock(&isrc_table_lock);
return (0);
}
@@ -504,8 +431,6 @@
int error;
mtx_lock(&isrc_table_lock);
- if ((isrc->isrc_flags & INTR_ISRCF_IPI) == 0)
- isrc_release_counters(isrc);
error = isrc_free_irq(isrc);
mtx_unlock(&isrc_table_lock);
return (error);
@@ -721,15 +646,8 @@
return (error);
}
- error = intr_event_add_handler(isrc->isrc_event, name, filter, handler,
- arg, intr_priority(flags), flags, cookiep);
- if (error == 0) {
- mtx_lock(&isrc_table_lock);
- intrcnt_updatename(isrc);
- mtx_unlock(&isrc_table_lock);
- }
-
- return (error);
+ return (intr_event_add_handler(isrc->isrc_event, name, filter, handler,
+ arg, intr_priority(flags), flags, cookiep));
}
/*
@@ -1159,7 +1077,6 @@
if (isrc->isrc_handlers == 0)
PIC_DISABLE_INTR(isrc->isrc_dev, isrc);
PIC_TEARDOWN_INTR(isrc->isrc_dev, isrc, res, data);
- intrcnt_updatename(isrc);
mtx_unlock(&isrc_table_lock);
}
return (error);
@@ -1169,7 +1086,6 @@
intr_describe_irq(device_t dev, struct resource *res, void *cookie,
const char *descr)
{
- int error;
struct intr_irqsrc *isrc;
u_int res_id;
@@ -1191,13 +1107,7 @@
return (0);
}
#endif
- error = intr_event_describe_handler(isrc->isrc_event, cookie, descr);
- if (error == 0) {
- mtx_lock(&isrc_table_lock);
- intrcnt_updatename(isrc);
- mtx_unlock(&isrc_table_lock);
- }
- return (error);
+ return (intr_event_describe_handler(isrc->isrc_event, cookie, descr));
}
#ifdef SMP
@@ -1569,7 +1479,7 @@
if (isrc == NULL)
continue;
- num = isrc->isrc_count != NULL ? isrc->isrc_count[0] : 0;
+ num = isrc->isrc_event != NULL ? isrc->isrc_event->ie_intrcnt : 0;
db_printf("irq%-3u <%s>: cpu %02lx%s cnt %lu\n", i,
isrc->isrc_name, isrc->isrc_cpu.__bits[0],
isrc->isrc_flags & INTR_ISRCF_BOUND ? " (bound)" : "", num);
@@ -1753,3 +1663,53 @@
M_INTRNG, M_WAITOK | M_ZERO);
}
SYSINIT(intr_map_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_map_init, NULL);
+
+/*
+ * Sysctls used by systat and others: hw.intrnames and hw.intrcnt.
+ */
+static int
+sysctl_intrnames(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+
+ error = sysctl_handle_opaque(oidp, intrnames, sintrnames, req);
+ if (error != 0)
+ return (error);
+
+ return (intr_event_sysctl_intrnames(oidp, intrnames, sintrnames, req));
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, intrnames,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_intrnames,
+ "", "Interrupt Names");
+
+static int
+sysctl_intrcnt(SYSCTL_HANDLER_ARGS)
+{
+ int error = 0;
+#ifdef SCTL_MASK32
+ u_int idx;
+ uint32_t val32;
+
+ if (req->flags & SCTL_MASK32)
+ for (idx = 0; idx <= sintrcnt / sizeof(u_long) ; ++idx) {
+ val32 = intrcnt[idx];
+ error = SYSCTL_OUT(req, &val32, sizeof(val32));
+ if (error != 0)
+ return (error);
+ } else
+#endif
+ {
+ error = sysctl_handle_opaque(oidp, intrcnt, sintrcnt, req);
+ if (error != 0)
+ return (error);
+ }
+
+ return (intr_event_sysctl_intrcnt(oidp, intrcnt, sintrcnt, req));
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, intrcnt,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_intrcnt,
+ "", "Interrupt Counts");
diff --git a/sys/powerpc/powerpc/intr_machdep.c b/sys/powerpc/powerpc/intr_machdep.c
--- a/sys/powerpc/powerpc/intr_machdep.c
+++ b/sys/powerpc/powerpc/intr_machdep.c
@@ -93,13 +93,11 @@
struct powerpc_intr {
struct intr_event *event;
- long *cntp;
void *priv; /* PIC-private data */
device_t pic;
u_int irq;
u_int intline;
u_int vector;
- u_int cntindex;
int fwcode;
int ipi;
int pi_domain;
@@ -116,7 +114,6 @@
int base;
};
-static u_int intrcnt_index = 0;
static struct mtx intr_table_lock;
static struct powerpc_intr **powerpc_intrs;
static struct pic piclist[MAX_PICS];
@@ -131,9 +128,9 @@
u_long *intrcnt;
char *intrnames;
-size_t sintrcnt = sizeof(intrcnt);
-size_t sintrnames = sizeof(intrnames);
-int nintrcnt;
+size_t sintrcnt;
+size_t sintrnames;
+u_int nintrcnt;
/*
* Just to start
@@ -172,7 +169,7 @@
powerpc_intrs = mallocarray(num_io_irqs, sizeof(*powerpc_intrs),
M_INTR, M_WAITOK | M_ZERO);
- nintrcnt = 1 + num_io_irqs * 2 + mp_ncpus * 2;
+ nintrcnt = 1 + mp_ncpus * 2;
#ifdef COUNT_IPIS
if (mp_ncpus > 1)
nintrcnt += 8 * mp_ncpus;
@@ -181,11 +178,6 @@
M_ZERO);
intrnames = mallocarray(nintrcnt, MAXCOMLEN + 1, M_INTR, M_WAITOK |
M_ZERO);
- sintrcnt = nintrcnt * sizeof(u_long);
- sintrnames = nintrcnt * (MAXCOMLEN + 1);
-
- intrcnt_setname("???", 0);
- intrcnt_index = 1;
}
/*
* This needs to happen before SI_SUB_CPU
@@ -211,11 +203,12 @@
void
intrcnt_add(const char *name, u_long **countp)
{
- int idx;
+ u_int idx;
- idx = atomic_fetchadd_int(&intrcnt_index, 1);
- KASSERT(idx < nintrcnt, ("intrcnt_add: Interrupt counter index %d/%d"
- "reached nintrcnt : %d", intrcnt_index, idx, nintrcnt));
+ idx = atomic_fetchadd_int(&sintrcnt, sizeof(u_long)) / sizeof(u_long);
+ KASSERT(idx < nintrcnt, ("%s: Interrupt counter index %u reached "
+ "nintrcnt : %u, for \"%s\"", __func__, idx, nintrcnt, name));
+ atomic_add_int(&sintrnames, MAXCOMLEN + 1);
*countp = &intrcnt[idx];
intrcnt_setname(name, idx);
}
@@ -224,7 +217,6 @@
static struct powerpc_intr *
intr_create(u_int irq)
{
- char intrname[16];
struct powerpc_intr *i, *iscan;
int vector;
@@ -244,7 +236,6 @@
}
i->event = NULL;
- i->cntp = NULL;
i->priv = NULL;
i->trig = INTR_TRIGGER_CONFORM;
i->pol = INTR_POLARITY_CONFORM;
@@ -272,10 +263,8 @@
if (iscan == NULL && i->vector != -1) {
powerpc_intrs[i->vector] = i;
- i->cntindex = atomic_fetchadd_int(&intrcnt_index, 1);
- i->cntp = &intrcnt[i->cntindex];
- sprintf(intrname, "irq%u:", i->irq);
- intrcnt_setname(intrname, i->cntindex);
+ snprintf(i->event->ie_fullname, sizeof(i->event->ie_fullname),
+ "irq%u:", i->irq);
nvectors++;
}
mtx_unlock(&intr_table_lock);
@@ -576,9 +565,6 @@
CPU_ZERO(&i->pi_cpuset);
CPU_COPY(&cpuset_domain[domain], &i->pi_cpuset);
}
- mtx_lock(&intr_table_lock);
- intrcnt_setname(i->event->ie_fullname, i->cntindex);
- mtx_unlock(&intr_table_lock);
if (!cold) {
error = powerpc_map_irq(i);
@@ -674,8 +660,6 @@
if (i == NULL)
goto stray;
- (*i->cntp)++;
-
ie = i->event;
KASSERT(ie != NULL, ("%s: interrupt without an event", __func__));
@@ -727,3 +711,53 @@
PIC_UNMASK(i->pic, i->intline, i->priv);
}
+
+/*
+ * Sysctls used by systat and others: hw.intrnames and hw.intrcnt.
+ */
+static int
+sysctl_intrnames(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+
+ error = sysctl_handle_opaque(oidp, intrnames, sintrnames, req);
+ if (error != 0)
+ return (error);
+
+ return (intr_event_sysctl_intrnames(oidp, intrnames, sintrnames, req));
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, intrnames,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_intrnames,
+ "", "Interrupt Names");
+
+static int
+sysctl_intrcnt(SYSCTL_HANDLER_ARGS)
+{
+ int error = 0;
+#ifdef SCTL_MASK32
+ u_int idx;
+ uint32_t val32;
+
+ if (req->flags & SCTL_MASK32)
+ for (idx = 0; idx <= sintrcnt / sizeof(u_long) ; ++idx) {
+ val32 = intrcnt[idx];
+ error = SYSCTL_OUT(req, &val32, sizeof(val32));
+ if (error != 0)
+ return (error);
+ } else
+#endif
+ {
+ error = sysctl_handle_opaque(oidp, intrcnt, sintrcnt, req);
+ if (error != 0)
+ return (error);
+ }
+
+ return (intr_event_sysctl_intrcnt(oidp, intrcnt, sintrcnt, req));
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, intrcnt,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_intrcnt,
+ "", "Interrupt Counts");
diff --git a/sys/sys/interrupt.h b/sys/sys/interrupt.h
--- a/sys/sys/interrupt.h
+++ b/sys/sys/interrupt.h
@@ -34,6 +34,7 @@
#include <sys/_lock.h>
#include <sys/_mutex.h>
#include <sys/ck.h>
+#include <sys/sysctl.h>
struct intr_event;
struct intr_thread;
@@ -126,6 +127,8 @@
int ie_cpu; /* CPU this event is bound to. */
volatile int ie_phase; /* Switched to establish a barrier. */
volatile int ie_active[2]; /* Filters in ISR context. */
+ u_long ie_stray; /* Stray interrupt counter */
+ u_long ie_intrcnt; /* Interrupt counter */
};
/* Interrupt event flags kept in ie_flags. */
@@ -156,12 +159,6 @@
extern struct intr_event *clk_intr_event;
-/* Counts and names for statistics (defined in MD code). */
-extern u_long *intrcnt; /* counts for each device and stray */
-extern char *intrnames; /* string table containing device names */
-extern size_t sintrcnt; /* size of intrcnt table */
-extern size_t sintrnames; /* size of intrnames table */
-
#ifdef DDB
void db_dump_intr_event(struct intr_event *ie, int handlers);
#endif
@@ -182,7 +179,7 @@
int intr_event_describe_handler(struct intr_event *ie, void *cookie,
const char *descr);
int intr_event_destroy(struct intr_event *ie);
-int intr_event_handle(struct intr_event *ie, struct trapframe *frame);
+u_long intr_event_handle(struct intr_event *ie, struct trapframe *frame);
int intr_event_remove_handler(void *cookie);
int intr_event_suspend_handler(void *cookie);
int intr_event_resume_handler(void *cookie);
@@ -196,4 +193,8 @@
void swi_sched(void *cookie, int flags);
int swi_remove(void *cookie);
+/* For handling the core interrupt counters and names */
+extern int intr_event_sysctl_intrnames(SYSCTL_HANDLER_ARGS);
+extern int intr_event_sysctl_intrcnt(SYSCTL_HANDLER_ARGS);
+
#endif
diff --git a/sys/sys/intr.h b/sys/sys/intr.h
--- a/sys/sys/intr.h
+++ b/sys/sys/intr.h
@@ -104,8 +104,6 @@
u_int isrc_flags;
char isrc_name[INTR_ISRC_NAMELEN];
cpuset_t isrc_cpu; /* on which CPUs is enabled */
- u_int isrc_index;
- u_long * isrc_count;
u_int isrc_handlers;
struct intr_event * isrc_event;
#ifdef INTR_SOLO
diff --git a/sys/x86/include/intr.h b/sys/x86/include/intr.h
--- a/sys/x86/include/intr.h
+++ b/sys/x86/include/intr.h
@@ -128,9 +128,6 @@
struct intsrc {
struct pic *is_pic;
struct intr_event *is_event;
- u_long *is_count;
- u_long *is_straycount;
- u_int is_index;
u_int is_handlers;
u_int is_domain;
u_int is_cpu;
diff --git a/sys/x86/isa/atpic.c b/sys/x86/isa/atpic.c
--- a/sys/x86/isa/atpic.c
+++ b/sys/x86/isa/atpic.c
@@ -131,8 +131,6 @@
inthand_t *at_intr, *at_intr_pti;
int at_irq; /* Relative to PIC base. */
enum intr_trigger at_trigger;
- u_long at_count;
- u_long at_straycount;
};
static void atpic_register_sources(struct pic *pic);
@@ -464,8 +462,6 @@
for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) {
if (i == ICU_SLAVEID)
continue;
- ai->at_intsrc.is_count = &ai->at_count;
- ai->at_intsrc.is_straycount = &ai->at_straycount;
setidt(((struct atpic *)ai->at_intsrc.is_pic)->at_intbase +
ai->at_irq, pti ? ai->at_intr_pti : ai->at_intr, SDT_ATPIC,
SEL_KPL, GSEL_ATPIC);
diff --git a/sys/x86/x86/intr_machdep.c b/sys/x86/x86/intr_machdep.c
--- a/sys/x86/x86/intr_machdep.c
+++ b/sys/x86/x86/intr_machdep.c
@@ -76,7 +76,6 @@
typedef void (*mask_fn)(void *);
-static int intrcnt_index;
static struct intsrc **interrupt_sources;
#ifdef SMP
static struct intsrc **interrupt_sorted;
@@ -97,9 +96,9 @@
u_long *intrcnt;
char *intrnames;
-size_t sintrcnt = sizeof(intrcnt);
-size_t sintrnames = sizeof(intrnames);
-int nintrcnt;
+size_t sintrcnt;
+size_t sintrnames;
+u_int nintrcnt;
static MALLOC_DEFINE(M_INTR, "intr", "Interrupt Sources");
@@ -108,8 +107,6 @@
static void intr_init(void *__dummy);
static int intr_pic_registered(struct pic *pic);
static void intrcnt_setname(const char *name, int index);
-static void intrcnt_updatename(struct intsrc *is);
-static void intrcnt_register(struct intsrc *is);
/*
* SYSINIT levels for SI_SUB_INTR:
@@ -176,13 +173,12 @@
#endif
/*
- * - 1 ??? dummy counter.
* - 2 counters for each I/O interrupt.
* - 1 counter for each CPU for lapic timer.
* - 1 counter for each CPU for the Hyper-V vmbus driver.
* - 8 counters for each CPU for IPI counters for SMP.
*/
- nintrcnt = 1 + num_io_irqs * 2 + mp_ncpus * 2;
+ nintrcnt = 1 + mp_ncpus * 2;
#ifdef COUNT_IPIS
if (mp_ncpus > 1)
nintrcnt += 8 * mp_ncpus;
@@ -191,11 +187,6 @@
M_ZERO);
intrnames = mallocarray(nintrcnt, MAXCOMLEN + 1, M_INTR, M_WAITOK |
M_ZERO);
- sintrcnt = nintrcnt * sizeof(u_long);
- sintrnames = nintrcnt * (MAXCOMLEN + 1);
-
- intrcnt_setname("???", 0);
- intrcnt_index = 1;
/*
* NB: intrpic_lock is not held here to avoid LORs due to
@@ -239,7 +230,6 @@
intr_event_destroy(isrc->is_event);
return (EEXIST);
}
- intrcnt_register(isrc);
interrupt_sources[vector] = isrc;
isrc->is_handlers = 0;
sx_xunlock(&intrsrc_lock);
@@ -270,7 +260,6 @@
arg, intr_priority(flags), flags, cookiep);
if (error == 0) {
sx_xlock(&intrsrc_lock);
- intrcnt_updatename(isrc);
isrc->is_handlers++;
if (isrc->is_handlers == 1) {
isrc->is_domain = domain;
@@ -297,7 +286,6 @@
isrc->is_pic->pic_disable_source(isrc, PIC_NO_EOI);
isrc->is_pic->pic_disable_intr(isrc);
}
- intrcnt_updatename(isrc);
sx_xunlock(&intrsrc_lock);
}
return (error);
@@ -328,6 +316,7 @@
{
struct intr_event *ie;
int vector;
+ u_long strays;
/*
* We count software interrupts when we process them. The
@@ -335,7 +324,6 @@
* argument for counting hardware interrupts when they're
* processed too.
*/
- (*isrc->is_count)++;
VM_CNT_INC(v_intr);
ie = isrc->is_event;
@@ -352,12 +340,11 @@
* For stray interrupts, mask and EOI the source, bump the
* stray count, and log the condition.
*/
- if (intr_event_handle(ie, frame) != 0) {
+ if ((strays = intr_event_handle(ie, frame)) != 0) {
isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
- (*isrc->is_straycount)++;
- if (*isrc->is_straycount < INTR_STRAY_LOG_MAX)
+ if (strays < INTR_STRAY_LOG_MAX)
log(LOG_ERR, "stray irq%d\n", vector);
- else if (*isrc->is_straycount == INTR_STRAY_LOG_MAX)
+ else if (strays == INTR_STRAY_LOG_MAX)
log(LOG_CRIT,
"too many stray irq %d's: not logging anymore\n",
vector);
@@ -434,41 +421,16 @@
MAXCOMLEN, name);
}
-static void
-intrcnt_updatename(struct intsrc *is)
-{
-
- intrcnt_setname(is->is_event->ie_fullname, is->is_index);
-}
-
-static void
-intrcnt_register(struct intsrc *is)
-{
- char straystr[MAXCOMLEN + 1];
-
- KASSERT(is->is_event != NULL, ("%s: isrc with no event", __func__));
- mtx_lock_spin(&intrcnt_lock);
- MPASS(intrcnt_index + 2 <= nintrcnt);
- is->is_index = intrcnt_index;
- intrcnt_index += 2;
- snprintf(straystr, MAXCOMLEN + 1, "stray irq%d",
- is->is_pic->pic_vector(is));
- intrcnt_updatename(is);
- is->is_count = &intrcnt[is->is_index];
- intrcnt_setname(straystr, is->is_index + 1);
- is->is_straycount = &intrcnt[is->is_index + 1];
- mtx_unlock_spin(&intrcnt_lock);
-}
-
void
intrcnt_add(const char *name, u_long **countp)
{
mtx_lock_spin(&intrcnt_lock);
- MPASS(intrcnt_index < nintrcnt);
- *countp = &intrcnt[intrcnt_index];
- intrcnt_setname(name, intrcnt_index);
- intrcnt_index++;
+ MPASS(sintrcnt < nintrcnt * sizeof(u_long));
+ *countp = &intrcnt[sintrcnt / sizeof(u_long)];
+ intrcnt_setname(name, sintrcnt / sizeof(u_long));
+ sintrcnt += sizeof(u_long);
+ sintrnames += MAXCOMLEN + 1;
mtx_unlock_spin(&intrcnt_lock);
}
@@ -525,16 +487,11 @@
intr_describe(u_int vector, void *ih, const char *descr)
{
struct intsrc *isrc;
- int error;
isrc = intr_lookup(vector);
if (isrc == NULL)
return (EINVAL);
- error = intr_event_describe_handler(isrc->is_event, ih, descr);
- if (error)
- return (error);
- intrcnt_updatename(isrc);
- return (0);
+ return (intr_event_describe_handler(isrc->is_event, ih, descr));
}
void
@@ -735,12 +692,11 @@
isrc = interrupt_sources[i];
if (isrc == NULL)
continue;
- sbuf_printf(&sbuf, "%s:%d @cpu%d(domain%d): %ld\n",
+ sbuf_printf(&sbuf, "%s @cpu%d(domain%d): %lu\n",
isrc->is_event->ie_fullname,
- isrc->is_index,
isrc->is_cpu,
isrc->is_domain,
- *isrc->is_count);
+ isrc->is_event->ie_intrcnt);
}
sx_sunlock(&intrsrc_lock);
@@ -751,7 +707,7 @@
SYSCTL_PROC(_hw, OID_AUTO, intrs,
CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE,
0, 0, sysctl_hw_intrs, "A",
- "interrupt:number @cpu: count");
+ "interrupt @cpu: count");
/*
* Compare two, possibly NULL, entries in the interrupt source array
@@ -765,7 +721,7 @@
i1 = *(const struct intsrc * const *)one;
i2 = *(const struct intsrc * const *)two;
if (i1 != NULL && i2 != NULL)
- return (*i1->is_count - *i2->is_count);
+ return (i1->is_event->ie_intrcnt - i2->is_event->ie_intrcnt);
if (i1 != NULL)
return (1);
if (i2 != NULL)
@@ -845,3 +801,53 @@
return (PCPU_GET(apic_id));
}
#endif
+
+/*
+ * Sysctls used by systat and others: hw.intrnames and hw.intrcnt.
+ */
+static int
+sysctl_intrnames(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+
+ error = sysctl_handle_opaque(oidp, intrnames, sintrnames, req);
+ if (error != 0)
+ return (error);
+
+ return (intr_event_sysctl_intrnames(oidp, intrnames, sintrnames, req));
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, intrnames,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_intrnames,
+ "", "Interrupt Names");
+
+static int
+sysctl_intrcnt(SYSCTL_HANDLER_ARGS)
+{
+ int error = 0;
+#ifdef SCTL_MASK32
+ u_int idx;
+ uint32_t val32;
+
+ if (req->flags & SCTL_MASK32)
+ for (idx = 0; idx <= sintrcnt / sizeof(u_long) ; ++idx) {
+ val32 = intrcnt[idx];
+ error = SYSCTL_OUT(req, &val32, sizeof(val32));
+ if (error != 0)
+ return (error);
+ } else
+#endif
+ {
+ error = sysctl_handle_opaque(oidp, intrcnt, sintrcnt, req);
+ if (error != 0)
+ return (error);
+ }
+
+ return (intr_event_sysctl_intrcnt(oidp, intrcnt, sintrcnt, req));
+}
+
+SYSCTL_PROC(_hw, OID_AUTO, intrcnt,
+ CTLTYPE_OPAQUE | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
+ sysctl_intrcnt,
+ "", "Interrupt Counts");

File Metadata

Mime Type
text/plain
Expires
Sun, Apr 19, 11:29 PM (5 h, 56 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31807490
Default Alt Text
D36610.id114524.diff (29 KB)

Event Timeline