uart vs sio differences ?
Scott Long
scottl at samsco.org
Tue Dec 9 20:33:42 UTC 2008
Marcel Moolenaar wrote:
>
> On Dec 9, 2008, at 9:14 AM, Scott Long wrote:
>
>> That aside, I think what needs to happen is for the driver to use the
>> interrupt handler to pull the bytes out of the hardware and into an
>> internal lockless ring buffer, then schedule the swi to process the ring
>> buffer.
>
> The uart(4) driver is exactly doing what you describe.
>
Yup, my mistake. However, I think that the semaphore spinwait in
uart_sched_softih() is the source of the problems here. Imagine a
a timeline scenario like this (in 8-CURRENT):
CPU0 CPU1
irq4
uart_intr()
UART_RECEIVE()
uart_sched_softih()
check ttypend
swi_sched()
uart_swi
uart_tty_intr()
clear ttypend
tty_lock()
<sleep wait for lock>
irq4
uart_intr()
UART_RECEIVE()
uart_sched_softih()
check ttypend
swi_sched()
irq4
uart_intr()
UART_RECEIVE()
uart_sched_softif()
check ttypend
<spin for ttypend to clear from the previous interrupt>
<uart fifo overruns>
With FreeBSD 6 and 7, it's even worse because Giant can be
contended on before ttypend is cleared. But in either case,
what you've effectively done here is created a home-rolled spinlock
that comes after a sleep lock, so the time-critical interrupt
handler is now slaved to the slow swi handler, completely defeating
the benefits of having a fast handler (and also defeating WITNESS checks
against this kind of problem).
You really don't need the home-rolled semaphore. You already atomically
read and write the variable, so you can just have uart_tty_intr()
continue to loop around to check if it changes. Or since you already
have a nice lockless ring buffer, you could just extend it also store
each pending flag update.
Scott
More information about the freebsd-current
mailing list