Re: uart vs sio differences ?

From: Scott Long <scottl_at_samsco.org>
Date: Tue, 09 Dec 2008 13:33:37 -0700
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
Received on Tue Dec 09 2008 - 19:33:42 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:39:38 UTC