PERFORCE change 103113 for review
Paolo Pisati
piso at FreeBSD.org
Thu Aug 3 13:22:51 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=103113
Change 103113 by piso at piso_newluxor on 2006/08/03 13:22:23
First implementation of interrupt storm logic for filters:
in case an interrupt come, and no filters claim it (and we
don't have any ithread_only handler on that line),
throttle the line (mask the interrupt and mark the source) and
kick off a timeout once per second.
Timeout function (when called) will check all the interrupts:
if any of these interrupt is marked, check if it is
still pending else unmask/unmark the source. If the interrupt
is still pending, call filters and if any of them claim the
interrupt, unmask/unmark it. Else, if no filter claims the
interrupt, increase the timeout threshold for next check.
TODO:
-The code is still MD, but i would like to make it MI.
-we need tunable timeout tresholds (upper & lower).
-filters are called with a NULL frame parameter, while
some of them expect to receive a valid trapframe...
-i should call callout_drain() but i can't find a place
where to do that: i guess we don't do cleanup in this case,
case if we need to drain the callout, it means we are
shutting down the box, right?
Affected files ...
.. //depot/projects/soc2006/intr_filter/i386/i386/intr_machdep.c#8 edit
Differences ...
==== //depot/projects/soc2006/intr_filter/i386/i386/intr_machdep.c#8 (text+ko) ====
@@ -45,6 +45,7 @@
#include <sys/lock.h>
#include <sys/ktr.h>
#include <sys/kernel.h>
+#include <sys/limits.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/syslog.h>
@@ -63,6 +64,9 @@
static struct intsrc *interrupt_sources[NUM_IO_INTS];
static struct mtx intr_table_lock;
+static struct callout callout_handle;
+static int backoff = 1;
+
#ifdef SMP
static int assign_cpu;
@@ -165,6 +169,57 @@
return (isrc->is_pic->pic_config_intr(isrc, trig, pol));
}
+static struct intsrc *
+walk_intr_src(void) {
+ static int i = 0;
+
+ for (; i<NUM_IO_INTS; i++) {
+ if (interrupt_sources[i] != NULL)
+ return (interrupt_sources[i]);
+ }
+ i = 0;
+ return (NULL);
+}
+
+static void
+stray_detection(void *arg __unused)
+{
+ struct intsrc *isrc;
+ struct intr_event *ie;
+ int thread;
+
+ /* analyze all the interrupt sources... */
+ while ((isrc = walk_intr_src()) != NULL) {
+ ie = isrc->is_event;
+ /* is this interrupt marked as being throttled? */
+ if (ie != NULL && ie->ie_count == INT_MAX) {
+ /* and is the interrupt still pending? */
+ if (isrc->is_pic->pic_source_pending(isrc)) {
+ /*
+ * yes, it's still pending: call filters...
+ */
+ thread = intr_filter_loop(ie, NULL /* XXX frame */ );
+ if (thread & FILTER_STRAY) {
+ /*
+ * no filter claimed the intr,
+ * backoff with a longer timeout
+ */
+ backoff++; // XXX we need thresholds...
+ callout_reset(&callout_handle, hz*backoff,
+ &stray_detection, NULL);
+ continue;
+ }
+ }
+ /*
+ * a filter claimed the intr, or the intr was not
+ * pending anymore: unmask it
+ */
+ ie->ie_count = 0;
+ isrc->is_pic->pic_enable_source(isrc);
+ }
+ }
+}
+
void
intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
{
@@ -225,6 +280,15 @@
isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
critical_exit();
+
+ /* Interrupt storm logic */
+ if (thread & FILTER_STRAY) {
+ ie->ie_count = INT_MAX;
+ mtx_lock_spin(&intr_table_lock);
+ callout_reset(&callout_handle, hz, &stray_detection, NULL);
+ mtx_unlock_spin(&intr_table_lock);
+ }
+
/* Schedule the ithread if needed. */
if (thread & FILTER_SCHEDULE_THREAD) {
error = intr_event_schedule_thread(ie);
@@ -309,6 +373,8 @@
intrcnt_setname("???", 0);
intrcnt_index = 1;
mtx_init(&intr_table_lock, "intr table", NULL, MTX_SPIN);
+ callout_init_mtx(&callout_handle, &intr_table_lock, 0);
+ // XXX - we don't drain the callout...
}
SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL)
More information about the p4-projects
mailing list