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>