Module Name: src Committed By: tsutsui Date: Fri Mar 21 16:58:54 UTC 2014
Modified Files: src/sys/arch/x68k/dev: event.c event_var.h kbd.c ms.c Log Message: Replace tsleep(9)/wakeup(9) with condvar(9) as practice. Also replace malloc(9) with kmem_alloc(9). Pevent more possible races. Tested on both console and Xserver on X68030. To generate a diff of this commit: cvs rdiff -u -r1.13 -r1.14 src/sys/arch/x68k/dev/event.c cvs rdiff -u -r1.9 -r1.10 src/sys/arch/x68k/dev/event_var.h cvs rdiff -u -r1.38 -r1.39 src/sys/arch/x68k/dev/kbd.c cvs rdiff -u -r1.31 -r1.32 src/sys/arch/x68k/dev/ms.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x68k/dev/event.c diff -u src/sys/arch/x68k/dev/event.c:1.13 src/sys/arch/x68k/dev/event.c:1.14 --- src/sys/arch/x68k/dev/event.c:1.13 Sat Mar 1 14:16:50 2008 +++ src/sys/arch/x68k/dev/event.c Fri Mar 21 16:58:54 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: event.c,v 1.13 2008/03/01 14:16:50 rmind Exp $ */ +/* $NetBSD: event.c,v 1.14 2014/03/21 16:58:54 tsutsui Exp $ */ /* * Copyright (c) 1992, 1993 @@ -45,16 +45,18 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: event.c,v 1.13 2008/03/01 14:16:50 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: event.c,v 1.14 2014/03/21 16:58:54 tsutsui Exp $"); #include <sys/param.h> #include <sys/fcntl.h> -#include <sys/malloc.h> +#include <sys/kmem.h> #include <sys/proc.h> #include <sys/systm.h> #include <sys/vnode.h> #include <sys/select.h> #include <sys/poll.h> +#include <sys/mutex.h> +#include <sys/condvar.h> #include <machine/vuid_event.h> #include <x68k/dev/event_var.h> @@ -63,13 +65,15 @@ __KERNEL_RCSID(0, "$NetBSD: event.c,v 1. * Initialize a firm_event queue. */ void -ev_init(struct evvar *ev) +ev_init(struct evvar *ev, const char *name, kmutex_t *mtx) { ev->ev_get = ev->ev_put = 0; - ev->ev_q = malloc((u_long)EV_QSIZE * sizeof(struct firm_event), - M_DEVBUF, M_WAITOK|M_ZERO); + ev->ev_q = kmem_zalloc((size_t)EV_QSIZE * sizeof(struct firm_event), + KM_SLEEP); selinit(&ev->ev_sel); + ev->ev_lock = mtx; + cv_init(&ev->ev_cv, name); } /* @@ -79,8 +83,9 @@ void ev_fini(struct evvar *ev) { + cv_destroy(&ev->ev_cv); seldestroy(&ev->ev_sel); - free(ev->ev_q, M_DEVBUF); + kmem_free(ev->ev_q, (size_t)EV_QSIZE * sizeof(struct firm_event)); } /* @@ -90,23 +95,23 @@ ev_fini(struct evvar *ev) int ev_read(struct evvar *ev, struct uio *uio, int flags) { - int s, n, cnt, error; + int n, cnt, put, error; /* * Make sure we can return at least 1. */ if (uio->uio_resid < sizeof(struct firm_event)) return (EMSGSIZE); /* ??? */ - s = splev(); + mutex_enter(ev->ev_lock); while (ev->ev_get == ev->ev_put) { if (flags & IO_NDELAY) { - splx(s); + mutex_exit(ev->ev_lock); return (EWOULDBLOCK); } - ev->ev_wanted = 1; - error = tsleep((void *)ev, PEVENT | PCATCH, "firm_event", 0); - if (error) { - splx(s); + ev->ev_wanted = true; + error = cv_wait_sig(&ev->ev_cv, ev->ev_lock); + if (error != 0) { + mutex_exit(ev->ev_lock); return (error); } } @@ -118,7 +123,8 @@ ev_read(struct evvar *ev, struct uio *ui cnt = EV_QSIZE - ev->ev_get; /* events in [get..QSIZE) */ else cnt = ev->ev_put - ev->ev_get; /* events in [get..put) */ - splx(s); + put = ev->ev_put; + mutex_exit(ev->ev_lock); n = howmany(uio->uio_resid, sizeof(struct firm_event)); if (cnt > n) cnt = n; @@ -131,7 +137,7 @@ ev_read(struct evvar *ev, struct uio *ui * is anything there to move. */ if ((ev->ev_get = (ev->ev_get + cnt) % EV_QSIZE) != 0 || - n == 0 || error || (cnt = ev->ev_put) == 0) + n == 0 || error || (cnt = put) == 0) return (error); if (cnt > n) cnt = n; @@ -144,9 +150,9 @@ ev_read(struct evvar *ev, struct uio *ui int ev_poll(struct evvar *ev, int events, struct lwp *l) { - int s, revents = 0; + int revents = 0; - s = splev(); + mutex_enter(ev->ev_lock); if (events & (POLLIN | POLLRDNORM)) { if (ev->ev_get == ev->ev_put) selrecord(l, &ev->ev_sel); @@ -154,38 +160,60 @@ ev_poll(struct evvar *ev, int events, st revents |= events & (POLLIN | POLLRDNORM); } revents |= events & (POLLOUT | POLLWRNORM); - splx(s); + mutex_exit(ev->ev_lock); return (revents); } +void +ev_wakeup(struct evvar *ev) +{ + + mutex_enter(ev->ev_lock); + selnotify(&ev->ev_sel, 0, 0); + if (ev->ev_wanted) { + ev->ev_wanted = false; + cv_signal(&ev->ev_cv); + } + mutex_exit(ev->ev_lock); + + if (ev->ev_async) { + mutex_enter(proc_lock); + psignal(ev->ev_io, SIGIO); + mutex_exit(proc_lock); + } +} + static void filt_evrdetach(struct knote *kn) { struct evvar *ev = kn->kn_hook; - int s; - s = splev(); + mutex_enter(ev->ev_lock); SLIST_REMOVE(&ev->ev_sel.sel_klist, kn, knote, kn_selnext); - splx(s); + mutex_exit(ev->ev_lock); } static int filt_evread(struct knote *kn, long hint) { struct evvar *ev = kn->kn_hook; + int rv = 1; - if (ev->ev_get == ev->ev_put) - return (0); - - if (ev->ev_get < ev->ev_put) - kn->kn_data = ev->ev_put - ev->ev_get; - else - kn->kn_data = (EV_QSIZE - ev->ev_get) + - ev->ev_put; + mutex_enter(ev->ev_lock); + if (ev->ev_get == ev->ev_put) { + rv = 0; + } else { + if (ev->ev_get < ev->ev_put) + kn->kn_data = ev->ev_put - ev->ev_get; + else + kn->kn_data = (EV_QSIZE - ev->ev_get) + + ev->ev_put; - kn->kn_data *= sizeof(struct firm_event); + kn->kn_data *= sizeof(struct firm_event); + } + mutex_exit(ev->ev_lock); - return (1); + return rv; } static const struct filterops ev_filtops = @@ -195,7 +223,6 @@ int ev_kqfilter(struct evvar *ev, struct knote *kn) { struct klist *klist; - int s; switch (kn->kn_filter) { case EVFILT_READ: @@ -209,9 +236,9 @@ ev_kqfilter(struct evvar *ev, struct kno kn->kn_hook = ev; - s = splev(); + mutex_enter(ev->ev_lock); SLIST_INSERT_HEAD(klist, kn, kn_selnext); - splx(s); + mutex_exit(ev->ev_lock); return (0); } Index: src/sys/arch/x68k/dev/event_var.h diff -u src/sys/arch/x68k/dev/event_var.h:1.9 src/sys/arch/x68k/dev/event_var.h:1.10 --- src/sys/arch/x68k/dev/event_var.h:1.9 Wed Aug 15 19:13:58 2012 +++ src/sys/arch/x68k/dev/event_var.h Fri Mar 21 16:58:54 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: event_var.h,v 1.9 2012/08/15 19:13:58 tsutsui Exp $ */ +/* $NetBSD: event_var.h,v 1.10 2014/03/21 16:58:54 tsutsui Exp $ */ /* * Copyright (c) 1992, 1993 @@ -54,31 +54,19 @@ struct evvar { volatile u_int ev_put; /* put (write) index (modified by interrupt) */ struct selinfo ev_sel; /* process selecting */ struct proc *ev_io; /* process that opened queue (can get SIGIO) */ - char ev_wanted; /* wake up on input ready */ - char ev_async; /* send SIGIO on input ready */ + bool ev_wanted; /* wake up on input ready */ + bool ev_async; /* send SIGIO on input ready */ struct firm_event *ev_q;/* circular buffer (queue) of events */ + kmutex_t *ev_lock; /* lock from the parent device */ + kcondvar_t ev_cv; /* condvar(9) to delever signal */ }; -#define splev() spltty() - -#define EV_WAKEUP(ev) { \ - selnotify(&(ev)->ev_sel, 0, 0); \ - if ((ev)->ev_wanted) { \ - (ev)->ev_wanted = 0; \ - wakeup((void *)(ev)); \ - } \ - if ((ev)->ev_async) { \ - mutex_enter(proc_lock); \ - psignal((ev)->ev_io, SIGIO); \ - mutex_exit(proc_lock); \ - } \ -} - -void ev_init(struct evvar *); +void ev_init(struct evvar *, const char *, kmutex_t *); void ev_fini(struct evvar *); int ev_read(struct evvar *, struct uio *, int); int ev_select(struct evvar *, int, struct lwp *); int ev_poll(struct evvar *, int, struct lwp *); +void ev_wakeup(struct evvar *); int ev_kqfilter(struct evvar *, struct knote *); /* Index: src/sys/arch/x68k/dev/kbd.c diff -u src/sys/arch/x68k/dev/kbd.c:1.38 src/sys/arch/x68k/dev/kbd.c:1.39 --- src/sys/arch/x68k/dev/kbd.c:1.38 Sun Mar 16 05:20:26 2014 +++ src/sys/arch/x68k/dev/kbd.c Fri Mar 21 16:58:54 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: kbd.c,v 1.38 2014/03/16 05:20:26 dholland Exp $ */ +/* $NetBSD: kbd.c,v 1.39 2014/03/21 16:58:54 tsutsui Exp $ */ /* * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kbd.c,v 1.38 2014/03/16 05:20:26 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kbd.c,v 1.39 2014/03/21 16:58:54 tsutsui Exp $"); #include "ite.h" #include "bell.h" @@ -50,6 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: kbd.c,v 1.38 #include <sys/cpu.h> #include <sys/bus.h> #include <sys/intr.h> +#include <sys/mutex.h> #include <arch/x68k/dev/intiovar.h> #include <arch/x68k/dev/mfp.h> @@ -63,9 +64,11 @@ __KERNEL_RCSID(0, "$NetBSD: kbd.c,v 1.38 #include <machine/vuid_event.h> struct kbd_softc { + device_t sc_dev; int sc_event_mode; /* if true, collect events, else pass to ite */ struct evvar sc_events; /* event queue state */ void *sc_softintr_cookie; + kmutex_t sc_lock; }; void kbdenable(int); @@ -123,11 +126,10 @@ kbdattach(device_t parent, device_t self { struct kbd_softc *sc = device_private(self); struct mfp_softc *mfp = device_private(parent); - int s; kbd_attached = 1; - - s = spltty(); + sc->sc_dev = self; + mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_HIGH); /* MFP interrupt #12 is for USART receive buffer full */ intio_intr_establish(mfp->sc_intr + 12, "kbd", kbdintr, sc); @@ -137,7 +139,6 @@ kbdattach(device_t parent, device_t self kbdenable(1); sc->sc_event_mode = 0; sc->sc_events.ev_io = 0; - splx(s); aprint_normal("\n"); } @@ -191,7 +192,7 @@ kbdopen(dev_t dev, int flags, int mode, if (k->sc_events.ev_io) return (EBUSY); k->sc_events.ev_io = l->l_proc; - ev_init(&k->sc_events); + ev_init(&k->sc_events, device_xname(k->sc_dev), &k->sc_lock); return (0); } @@ -324,7 +325,7 @@ static int kbdgetoff = 0; int kbdintr(void *arg) { - u_char c, st; + uint8_t c, st; struct kbd_softc *sc = arg; struct firm_event *fe; int put; @@ -368,18 +369,19 @@ void kbdsoftint(void *arg) /* what if ite is not configured? */ { struct kbd_softc *sc = arg; - int s; - - s = spltty(); if (sc->sc_event_mode) - EV_WAKEUP(&sc->sc_events); + ev_wakeup(&sc->sc_events); - while(kbdgetoff < kbdputoff) + mutex_enter(&sc->sc_lock); + while (kbdgetoff < kbdputoff) { + mutex_exit(&sc->sc_lock); ite_filter(kbdbuf[kbdgetoff++ & KBDBUFMASK]); + mutex_enter(&sc->sc_lock); + } kbdgetoff = kbdputoff = 0; - splx(s); + mutex_exit(&sc->sc_lock); } void Index: src/sys/arch/x68k/dev/ms.c diff -u src/sys/arch/x68k/dev/ms.c:1.31 src/sys/arch/x68k/dev/ms.c:1.32 --- src/sys/arch/x68k/dev/ms.c:1.31 Sun Mar 16 05:20:26 2014 +++ src/sys/arch/x68k/dev/ms.c Fri Mar 21 16:58:54 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ms.c,v 1.31 2014/03/16 05:20:26 dholland Exp $ */ +/* $NetBSD: ms.c,v 1.32 2014/03/21 16:58:54 tsutsui Exp $ */ /* * Copyright (c) 1992, 1993 @@ -45,7 +45,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ms.c,v 1.31 2014/03/16 05:20:26 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ms.c,v 1.32 2014/03/21 16:58:54 tsutsui Exp $"); #include <sys/param.h> #include <sys/conf.h> @@ -57,6 +57,7 @@ __KERNEL_RCSID(0, "$NetBSD: ms.c,v 1.31 #include <sys/tty.h> #include <sys/device.h> #include <sys/signalvar.h> +#include <sys/mutex.h> #include <dev/ic/z8530reg.h> #include <machine/z8530var.h> @@ -132,6 +133,7 @@ struct ms_softc { */ volatile int ms_ready; /* event queue is ready */ struct evvar ms_events; /* event queue state */ + kmutex_t ms_lock; } ms_softc; static int ms_match(device_t, cfdata_t, void *); @@ -203,10 +205,11 @@ ms_attach(device_t parent, device_t self struct zsc_softc *zsc = device_private(parent); struct zs_chanstate *cs; cfdata_t cf; - int reset, s; + int reset; ms->ms_dev = self; callout_init(&ms->ms_modem_ch, 0); + mutex_init(&ms->ms_lock, MUTEX_DEFAULT, IPL_SERIAL); cf = device_cfdata(self); cs = zsc->zsc_cs[1]; @@ -215,7 +218,6 @@ ms_attach(device_t parent, device_t self ms->ms_cs = cs; /* Initialize the speed, etc. */ - s = splzs(); /* May need reset... */ reset = ZSWR9_B_RESET; zs_write_reg(cs, 9, reset); @@ -224,7 +226,6 @@ ms_attach(device_t parent, device_t self cs->cs_preg[4] = ZSWR4_CLK_X16 | ZSWR4_TWOSB; (void)zs_set_speed(cs, MS_BPS); zs_loadchannelregs(cs); - splx(s); /* Initialize translator. */ ms->ms_ready = 0; @@ -250,7 +251,7 @@ msopen(dev_t dev, int flags, int mode, s if (ms->ms_events.ev_io) return EBUSY; ms->ms_events.ev_io = l->l_proc; - ev_init(&ms->ms_events); /* may cause sleep */ + ev_init(&ms->ms_events, device_xname(ms->ms_dev), &ms->ms_lock); ms->ms_ready = 1; /* start accepting events */ ms->ms_rts = 1; @@ -464,7 +465,7 @@ out: if (any) { ms->ms_ub = ub; ms->ms_events.ev_put = put; - EV_WAKEUP(&ms->ms_events); + ev_wakeup(&ms->ms_events); } } @@ -557,26 +558,23 @@ static void ms_softint(struct zs_chanstate *cs) { struct ms_softc *ms; - int get, c, s; + int get, c; int intr_flags; u_short ring_data; ms = cs->cs_private; - /* Atomically get and clear flags. */ - s = splzs(); + mutex_enter(&ms->ms_lock); intr_flags = ms->ms_intr_flags; ms->ms_intr_flags = 0; - /* Now lower to spltty for the rest. */ - (void) spltty(); - /* * Copy data from the receive ring to the event layer. */ get = ms->ms_rbget; while (get != ms->ms_rbput) { ring_data = ms->ms_rbuf[get]; + mutex_exit(&ms->ms_lock); get = (get + 1) & MS_RX_RING_MASK; /* low byte of ring_data is rr1 */ @@ -592,7 +590,10 @@ ms_softint(struct zs_chanstate *cs) /* Pass this up to the "middle" layer. */ ms_input(ms, c); + mutex_enter(&ms->ms_lock); } + mutex_exit(&ms->ms_lock); + if (intr_flags & INTR_RX_OVERRUN) { log(LOG_ERR, "%s: input overrun\n", device_xname(ms->ms_dev)); @@ -613,10 +614,10 @@ ms_softint(struct zs_chanstate *cs) */ log(LOG_ERR, "%s: status interrupt?\n", device_xname(ms->ms_dev)); + mutex_enter(&ms->ms_lock); cs->cs_rr0_delta = 0; + mutex_exit(&ms->ms_lock); } - - splx(s); } @@ -643,12 +644,11 @@ void ms_modem(void *arg) { struct ms_softc *ms = arg; - int s; if (!ms->ms_ready) return; - s = splzs(); + mutex_enter(&ms->ms_lock); if (ms->ms_nodata++ > 250) { /* XXX */ log(LOG_ERR, "%s: no data for 5 secs. resetting.\n", @@ -670,6 +670,6 @@ ms_modem(void *arg) ms_trigger(ms->ms_cs, ms->ms_rts); } - (void) splx(s); + mutex_exit(&ms->ms_lock); callout_reset(&ms->ms_modem_ch, 2, ms_modem, ms); }