Module Name:    src
Committed By:   nat
Date:           Fri Feb 24 09:49:49 UTC 2017

Modified Files:
        src/sys/dev: audio.c

Log Message:
Simplify locking.  Hold intr lock only when dealing with sc_pr (mix ring)
or virtual channel 0 (hardware).


To generate a diff of this commit:
cvs rdiff -u -r1.309 -r1.310 src/sys/dev/audio.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/dev/audio.c
diff -u src/sys/dev/audio.c:1.309 src/sys/dev/audio.c:1.310
--- src/sys/dev/audio.c:1.309	Fri Feb 24 07:52:39 2017
+++ src/sys/dev/audio.c	Fri Feb 24 09:49:49 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: audio.c,v 1.309 2017/02/24 07:52:39 skrll Exp $	*/
+/*	$NetBSD: audio.c,v 1.310 2017/02/24 09:49:49 nat Exp $	*/
 
 /*-
  * Copyright (c) 2016 Nathanial Sloss <nathanialsl...@yahoo.com.au>
@@ -148,7 +148,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.309 2017/02/24 07:52:39 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.310 2017/02/24 09:49:49 nat Exp $");
 
 #include "audio.h"
 #if NAUDIO > 0
@@ -206,6 +206,12 @@ int	audiodebug = AUDIO_DEBUG;
 int	audio_idle_timeout = 30;
 #endif
 
+#define HW_LOCK(x)	if (x == SIMPLEQ_FIRST(&sc->sc_audiochan)->vc) \
+				mutex_enter(sc->sc_intr_lock);
+
+#define HW_UNLOCK(x)	if (x == SIMPLEQ_FIRST(&sc->sc_audiochan)->vc) \
+				mutex_exit(sc->sc_intr_lock);
+
 int	audio_blk_ms = AUDIO_BLK_MS;
 
 int	audiosetinfo(struct audio_softc *, struct audio_info *, bool,
@@ -1280,7 +1286,7 @@ audio_setup_pfilters(struct audio_softc 
 	}
 
 	/* Swap in new filters. */
-	mutex_enter(sc->sc_intr_lock);
+	HW_LOCK(vc);
 	memcpy(of, vc->sc_pfilters, sizeof(of));
 	memcpy(os, vc->sc_pstreams, sizeof(os));
 	onfilters = vc->sc_npfilters;
@@ -1298,7 +1304,7 @@ audio_setup_pfilters(struct audio_softc 
 		vc->sc_mpr.s.param = pfilters->filters[0].param;
 		vc->sc_pustream = &vc->sc_pstreams[0];
 	}
-	mutex_exit(sc->sc_intr_lock);
+	HW_UNLOCK(vc);
 
 	/* Destroy old filters. */
 	for (i = 0; i < onfilters; i++) {
@@ -1365,7 +1371,7 @@ audio_setup_rfilters(struct audio_softc 
 	}
 
 	/* Swap in new filters. */
-	mutex_enter(sc->sc_intr_lock);
+	HW_LOCK(vc);
 	memcpy(of, vc->sc_rfilters, sizeof(of));
 	memcpy(os, vc->sc_rstreams, sizeof(os));
 	onfilters = vc->sc_nrfilters;
@@ -1383,7 +1389,7 @@ audio_setup_rfilters(struct audio_softc 
 		vc->sc_mrr.s.param = rfilters->filters[0].param;
 		vc->sc_rustream = &vc->sc_rstreams[rfilters->req_size - 1];
 	}
-	mutex_exit(sc->sc_intr_lock);
+	HW_UNLOCK(vc);
 
 #ifdef AUDIO_DEBUG
 	printf("%s: HW-buffer=%p pustream=%p\n",
@@ -2187,7 +2193,6 @@ audio_open(dev_t dev, struct audio_softc
 	DPRINTF(("audio_open: done sc_mode = 0x%x\n", vc->sc_mode));
 
 	grow_mixer_states(sc, 2);
-	mutex_enter(sc->sc_intr_lock);
 	if (flags & FREAD)
 		sc->sc_recopens++;
 	sc->sc_opens++;
@@ -2195,7 +2200,6 @@ audio_open(dev_t dev, struct audio_softc
 	chan->chan = n;
 	chan->deschan = n;
 	SIMPLEQ_INSERT_TAIL(&sc->sc_audiochan, chan, entries);
-	mutex_exit(sc->sc_intr_lock);
 
 	error = fd_clone(fp, fd, flags, &audio_fileops, chan);
 	KASSERT(error == EMOVEFD);
@@ -2303,7 +2307,9 @@ audio_drain(struct audio_softc *sc, stru
 		cc = cb->blksize - (inp - cb->s.start) % cb->blksize;
 		audio_fill_silence(&cb->s.param, inp, cc);
 		cb->s.inp = audio_stream_add_inp(&cb->s, inp, cc);
+		mutex_exit(sc->sc_intr_lock);
 		error = audiostartp(sc, vc);
+		mutex_enter(sc->sc_intr_lock);
 		if (error)
 			return error;
 	} else if (hw == true) {
@@ -2411,6 +2417,8 @@ audio_close(struct audio_softc *sc, int 
 
 	if (sc->sc_opens == 1 && hw->close != NULL)
 		hw->close(sc->hw_hdl);
+	mutex_exit(sc->sc_intr_lock);
+
 	if (sc->sc_opens == 1) {
 		sc->sc_async_audio = 0;
 		kauth_cred_free(sc->sc_credentials);
@@ -2438,7 +2446,6 @@ audio_close(struct audio_softc *sc, int 
 	sc->sc_opens--;
 	shrink_mixer_states(sc, 2);
 	SIMPLEQ_REMOVE(&sc->sc_audiochan, chan, audio_chan, entries);
-	mutex_exit(sc->sc_intr_lock);
 	mutex_exit(sc->sc_lock);
 	audio_free_ring(sc, &vc->sc_mpr);
 	audio_free_ring(sc, &vc->sc_mrr);
@@ -2510,12 +2517,10 @@ audio_read(struct audio_softc *sc, struc
 		return error;
 	}
 
-	mutex_enter(sc->sc_intr_lock);
 	while (uio->uio_resid > 0 && !error) {
 		while ((used = audio_stream_get_used(vc->sc_rustream)) <= 0) {
 			if (!vc->sc_rbus && !vc->sc_mrr.pause)
 				error = audiostartr(sc, vc);
-			mutex_exit(sc->sc_intr_lock);
 			if (error)
 				return error;
 			if (ioflag & IO_NDELAY)
@@ -2526,7 +2531,6 @@ audio_read(struct audio_softc *sc, struc
 				error = EIO;
 			if (error)
 				return error;
-			mutex_enter(sc->sc_intr_lock);
 		}
 
 		outp = vc->sc_rustream->outp;
@@ -2553,7 +2557,6 @@ audio_read(struct audio_softc *sc, struc
 			(vc->sc_rustream, outp, n);
 		cb->copying = false;
 	}
-	mutex_exit(sc->sc_intr_lock);
 	return error;
 }
 
@@ -2838,7 +2841,6 @@ audio_write(struct audio_softc *sc, stru
 	}
 
 	error = 0;
-	mutex_enter(sc->sc_intr_lock);
 	while (uio->uio_resid > 0 && !error) {
 		/* wait if the first buffer is occupied */
 		while ((used = audio_stream_get_used(vc->sc_pustream)) >=
@@ -2846,7 +2848,6 @@ audio_write(struct audio_softc *sc, stru
 			DPRINTFN(2, ("audio_write: sleep used=%d lowat=%d "
 				     "hiwat=%d\n", used,
 				     cb->usedlow, cb->usedhigh));
-			mutex_exit(sc->sc_intr_lock);
 			if (ioflag & IO_NDELAY)
 				return EWOULDBLOCK;
 			error = audio_waitio(sc, &sc->sc_wchan, vc);
@@ -2854,7 +2855,6 @@ audio_write(struct audio_softc *sc, stru
 				error = EIO;
 			if (error)
 				return error;
-			mutex_enter(sc->sc_intr_lock);
 		}
 		inp = cb->s.inp;
 		cb->copying = true;
@@ -2862,7 +2862,6 @@ audio_write(struct audio_softc *sc, stru
 		used = stream.used;
 
 		/* Write to the sc_pustream as much as possible. */
-		mutex_exit(sc->sc_intr_lock);
 		if (vc->sc_npfilters > 0) {
 			filter = vc->sc_pfilters[0];
 			filter->set_fetcher(filter, &ufetcher.base);
@@ -2881,7 +2880,6 @@ audio_write(struct audio_softc *sc, stru
 			cc = stream.end - stream.start;
 			error = fetcher->fetch_to(sc, fetcher, &stream, cc);
 		}
-		mutex_enter(sc->sc_intr_lock);
 		if (vc->sc_npfilters > 0) {
 			cb->fstamp += ufetcher.last_used
 			    - audio_stream_get_used(vc->sc_pustream);
@@ -2924,7 +2922,6 @@ audio_write(struct audio_softc *sc, stru
 			audio_fill_silence(&cb->s.param, einp, cc);
 		}
 	}
-	mutex_exit(sc->sc_intr_lock);
 
 	return error;
 }
@@ -2994,12 +2991,12 @@ audio_ioctl(dev_t dev, struct audio_soft
 			mutex_exit(sc->sc_intr_lock);
 			return error;
 		}
+		mutex_exit(sc->sc_intr_lock);
 		if ((vc->sc_mode & AUMODE_PLAY) && !vc->sc_pbus && pbus)
 			error = audiostartp(sc, vc);
 		if (!error &&
 		    (vc->sc_mode & AUMODE_RECORD) && !vc->sc_rbus && rbus)
 			error = audiostartr(sc, vc);
-		mutex_exit(sc->sc_intr_lock);
 		break;
 
 	/*
@@ -3019,12 +3016,12 @@ audio_ioctl(dev_t dev, struct audio_soft
 	 */
 	case AUDIO_GETIOFFS:
 		ao = (struct audio_offset *)addr;
-		mutex_enter(sc->sc_intr_lock);
+		HW_LOCK(vc);
 		/* figure out where next DMA will start */
 		stamp = vc->sc_rustream == &vc->sc_mrr.s
 			? vc->sc_mrr.stamp : vc->sc_mrr.fstamp;
 		offs = vc->sc_rustream->inp - vc->sc_rustream->start;
-		mutex_exit(sc->sc_intr_lock);
+		HW_UNLOCK(vc);
 		ao->samples = stamp;
 		ao->deltablks =
 		  (stamp / vc->sc_mrr.blksize) -
@@ -3035,13 +3032,13 @@ audio_ioctl(dev_t dev, struct audio_soft
 
 	case AUDIO_GETOOFFS:
 		ao = (struct audio_offset *)addr;
-		mutex_enter(sc->sc_intr_lock);
+		HW_LOCK(vc);
 		/* figure out where next DMA will start */
 		stamp = vc->sc_pustream == &vc->sc_mpr.s
 			? vc->sc_mpr.stamp : vc->sc_mpr.fstamp;
 		offs = vc->sc_pustream->outp - vc->sc_pustream->start
 			+ vc->sc_mpr.blksize;
-		mutex_exit(sc->sc_intr_lock);
+		HW_UNLOCK(vc);
 		ao->samples = stamp;
 		ao->deltablks =
 		  (stamp / vc->sc_mpr.blksize) -
@@ -3153,7 +3150,7 @@ audio_poll(struct audio_softc *sc, int e
 	DPRINTF(("audio_poll: events=0x%x mode=%d\n", events, vc->sc_mode));
 
 	revents = 0;
-	mutex_enter(sc->sc_intr_lock);
+	HW_LOCK(vc);
 	if (events & (POLLIN | POLLRDNORM)) {
 		used = audio_stream_get_used(vc->sc_rustream);
 		/*
@@ -3180,7 +3177,7 @@ audio_poll(struct audio_softc *sc, int e
 		    (used <= vc->sc_mpr.usedlow))
 			revents |= events & (POLLOUT | POLLWRNORM);
 	}
-	mutex_exit(sc->sc_intr_lock);
+	HW_UNLOCK(vc);
 
 	if (revents == 0) {
 		if (events & (POLLIN | POLLRDNORM))
@@ -3370,17 +3367,13 @@ audio_mmap(struct audio_softc *sc, off_t
 		if (cb != &sc->sc_rr) {
 			audio_fill_silence(&cb->s.param, cb->s.start,
 					   cb->s.bufsize);
-			mutex_enter(sc->sc_intr_lock);
 			vc->sc_pustream = &cb->s;
 			if (!vc->sc_pbus && !vc->sc_mpr.pause)
 				(void)audiostartp(sc, vc);
-			mutex_exit(sc->sc_intr_lock);
 		} else {
-			mutex_enter(sc->sc_intr_lock);
 			vc->sc_rustream = &cb->s;
 			if (!vc->sc_rbus && !sc->sc_rr.pause)
 				(void)audiostartr(sc, vc);
-			mutex_exit(sc->sc_intr_lock);
 		}
 	}
 
@@ -3394,7 +3387,6 @@ audiostartr(struct audio_softc *sc, stru
 {
 
 	KASSERT(mutex_owned(sc->sc_lock));
-	KASSERT(mutex_owned(sc->sc_intr_lock));
 
 	DPRINTF(("audiostartr: start=%p used=%d(hi=%d) mmapped=%d\n",
 		 vc->sc_mrr.s.start, audio_stream_get_used(&vc->sc_mrr.s),
@@ -3404,8 +3396,10 @@ audiostartr(struct audio_softc *sc, stru
 		return EINVAL;
 
 	if (sc->sc_rec_started == false) {
+		mutex_enter(sc->sc_intr_lock);
 		mix_read(sc);
 		cv_broadcast(&sc->sc_rcondvar);
+		mutex_exit(sc->sc_intr_lock);
 	}
 	vc->sc_rbus = true;
 
@@ -3419,7 +3413,6 @@ audiostartp(struct audio_softc *sc, stru
 	int error, used;
 
 	KASSERT(mutex_owned(sc->sc_lock));
-	KASSERT(mutex_owned(sc->sc_intr_lock));
 
 	chan = SIMPLEQ_FIRST(&sc->sc_audiochan);
 	error = 0;
@@ -3440,15 +3433,17 @@ audiostartp(struct audio_softc *sc, stru
 	vc->sc_pbus = true;
 	if (sc->sc_trigger_started == false) {
 		audio_mix(sc);
-		mix_write(sc);
 
 		vc = chan->vc;
 		vc->sc_mpr.s.outp =
 		    audio_stream_add_outp(&vc->sc_mpr.s,
 		      vc->sc_mpr.s.outp, vc->sc_mpr.blksize);
 		audio_mix(sc);
+		mutex_enter(sc->sc_intr_lock);
+		mix_write(sc);
 		mix_write(sc);
 		cv_broadcast(&sc->sc_condvar);
+		mutex_exit(sc->sc_intr_lock);
 	}
 
 	return error;
@@ -3639,7 +3634,9 @@ audio_mix(void *v)
 		if (cb->mmapped) {
 			DPRINTF(("audio_pint: mmapped outp=%p cc=%d inp=%p\n",
 				     cb->s.outp, blksize, cb->s.inp));
+			mutex_enter(sc->sc_intr_lock);
 			mix_func(sc, cb, vc);
+			mutex_exit(sc->sc_intr_lock);
 			continue;
 		}
 
@@ -3731,7 +3728,9 @@ audio_mix(void *v)
 
 		DPRINTFN(5, ("audio_pint: outp=%p cc=%d\n", cb->s.outp,
 			 blksize));
+		mutex_enter(sc->sc_intr_lock);
 		mix_func(sc, cb, vc);
+		mutex_exit(sc->sc_intr_lock);
 		cb->s.outp = audio_stream_add_outp(&cb->s, cb->s.outp, blksize);
 
 		DPRINTFN(2, ("audio_pint: mode=%d pause=%d used=%d lowat=%d\n",
@@ -3747,11 +3746,14 @@ audio_mix(void *v)
 		if (!vc->sc_full_duplex && vc->sc_mode & AUMODE_RECORD)
 				sc->schedule_rih = true;
 	}
+	mutex_enter(sc->sc_intr_lock);
 	if (sc->sc_saturate == true && sc->sc_opens > 1)
 		saturate_func(sc);
 
 	cb = &sc->sc_pr;
-	cb->s.inp = audio_stream_add_inp(&cb->s, cb->s.inp, blksize);
+	if (sc->sc_writeme == true)
+		cb->s.inp = audio_stream_add_inp(&cb->s, cb->s.inp, blksize);
+	mutex_exit(sc->sc_intr_lock);
 
 	kpreempt_disable();
 	if (sc->schedule_wih == true)
@@ -3775,6 +3777,8 @@ audio_rint(void *v)
 
 	sc = v;
 
+	KASSERT(mutex_owned(sc->sc_intr_lock));
+
 	if (sc->sc_dying == true)
 		return;
 
@@ -3833,12 +3837,14 @@ audio_upmix(void *v)
 		cc = blksize;
 		if (cb->s.inp + blksize > cb->s.end)
 			cc = cb->s.end - cb->s.inp;
+		mutex_enter(sc->sc_intr_lock);
 		memcpy(cb->s.inp, sc->sc_rr.s.start, cc);
 		if (cc < blksize && cc != 0) {
 			cc1 = cc;
 			cc = blksize - cc;
 			memcpy(cb->s.start, sc->sc_rr.s.start + cc1, cc);
 		}
+		mutex_exit(sc->sc_intr_lock);
 
 		cc = blksize;
 		recswvol_func(sc, cb, blksize, vc);
@@ -4721,7 +4727,6 @@ cleanup:
 	if (error == 0 && (cleared || pausechange|| reset)) {
 		int init_error;
 
-		mutex_enter(sc->sc_intr_lock);
 		init_error = (pausechange == 1 && reset == 0) ? 0 :
 		    audio_initbufs(sc, vc);
 		if (init_error) goto err;
@@ -4738,7 +4743,6 @@ cleanup:
 		    rbus && !vc->sc_rbus)
 			init_error = audiostartr(sc, vc);
 	err:
-		mutex_exit(sc->sc_intr_lock);
 		if (init_error)
 			return init_error;
 	}
@@ -5251,12 +5255,10 @@ audio_resume(device_t dv, const pmf_qual
 
 		if (vc->sc_lastinfovalid == true)
 			audiosetinfo(sc, &vc->sc_lastinfo, true, vc);
-		mutex_enter(sc->sc_intr_lock);
 		if (vc->sc_pbus == true && !vc->sc_mpr.pause)
 			audiostartp(sc, vc);
 		if (vc->sc_rbus == true && !vc->sc_mrr.pause)
 			audiostartr(sc, vc);
-		mutex_exit(sc->sc_intr_lock);
 	}
 	mutex_exit(sc->sc_lock);
 

Reply via email to