ath / 802.11n performance issues and timer code
Attilio Rao
attilio at freebsd.org
Tue Sep 27 13:57:55 UTC 2011
2011/9/27 John Baldwin <jhb at freebsd.org>:
> On Monday, September 26, 2011 11:36:26 pm Adrian Chadd wrote:
>> .. and as a follow up (and cc'ing attillo and freebsd-mips, in case
>> it's relevant to other platforms and there's a MIPS specific thing to
>> fix):
>>
>> * 2128: mi_switch to idle
>> * 2129: kern_clocksource.c:762 - ie, cpu_idleclock() has been called
>> * 2130: the ath interrupt comes in
>> * 2134: it's skipped for now as the idle thread is in a critical section
>> * 2136: kern_clocksource.c:266 - ie, getnextcpuevent(), inside
> cpu_idleclock().
>>
>> What I bet is happening is this race between the critical section +
>> cpu_idleclock() and the ath0 interrupt:
>>
>> * idle gets scheduled
>> * critical_enter() is called in the mips cpu_idle() routine
>> * the ath interrupt comes in here and gets handled, but since we're in
>> a critical section, it won't preempt things
>> * the cpu_idleclock() code completes without releasing the preemption,
>> and the only thing that wakes up from that wait is the next interrupt
>> (clock, arge0, etc.)
>
> I think this is a mips-specific bug, though it may be well to audit all the
> cpu_idle() implementations. On x86 the idle hooks all check sched_runnable()
> with interrupts disabled and then atomically re-enable interrupts and sleep
> only if that is false, e.g.:
>
> static void
> cpu_idle_hlt(int busy)
> {
> int *state;
>
> state = (int *)PCPU_PTR(monitorbuf);
> *state = STATE_SLEEPING;
> /*
> * We must absolutely guarentee that hlt is the next instruction
> * after sti or we introduce a timing window.
> */
> disable_intr();
> if (sched_runnable())
> enable_intr();
> else
> __asm __volatile("sti; hlt");
> *state = STATE_RUNNING;
> }
>
> I don't know if it is possible to do the same thing with the mips "wait"
> instruction.
After thinking about it I think this check is unnecessary.
sti, infact, doesn't enable interrupts before hlt (it just sets IF=1)
but interrupts can fire only after hlt, thus I don't think a
preemption or interrupts firing there can be possible.
This patch:
http://www.freebsd.org/~attilio/stihlt.patch
removes the check and also replaces simple 'hlt' instruction insertion
in C code with the already defined halt().
I still have to go through Adrian's e-mails so I'm not sure if the
logic you post is going to help him or not, but this is my thinking on
the x86 implementation (specifically).
Comments?
Attilio
--
Peace can only be achieved by understanding - A. Einstein
More information about the freebsd-current
mailing list