summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2007-11-21 04:03:51 +0000
committerscottl <scottl@FreeBSD.org>2007-11-21 04:03:51 +0000
commitb607c8d8ad8a9a7639a87f1bc13821a2294feffa (patch)
tree1c728d282e4c2d3e4989c71f176b996bc9fbb90d /sys
parentdb332cba551507129323c839351afcb5f28060d5 (diff)
downloadFreeBSD-src-b607c8d8ad8a9a7639a87f1bc13821a2294feffa.zip
FreeBSD-src-b607c8d8ad8a9a7639a87f1bc13821a2294feffa.tar.gz
Extend critical section coverage in the low-level interrupt handlers to
include the ithread scheduling step. Without this, a preemption might occur in between the interrupt getting masked and the ithread getting scheduled. Since the interrupt handler runs in the context of curthread, the scheudler might see it as having a such a low priority on a busy system that it doesn't get to run for a _long_ time, leaving the interrupt stranded in a disabled state. The only way that the preemption can happen is by a fast/filter handler triggering a schduling event earlier in the handler, so this problem can only happen for cases where an interrupt is being shared by both a fast/filter handler and an ithread handler. Unfortunately, it seems to be common for this sharing to happen with network and USB devices, for example. This fixes many of the mysterious TCP session timeouts and NIC watchdogs that were being reported. Many thanks to Sam Lefler for getting to the bottom of this problem. Reviewed by: jhb, jeff, silby
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/amd64/intr_machdep.c2
-rw-r--r--sys/i386/i386/intr_machdep.c2
-rw-r--r--sys/ia64/ia64/interrupt.c2
-rw-r--r--sys/powerpc/powerpc/intr_machdep.c2
-rw-r--r--sys/sparc64/sparc64/intr_machdep.c2
5 files changed, 5 insertions, 5 deletions
diff --git a/sys/amd64/amd64/intr_machdep.c b/sys/amd64/amd64/intr_machdep.c
index 3dc1361..9e151ff 100644
--- a/sys/amd64/amd64/intr_machdep.c
+++ b/sys/amd64/amd64/intr_machdep.c
@@ -390,13 +390,13 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
else
isrc->is_pic->pic_eoi_source(isrc);
- critical_exit();
/* Schedule the ithread if needed. */
if (thread) {
error = intr_event_schedule_thread(ie);
KASSERT(error == 0, ("bad stray interrupt"));
}
+ critical_exit();
td->td_intr_nesting_level--;
}
#endif
diff --git a/sys/i386/i386/intr_machdep.c b/sys/i386/i386/intr_machdep.c
index a07ee77..b1d8db9 100644
--- a/sys/i386/i386/intr_machdep.c
+++ b/sys/i386/i386/intr_machdep.c
@@ -391,13 +391,13 @@ intr_execute_handlers(struct intsrc *isrc, struct trapframe *frame)
isrc->is_pic->pic_disable_source(isrc, PIC_EOI);
else
isrc->is_pic->pic_eoi_source(isrc);
- critical_exit();
/* Schedule the ithread if needed. */
if (thread) {
error = intr_event_schedule_thread(ie);
KASSERT(error == 0, ("bad stray interrupt"));
}
+ critical_exit();
td->td_intr_nesting_level--;
}
#endif
diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c
index 5460c59..5d30566 100644
--- a/sys/ia64/ia64/interrupt.c
+++ b/sys/ia64/ia64/interrupt.c
@@ -441,7 +441,6 @@ ia64_dispatch_intr(void *frame, u_int vector)
thread = 1;
}
}
- critical_exit();
if (thread) {
ia64_intr_mask((void *)(uintptr_t)vector);
@@ -449,6 +448,7 @@ ia64_dispatch_intr(void *frame, u_int vector)
KASSERT(error == 0, ("%s: impossible stray", __func__));
} else
ia64_intr_eoi((void *)(uintptr_t)vector);
+ critical_exit();
#endif
}
diff --git a/sys/powerpc/powerpc/intr_machdep.c b/sys/powerpc/powerpc/intr_machdep.c
index 7daaf23..7653347 100644
--- a/sys/powerpc/powerpc/intr_machdep.c
+++ b/sys/powerpc/powerpc/intr_machdep.c
@@ -280,7 +280,6 @@ powerpc_dispatch_intr(u_int vector, struct trapframe *tf)
sched = 1;
}
}
- critical_exit();
if (sched) {
PIC_MASK(pic, i->irq);
@@ -289,6 +288,7 @@ powerpc_dispatch_intr(u_int vector, struct trapframe *tf)
__func__));
} else
PIC_EOI(pic, i->irq);
+ critical_exit();
#endif
return;
diff --git a/sys/sparc64/sparc64/intr_machdep.c b/sys/sparc64/sparc64/intr_machdep.c
index aa9a38a..735b4c0 100644
--- a/sys/sparc64/sparc64/intr_machdep.c
+++ b/sys/sparc64/sparc64/intr_machdep.c
@@ -286,7 +286,6 @@ intr_execute_handlers(void *cookie)
}
if (!thread)
intr_enable_eoi(iv);
- critical_exit();
/* Schedule a heavyweight interrupt process. */
if (thread)
@@ -295,6 +294,7 @@ intr_execute_handlers(void *cookie)
error = EINVAL;
else
error = 0;
+ critical_exit();
if (error == EINVAL)
#else
if (intr_event_handle(iv->iv_event, NULL) != 0)
OpenPOWER on IntegriCloud