summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2013-01-19 00:50:12 +0000
committerian <ian@FreeBSD.org>2013-01-19 00:50:12 +0000
commit87dd3ff9a4d64b9a26b151e08efe00bffebf9b88 (patch)
tree6cbe49297c729b138c137e3a77a8e8b5e2c36593
parenta1e34841434a947a5784c4c395e887c0faa16543 (diff)
downloadFreeBSD-src-87dd3ff9a4d64b9a26b151e08efe00bffebf9b88.zip
FreeBSD-src-87dd3ff9a4d64b9a26b151e08efe00bffebf9b88.tar.gz
Eliminate the need for an intermediate array of indices into the arrays of
interrupt counts and names, by making the names into an array of fixed-length strings that can be directly indexed. This eliminates extra memory accesses on every interrupt to increment the counts. As a side effect, it also fixes a bug that would corrupt the names data if a name was longer than MAXCOMLEN, which led to incorrect vmstat -i output. Approved by: cognet (mentor)
-rw-r--r--sys/arm/arm/intr.c36
-rw-r--r--sys/arm/arm/machdep.c1
-rw-r--r--sys/arm/include/intr.h1
3 files changed, 26 insertions, 12 deletions
diff --git a/sys/arm/arm/intr.c b/sys/arm/arm/intr.c
index e79e44c..18a52a73 100644
--- a/sys/arm/arm/intr.c
+++ b/sys/arm/arm/intr.c
@@ -50,23 +50,40 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <machine/cpu.h>
+#define INTRNAME_LEN (MAXCOMLEN + 1)
+
typedef void (*mask_fn)(void *);
static struct intr_event *intr_events[NIRQ];
-static int intrcnt_tab[NIRQ];
-static int intrcnt_index = 0;
-static int last_printed = 0;
void arm_handler_execute(struct trapframe *, int);
void (*arm_post_filter)(void *) = NULL;
+/*
+ * Pre-format intrnames into an array of fixed-size strings containing spaces.
+ * This allows us to avoid the need for an intermediate table of indices into
+ * the names and counts arrays, while still meeting the requirements and
+ * assumptions of vmstat(8) and the kdb "show intrcnt" command, the two
+ * consumers of this data.
+ */
+void
+arm_intrnames_init()
+{
+ int i;
+
+ memset(intrnames, ' ', NIRQ * INTRNAME_LEN);
+ for (i = 0; i < NIRQ; ++i)
+ intrnames[i * INTRNAME_LEN - 1] = 0;
+}
+
void
arm_setup_irqhandler(const char *name, driver_filter_t *filt,
void (*hand)(void*), void *arg, int irq, int flags, void **cookiep)
{
struct intr_event *event;
int error;
+ char namebuf[INTRNAME_LEN];
if (irq < 0 || irq >= NIRQ)
return;
@@ -78,14 +95,9 @@ arm_setup_irqhandler(const char *name, driver_filter_t *filt,
if (error)
return;
intr_events[irq] = event;
- last_printed +=
- snprintf(intrnames + last_printed,
- MAXCOMLEN + 1,
- "irq%d: %s", irq, name);
- last_printed++;
- intrcnt_tab[irq] = intrcnt_index;
- intrcnt_index++;
-
+ snprintf(namebuf, sizeof(namebuf), "irq%d: %s", irq, name);
+ sprintf(intrnames + INTRNAME_LEN * irq, "%-*s",
+ INTRNAME_LEN - 1, namebuf);
}
intr_event_add_handler(event, name, filt, hand, arg,
intr_priority(flags), flags, cookiep);
@@ -122,7 +134,7 @@ arm_handler_execute(struct trapframe *frame, int irqnb)
PCPU_INC(cnt.v_intr);
i = -1;
while ((i = arm_get_next_irq(i)) != -1) {
- intrcnt[intrcnt_tab[i]]++;
+ intrcnt[i]++;
event = intr_events[i];
if (intr_event_handle(event, frame) != 0) {
/* XXX: Log stray IRQs */
diff --git a/sys/arm/arm/machdep.c b/sys/arm/arm/machdep.c
index a1b5a8f..5c4d92c 100644
--- a/sys/arm/arm/machdep.c
+++ b/sys/arm/arm/machdep.c
@@ -1474,6 +1474,7 @@ initarm(struct arm_boot_params *abp)
init_proc0(kernelstack.pv_va);
+ arm_intrnames_init();
arm_vector_init(ARM_VECTORS_HIGH, ARM_VEC_ALL);
arm_dump_avail_init(memsize, sizeof(dump_avail) / sizeof(dump_avail[0]));
pmap_bootstrap(freemempos, pmap_bootstrap_lastaddr, &kernel_l1pt);
diff --git a/sys/arm/include/intr.h b/sys/arm/include/intr.h
index 45e36e9..9392969 100644
--- a/sys/arm/include/intr.h
+++ b/sys/arm/include/intr.h
@@ -70,6 +70,7 @@
int arm_get_next_irq(int);
void arm_mask_irq(uintptr_t);
void arm_unmask_irq(uintptr_t);
+void arm_intrnames_init(void);
void arm_setup_irqhandler(const char *, int (*)(void*), void (*)(void*),
void *, int, int, void **);
int arm_remove_irqhandler(int, void *);
OpenPOWER on IntegriCloud