Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 09 Oct 2000 12:30:32 -0700 (PDT)
From:      John Baldwin <jhb@FreeBSD.org>
To:        bde@FreeBSD.org, current@FreeBSD.org
Subject:   sio patch to add mutexes..
Message-ID:  <XFMail.001009123032.jhb@FreeBSD.org>

next in thread | raw e-mail | index | archive | help
Hey gang,

I have some patches to add per-softc spin mutexes to the sio code
in place of the old COM_LOCK.  Since spin mutexes already dink with
interrupts, this also allows all the *_intr() cruft to go away.
Unfortunately, I can't get the current sio to work on any of the boxes
here because DCD is never raised, so I don't know if this breaks
anything, though it doesn't seem to fix my bxoes. :-/  The patch is
availabe at http://www.FreeBSD.org/~jhb/patches/sio.patch, and included
inline here for those w/o web access:

Index: sio.c
===================================================================
RCS file: /home/ncvs/src/sys/isa/sio.c,v
retrieving revision 1.316
diff -u -r1.316 sio.c
--- sio.c       2000/10/05 23:09:54     1.316
+++ sio.c       2000/10/06 06:11:29
@@ -96,12 +96,6 @@
 #endif
 #include <isa/ic/ns16550.h>
 
-/* XXX - this is ok because we only do sio fast interrupts on i386 */
-#ifndef __i386__
-#define disable_intr()
-#define enable_intr()
-#endif
-
 #define        LOTS_OF_EVENTS  64      /* helps separate urgent events from
input */
 
 #define        CALLOUT_MASK            0x80
@@ -284,6 +278,8 @@
         */
        u_char  obuf1[256];
        u_char  obuf2[256];
+
+       struct  mtx intrlock;   /* spin mutex used in the interrupt handler */
 };
 
 #ifdef COM_ESP
@@ -759,7 +755,6 @@
        u_int           flags = device_get_flags(dev);
        int             rid;
        struct resource *port;
-       int             intrsave;
 
        rid = xrid;
        port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
@@ -771,6 +766,7 @@
        com->bst = rman_get_bustag(port);
        com->bsh = rman_get_bushandle(port);
 
+       mtx_init(&com->intrlock, "sio interrupt lock", MTX_SPIN);
 #if 0
        /*
         * XXX this is broken - when we are first called, there are no
@@ -856,9 +852,7 @@
         * but mask them in the processor as well in case there are some
         * (misconfigured) shared interrupts.
         */
-       intrsave = save_intr();
-       disable_intr();
-       COM_LOCK();
+       mtx_enter(&com->intrlock, MTX_SPIN);
 /* EXTRA DELAY? */
 
        /*
@@ -955,9 +949,9 @@
                        CLR_FLAG(dev, COM_C_IIR_TXRDYBUG);
                }
                sio_setreg(com, com_cfcr, CFCR_8BITS);
-               COM_UNLOCK();
-               restore_intr(intrsave);
+               mtx_exit(&com->intrlock, MTX_SPIN);
                bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
+               mtx_destroy(&com->intrlock);
                return (iobase == siocniobase ? 0 : result);
        }
 
@@ -996,8 +990,7 @@
        irqmap[3] = isa_irq_pending();
        failures[9] = (sio_getreg(com, com_iir) & IIR_IMASK) - IIR_NOPEND;
 
-       COM_UNLOCK();
-       restore_intr(intrsave);
+       mtx_exit(&com->intrlock, MTX_SPIN);
 
        irqs = irqmap[1] & ~irqmap[0];
        if (bus_get_resource(idev, SYS_RES_IRQ, 0, &xirq, NULL) == 0 &&
@@ -1026,6 +1019,7 @@
                        break;
                }
        bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
+       mtx_destroy(&com->intrlock);
        return (iobase == siocniobase ? 0 : result);
 }
 
@@ -1116,7 +1110,6 @@
        int             rid;
        struct resource *port;
        int             ret;
-       int             intrstate;
 
        rid = xrid;
        port = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
@@ -1155,6 +1148,7 @@
        com->tx_fifo_size = 1;
        com->obufs[0].l_head = com->obuf1;
        com->obufs[1].l_head = com->obuf2;
+       mtx_init(&com->intrlock, "sio interrupt lock", MTX_SPIN);
 
        com->data_port = iobase + com_data;
        com->int_id_port = iobase + com_iir;
@@ -1185,10 +1179,8 @@
                com->it_in.c_ispeed = com->it_in.c_ospeed = comdefaultrate;
        } else
                com->it_in.c_ispeed = com->it_in.c_ospeed = TTYDEF_SPEED;
-       intrstate = save_intr();
        if (siosetwater(com, com->it_in.c_ispeed) != 0) {
-               COM_UNLOCK();
-               restore_intr(intrstate);
+               mtx_exit(&com->intrlock, MTX_SPIN);
                /*
                 * Leave i/o resources allocated if this is a `cn'-level
                 * console, so that other devices can't snarf them.
@@ -1197,8 +1189,7 @@
                        bus_release_resource(dev, SYS_RES_IOPORT, rid, port);
                return (ENOMEM);
        }
-       COM_UNLOCK();
-       restore_intr(intrstate);
+       mtx_exit(&com->intrlock, MTX_SPIN);
        termioschars(&com->it_in);
        com->it_out = com->it_in;
 
@@ -1432,8 +1423,6 @@
                        goto out;
                }
        } else {
-               int     intrsave;
-
                /*
                 * The device isn't open, so there are no conflicts.
                 * Initialize it.  Initialization is done twice in many
@@ -1493,9 +1482,7 @@
                        }
                }
 
-               intrsave = save_intr();
-               disable_intr();
-               COM_LOCK();
+               mtx_enter(&com->intrlock, MTX_SPIN);
                (void) inb(com->line_status_port);
                (void) inb(com->data_port);
                com->prev_modem_status = com->last_modem_status
@@ -1507,8 +1494,7 @@
                        outb(com->intr_ctl_port, IER_ERXRDY | IER_ETXRDY
                                                | IER_ERLS | IER_EMSC);
                }
-               COM_UNLOCK();
-               restore_intr(intrsave);
+               mtx_exit(&com->intrlock, MTX_SPIN);
                /*
                 * Handle initial DCD.  Callout devices get a fake initial
                 * DCD (trapdoor DCD).  If we are callout, then any sleeping
@@ -1730,7 +1716,8 @@
 }
 
 /*
- * Call this function with COM_LOCK.  It will return with the lock still held.
+ * Call this function with the per-softc intrlock mutex held.  It will return
+ * with the lock still held.
  */
 static void
 sioinput(com)
@@ -1741,7 +1728,6 @@
        u_char          line_status;
        int             recv_data;
        struct tty      *tp;
-       int             intrsave;
 
        buf = com->ibuf;
        tp = com->tp;
@@ -1764,9 +1750,7 @@
                         * semantics instead of the save-and-disable semantics
                         * that are used everywhere else.
                         */
-                       intrsave = save_intr();
-                       COM_UNLOCK();
-                       enable_intr();
+                       mtx_exit(&com->intrlock, MTX_SPIN);
                        incc = com->iptr - buf;
                        if (tp->t_rawq.c_cc + incc > tp->t_ihiwat
                            && (com->state & CS_RTS_IFLOW
@@ -1787,8 +1771,7 @@
                                tp->t_lflag &= ~FLUSHO;
                                comstart(tp);
                        }
-                       restore_intr(intrsave);
-                       COM_LOCK();
+                       mtx_enter(&com->intrlock, MTX_SPIN);
                } while (buf < com->iptr);
        } else {
                do {
@@ -1797,9 +1780,7 @@
                         * semantics instead of the save-and-disable semantics
                         * that are used everywhere else.
                         */
-                       intrsave = save_intr();
-                       COM_UNLOCK();
-                       enable_intr();
+                       mtx_exit(&com->intrlock, MTX_SPIN);
                        line_status = buf[com->ierroff];
                        recv_data = *buf++;
                        if (line_status
@@ -1814,8 +1795,7 @@
                                        recv_data |= TTY_PE;
                        }
                        (*linesw[tp->t_line].l_rint)(recv_data, tp);
-                       restore_intr(intrsave);
-                       COM_LOCK();
+                       mtx_enter(&com->intrlock, MTX_SPIN);
                } while (buf < com->iptr);
        }
        com_events -= (com->iptr - com->ibuf);
@@ -1835,14 +1815,17 @@
 siointr(arg)
        void            *arg;
 {
+       struct com_s    *com;
+
 #ifndef COM_MULTIPORT
-       COM_LOCK();
-       siointr1((struct com_s *) arg);
-       COM_UNLOCK();
+       com = (struct com_s *)arg;
+
+       mtx_enter(&com->intrlock, MTX_SPIN);
+       siointr1(com);
+       mtx_exit(&com->intrlock, MTX_SPIN);
 #else /* COM_MULTIPORT */
        bool_t          possibly_more_intrs;
        int             unit;
-       struct com_s    *com;
 
        /*
         * Loop until there is no activity on any port.  This is necessary
@@ -1851,15 +1834,11 @@
         * devices, then the edge from one may be lost because another is
         * on.
         */
-       COM_LOCK();
        do {
                possibly_more_intrs = FALSE;
                for (unit = 0; unit < sio_numunits; ++unit) {
                        com = com_addr(unit);
-                       /*
-                        * XXX COM_LOCK();
-                        * would it work here, or be counter-productive?
-                        */
+                       mtx_enter(&com->intrlock, MTX_SPIN);
                        if (com != NULL 
                            && !com->gone
                            && (inb(com->int_id_port) & IIR_IMASK)
@@ -1867,10 +1846,9 @@
                                siointr1(com);
                                possibly_more_intrs = TRUE;
                        }
-                       /* XXX COM_UNLOCK(); */
+                       mtx_exit(&com->intrlock, MTX_SPIN);
                }
        } while (possibly_more_intrs);
-       COM_UNLOCK();
 #endif /* COM_MULTIPORT */
 }
 
@@ -2264,7 +2242,6 @@
 siopoll()
 {
        int             unit;
-       int             intrsave;
 
        if (com_events == 0)
                return;
@@ -2283,9 +2260,7 @@
                         * Discard any events related to never-opened or
                         * going-away devices.
                         */
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&com->intrlock, MTX_SPIN);
                        incc = com->iptr - com->ibuf;
                        com->iptr = com->ibuf;
                        if (com->state & CS_CHECKMSR) {
@@ -2293,43 +2268,33 @@
                                com->state &= ~CS_CHECKMSR;
                        }
                        com_events -= incc;
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&com->intrlock, MTX_SPIN);
                        continue;
                }
                if (com->iptr != com->ibuf) {
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&com->intrlock, MTX_SPIN);
                        sioinput(com);
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&com->intrlock, MTX_SPIN);
                }
                if (com->state & CS_CHECKMSR) {
                        u_char  delta_modem_status;
 
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&com->intrlock, MTX_SPIN);
                        delta_modem_status = com->last_modem_status
                                             ^ com->prev_modem_status;
                        com->prev_modem_status = com->last_modem_status;
                        com_events -= LOTS_OF_EVENTS;
                        com->state &= ~CS_CHECKMSR;
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&com->intrlock, MTX_SPIN);
                        if (delta_modem_status & MSR_DCD)
                                (*linesw[tp->t_line].l_modem)
                                        (tp, com->prev_modem_status & MSR_DCD);
                }
                if (com->state & CS_ODONE) {
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&com->intrlock, MTX_SPIN);
                        com_events -= LOTS_OF_EVENTS;
                        com->state &= ~CS_ODONE;
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&com->intrlock, MTX_SPIN);
                        if (!(com->state & CS_BUSY)
                            && !(com->extra_state & CSE_BUSYCHECK)) {
                                timeout(siobusycheck, com, hz / 100);
@@ -2357,7 +2322,6 @@
        u_char          dlbl;
        int             s;
        int             unit;
-       int             intrsave;
 
        /* do historical conversions */
        if (t->c_ispeed == 0)
@@ -2429,7 +2393,6 @@
         * the speed change atomically.  Keeping interrupts disabled is
         * especially important while com_data is hidden.
         */
-       intrsave = save_intr();
        (void) siosetwater(com, t->c_ispeed);
 
        if (divisor != 0) {
@@ -2517,8 +2480,7 @@
        if (com->state >= (CS_BUSY | CS_TTGO))
                siointr1(com);
 
-       COM_UNLOCK();
-       restore_intr(intrsave);
+       mtx_exit(&com->intrlock, MTX_SPIN);
        splx(s);
        comstart(tp);
        if (com->ibufold != NULL) {
@@ -2529,8 +2491,8 @@
 }
 
 /*
- * This function must be called with interrupts enabled and the com_lock
- * unlocked.  It will return with interrupts disabled and the com_lock locked.
+ * This function must be called with the per-softc interrupt mutex released
+ * and will return with it obtained.
  */
 static int
 siosetwater(com, speed)
@@ -2552,8 +2514,7 @@
        for (ibufsize = 128; ibufsize < cp4ticks;)
                ibufsize <<= 1;
        if (ibufsize == com->ibufsize) {
-               disable_intr();
-               COM_LOCK();
+               mtx_enter(&com->intrlock, MTX_SPIN);
                return (0);
        }
 
@@ -2563,8 +2524,7 @@
         */
        ibuf = malloc(2 * ibufsize, M_DEVBUF, M_NOWAIT);
        if (ibuf == NULL) {
-               disable_intr();
-               COM_LOCK();
+               mtx_enter(&com->intrlock, MTX_SPIN);
                return (ENOMEM);
        }
 
@@ -2582,8 +2542,7 @@
         * Read current input buffer, if any.  Continue with interrupts
         * disabled.
         */
-       disable_intr();
-       COM_LOCK();
+       mtx_enter(&com->intrlock, MTX_SPIN);
        if (com->iptr != com->ibuf)
                sioinput(com);
 
@@ -2612,16 +2571,13 @@
        struct com_s    *com;
        int             s;
        int             unit;
-       int             intrsave;
 
        unit = DEV_TO_UNIT(tp->t_dev);
        com = com_addr(unit);
        if (com == NULL)
                return;
        s = spltty();
-       intrsave = save_intr();
-       disable_intr();
-       COM_LOCK();
+       mtx_enter(&com->intrlock, MTX_SPIN);
        if (tp->t_state & TS_TTSTOP)
                com->state &= ~CS_TTGO;
        else
@@ -2634,8 +2590,7 @@
                    && com->state & CS_RTS_IFLOW)
                        outb(com->modem_ctl_port, com->mcr_image |= MCR_RTS);
        }
-       COM_UNLOCK();
-       restore_intr(intrsave);
+       mtx_exit(&com->intrlock, MTX_SPIN);
        if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
                ttwwakeup(tp);
                splx(s);
@@ -2651,9 +2606,7 @@
                                                  sizeof com->obuf1);
                        com->obufs[0].l_next = NULL;
                        com->obufs[0].l_queued = TRUE;
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&com->intrlock, MTX_SPIN);
                        if (com->state & CS_BUSY) {
                                qp = com->obufq.l_next;
                                while ((next = qp->l_next) != NULL)
@@ -2665,8 +2618,7 @@
                                com->obufq.l_next = &com->obufs[0];
                                com->state |= CS_BUSY;
                        }
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&com->intrlock, MTX_SPIN);
                }
                if (tp->t_outq.c_cc != 0 && !com->obufs[1].l_queued) {
                        com->obufs[1].l_tail
@@ -2674,9 +2626,7 @@
                                                  sizeof com->obuf2);
                        com->obufs[1].l_next = NULL;
                        com->obufs[1].l_queued = TRUE;
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&com->intrlock, MTX_SPIN);
                        if (com->state & CS_BUSY) {
                                qp = com->obufq.l_next;
                                while ((next = qp->l_next) != NULL)
@@ -2688,18 +2638,14 @@
                                com->obufq.l_next = &com->obufs[1];
                                com->state |= CS_BUSY;
                        }
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&com->intrlock, MTX_SPIN);
                }
                tp->t_state |= TS_BUSY;
        }
-       intrsave = save_intr();
-       disable_intr();
-       COM_LOCK();
+       mtx_enter(&com->intrlock, MTX_SPIN);
        if (com->state >= (CS_BUSY | CS_TTGO))
                siointr1(com);  /* fake interrupt to start output */
-       COM_UNLOCK();
-       restore_intr(intrsave);
+       mtx_exit(&com->intrlock, MTX_SPIN);
        ttwwakeup(tp);
        splx(s);
 }
@@ -2710,14 +2656,11 @@
        int             rw;
 {
        struct com_s    *com;
-       int             intrsave;
 
        com = com_addr(DEV_TO_UNIT(tp->t_dev));
        if (com == NULL || com->gone)
                return;
-       intrsave = save_intr();
-       disable_intr();
-       COM_LOCK();
+       mtx_enter(&com->intrlock, MTX_SPIN);
        if (rw & FWRITE) {
                if (com->hasfifo)
 #ifdef COM_ESP
@@ -2744,8 +2687,7 @@
                com_events -= (com->iptr - com->ibuf);
                com->iptr = com->ibuf;
        }
-       COM_UNLOCK();
-       restore_intr(intrsave);
+       mtx_exit(&com->intrlock, MTX_SPIN);
        comstart(tp);
 }
 
@@ -2757,7 +2699,6 @@
 {
        int     mcr;
        int     msr;
-       int     intrsave;
 
        if (how == DMGET) {
                bits = TIOCM_LE;        /* XXX - always enabled while open */
@@ -2789,9 +2730,7 @@
                mcr |= MCR_RTS;
        if (com->gone)
                return(0);
-       intrsave = save_intr();
-       disable_intr();
-       COM_LOCK();
+       mtx_enter(&com->intrlock, MTX_SPIN);
        switch (how) {
        case DMSET:
                outb(com->modem_ctl_port,
@@ -2804,8 +2743,7 @@
                outb(com->modem_ctl_port, com->mcr_image &= ~mcr);
                break;
        }
-       COM_UNLOCK();
-       restore_intr(intrsave);
+       mtx_exit(&com->intrlock, MTX_SPIN);
        return (0);
 }
 
@@ -2853,7 +2791,6 @@
 {
        struct com_s    *com;
        int             unit;
-       int             intrsave;
 
        sio_timeout_handle = timeout(comwakeup, (void *)NULL, sio_timeout);
 
@@ -2865,12 +2802,9 @@
                com = com_addr(unit);
                if (com != NULL && !com->gone
                    && (com->state >= (CS_BUSY | CS_TTGO) || com->poll)) {
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&com->intrlock, MTX_SPIN);
                        siointr1(com);
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&com->intrlock, MTX_SPIN);
                }
        }
 
@@ -2892,13 +2826,10 @@
                        u_int   delta;
                        u_long  total;
 
-                       intrsave = save_intr();
-                       disable_intr();
-                       COM_LOCK();
+                       mtx_enter(&com->intrlock, MTX_SPIN);
                        delta = com->delta_error_counts[errnum];
                        com->delta_error_counts[errnum] = 0;
-                       COM_UNLOCK();
-                       restore_intr(intrsave);
+                       mtx_exit(&com->intrlock, MTX_SPIN);
                        if (delta == 0)
                                continue;
                        total = com->error_counts[errnum] += delta;

-- 

John Baldwin <jhb@FreeBSD.org> -- http://www.FreeBSD.org/~jhb/
PGP Key: http://www.baldwin.cx/~john/pgpkey.asc
"Power Users Use the Power to Serve!"  -  http://www.FreeBSD.org/


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?XFMail.001009123032.jhb>