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

Reply via email to