Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 09 Dec 2008 13:33:37 -0700
From:      Scott Long <scottl@samsco.org>
To:        Marcel Moolenaar <xcllnt@mac.com>
Cc:        freebsd-current@freebsd.org, Mike Tancsa <mike@sentex.net>
Subject:   Re: uart vs sio differences ?
Message-ID:  <493ED621.5010006@samsco.org>
In-Reply-To: <0E8F5AD4-A139-413E-A760-A1BEDDF44BAA@mac.com>
References:  <200812081621.mB8GLMxB041498@lava.sentex.ca> <ED8BC24F-EAC3-4266-AF54-4C6262DDC156@mac.com> <200812081906.mB8J6oha042222@lava.sentex.ca> <CF6E0ACA-CCFA-4A35-A88F-C95484309A78@mac.com> <200812082049.mB8KnHSN042710@lava.sentex.ca> <84A7F176-5A74-48AC-859A-C0D4C7CBCB48@mac.com> <7.1.0.9.0.20081208173515.13f62e88@sentex.net> <200812091457.mB9EvLSD047534@lava.sentex.ca> <493EA759.4000504@samsco.org> <0E8F5AD4-A139-413E-A760-A1BEDDF44BAA@mac.com>

next in thread | previous in thread | raw e-mail | index | archive | help
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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?493ED621.5010006>