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);
}