svn commit: r225860 - user/adrian/if_ath_tx/sys/mips/mips
Adrian Chadd
adrian at FreeBSD.org
Thu Sep 29 03:10:42 UTC 2011
Author: adrian
Date: Thu Sep 29 03:10:42 2011
New Revision: 225860
URL: http://svn.freebsd.org/changeset/base/225860
Log:
The MIPS cpu_idle() routine is unfortunately buggy now that
mav's eventtimer code has gone into the tree.
If an interrupt comes in after critical_enter() is called but
before "wait" occurs, the interrupt will be handled but it
won't:
* preempt the current idle thread, if PREEMPTION is enabled and
you're using the 4BSD scheduler;
* won't interrupt "wait", because it occured before it;
* won't be handled until the next interrupt that occurs after
the "wait" instruction is entered.
So the issues with if_arge and if_ath can be traced down to
a race with this particular behaviour in MIPS cpu_idle().
The interrupt would be posted but not handled until another
interrupt triggers things.
I've tried doing what is done in i386 -
* interrupts are disabled
* sched_runnable() is checked - if it's runnable, skip
calling wait and instead reenable interrupts
* otherwise atomically enable interrupts and call hlt.
If an interrupt has come in and scheduled a netisr or
taskqueue call, it'll (hopefully!) trip sched_runnable() and
thus skip the wait.
The atomic nature of "sti; hlt" is apparently documented
for the i386. This way there's no race where an interrupt
comes in before the hlt and doesn't wake it up.
Now, I've tried the same for MIPS but it doesn't seem to
fix things. The behaviour of wait is unfortunately implementation
dependent and someone who is much more well versed in the art
of MIPS hackery will have to fix it.
So for now, I've #if 0'ed the whole thing and left cpu_idle
to just do nothing. This fixes all the issues I've been seeing
and allows me to acheive 230mbit UDP RX/TX and 150mbit
TCP TX/RX without TX/RX queue servicing issues. Whatever is left
is due to ath interrupt handling and packet scheduling.
Modified:
user/adrian/if_ath_tx/sys/mips/mips/machdep.c
Modified: user/adrian/if_ath_tx/sys/mips/mips/machdep.c
==============================================================================
--- user/adrian/if_ath_tx/sys/mips/mips/machdep.c Thu Sep 29 02:57:08 2011 (r225859)
+++ user/adrian/if_ath_tx/sys/mips/mips/machdep.c Thu Sep 29 03:10:42 2011 (r225860)
@@ -488,20 +488,33 @@ spinlock_exit(void)
void
cpu_idle(int busy)
{
+#if 0
+ register_t m;
+
KASSERT((mips_rd_status() & MIPS_SR_INT_IE) != 0,
("interrupts disabled in idle process."));
KASSERT((mips_rd_status() & MIPS_INT_MASK) != 0,
("all interrupts masked in idle process."));
+ m = intr_disable();
if (!busy) {
critical_enter();
cpu_idleclock();
}
- __asm __volatile ("wait");
+
+ if (sched_runnable())
+ intr_restore(m);
+ else {
+ /* XXX not atomic! */
+ intr_restore(m);
+ __asm __volatile ("wait\n");
+ }
+
if (!busy) {
cpu_activeclock();
critical_exit();
}
+#endif
}
int
More information about the svn-src-user
mailing list