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. ScottReceived 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