Module Name:    src
Committed By:   isaki
Date:           Sat Mar  7 06:25:57 UTC 2020

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

Log Message:
Split sc_lock and sc_exlock.
Most (probably all) malloc/free (or routines which may sleep) now can be
called without holding mutex.
Pointed out by riastradh@.


To generate a diff of this commit:
cvs rdiff -u -r1.62 -r1.63 src/sys/dev/audio/audio.c
cvs rdiff -u -r1.10 -r1.11 src/sys/dev/audio/audiovar.h

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/audio.c
diff -u src/sys/dev/audio/audio.c:1.62 src/sys/dev/audio/audio.c:1.63
--- src/sys/dev/audio/audio.c:1.62	Wed Mar  4 14:19:41 2020
+++ src/sys/dev/audio/audio.c	Sat Mar  7 06:25:57 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: audio.c,v 1.62 2020/03/04 14:19:41 isaki Exp $	*/
+/*	$NetBSD: audio.c,v 1.63 2020/03/07 06:25:57 isaki Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -142,7 +142,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.62 2020/03/04 14:19:41 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.63 2020/03/07 06:25:57 isaki Exp $");
 
 #ifdef _KERNEL_OPT
 #include "audio.h"
@@ -497,8 +497,10 @@ static void audio_mixer_restore(struct a
 static void audio_softintr_rd(void *);
 static void audio_softintr_wr(void *);
 
-static int  audio_enter_exclusive(struct audio_softc *);
-static void audio_exit_exclusive(struct audio_softc *);
+static int audio_exlock_mutex_enter(struct audio_softc *);
+static void audio_exlock_mutex_exit(struct audio_softc *);
+static int audio_exlock_enter(struct audio_softc *);
+static void audio_exlock_exit(struct audio_softc *);
 static struct audio_softc *audio_file_enter(audio_file_t *, struct psref *);
 static void audio_file_exit(struct audio_softc *, struct psref *);
 static int audio_track_waitio(struct audio_softc *, audio_track_t *);
@@ -898,6 +900,7 @@ audioattach(device_t parent, device_t se
 	sc->hw_hdl = hdlp;
 	sc->hw_dev = parent;
 
+	sc->sc_exlock = 1;
 	sc->sc_blk_ms = AUDIO_BLK_MS;
 	SLIST_INIT(&sc->sc_files);
 	cv_init(&sc->sc_exlockcv, "audiolk");
@@ -981,10 +984,8 @@ audioattach(device_t parent, device_t se
 
 	/* Init hardware. */
 	/* hw_probe() also validates [pr]hwfmt.  */
-	mutex_enter(sc->sc_lock);
 	error = audio_hw_set_format(sc, mode, &phwfmt, &rhwfmt, &pfil, &rfil);
 	if (error) {
-		mutex_exit(sc->sc_lock);
 		aprint_error_dev(self, "audio_hw_set_format failed, "
 		    "error = %d\n", error);
 		goto bad;
@@ -995,7 +996,6 @@ audioattach(device_t parent, device_t se
 	 * attach time, we assume a success.
 	 */
 	error = audio_mixers_init(sc, mode, &phwfmt, &rhwfmt, &pfil, &rfil);
-	mutex_exit(sc->sc_lock);
 	if (sc->sc_pmixer == NULL && sc->sc_rmixer == NULL) {
 		aprint_error_dev(self, "audio_mixers_init failed, "
 		    "error = %d\n", error);
@@ -1087,11 +1087,13 @@ audioattach(device_t parent, device_t se
 #endif
 
 	audiorescan(self, "audio", NULL);
+	sc->sc_exlock = 0;
 	return;
 
 bad:
 	/* Clearing hw_if means that device is attached but disabled. */
 	sc->hw_if = NULL;
+	sc->sc_exlock = 0;
 	aprint_error_dev(sc->sc_dev, "disabled\n");
 	return;
 }
@@ -1309,6 +1311,7 @@ audiodetach(device_t self, int flags)
 	 * that hold sc, and any new calls with files that were for sc will
 	 * fail.  Thus, we now have exclusive access to the softc.
 	 */
+	sc->sc_exlock = 1;
 
 	/*
 	 * Nuke all open instances.
@@ -1334,7 +1337,6 @@ audiodetach(device_t self, int flags)
 	pmf_device_deregister(self);
 
 	/* Free resources */
-	mutex_enter(sc->sc_lock);
 	if (sc->sc_pmixer) {
 		audio_mixer_destroy(sc, sc->sc_pmixer);
 		kmem_free(sc->sc_pmixer, sizeof(*sc->sc_pmixer));
@@ -1343,7 +1345,6 @@ audiodetach(device_t self, int flags)
 		audio_mixer_destroy(sc, sc->sc_rmixer);
 		kmem_free(sc->sc_rmixer, sizeof(*sc->sc_rmixer));
 	}
-	mutex_exit(sc->sc_lock);
 	if (sc->sc_am)
 		kern_free(sc->sc_am);
 
@@ -1415,12 +1416,12 @@ audio_attach_mi(const struct audio_hw_if
 }
 
 /*
- * Acquire sc_lock and enter exlock critical section.
- * If successful, it returns 0.  Otherwise returns errno.
+ * Enter critical section and also keep sc_lock.
+ * If successful, returns 0 with sc_lock held.  Otherwise returns errno.
  * Must be called without sc_lock held.
  */
 static int
-audio_enter_exclusive(struct audio_softc *sc)
+audio_exlock_mutex_enter(struct audio_softc *sc)
 {
 	int error;
 
@@ -1446,23 +1447,51 @@ audio_enter_exclusive(struct audio_softc
 }
 
 /*
- * Leave exlock critical section and release sc_lock.
+ * Exit critical section and exit sc_lock.
  * Must be called with sc_lock held.
  */
 static void
-audio_exit_exclusive(struct audio_softc *sc)
+audio_exlock_mutex_exit(struct audio_softc *sc)
 {
 
 	KASSERT(mutex_owned(sc->sc_lock));
-	KASSERT(sc->sc_exlock);
 
-	/* Leave critical section */
 	sc->sc_exlock = 0;
 	cv_broadcast(&sc->sc_exlockcv);
 	mutex_exit(sc->sc_lock);
 }
 
 /*
+ * Enter critical section.
+ * If successful, it returns 0.  Otherwise returns errno.
+ * Must be called without sc_lock held.
+ * This function returns without sc_lock held.
+ */
+static int
+audio_exlock_enter(struct audio_softc *sc)
+{
+	int error;
+
+	error = audio_exlock_mutex_enter(sc);
+	if (error)
+		return error;
+	mutex_exit(sc->sc_lock);
+	return 0;
+}
+
+/*
+ * Exit critical section.
+ * Must be called without sc_lock held.
+ */
+static void
+audio_exlock_exit(struct audio_softc *sc)
+{
+
+	mutex_enter(sc->sc_lock);
+	audio_exlock_mutex_exit(sc);
+}
+
+/*
  * Acquire sc from file, and increment the psref count.
  * If successful, returns sc.  Otherwise returns NULL.
  */
@@ -1576,7 +1605,7 @@ audioopen(dev_t dev, int flags, int ifmt
 	if (sc == NULL || sc->hw_if == NULL)
 		return ENXIO;
 
-	error = audio_enter_exclusive(sc);
+	error = audio_exlock_enter(sc);
 	if (error)
 		return error;
 
@@ -1596,7 +1625,7 @@ audioopen(dev_t dev, int flags, int ifmt
 		error = ENXIO;
 		break;
 	}
-	audio_exit_exclusive(sc);
+	audio_exlock_exit(sc);
 
 	return error;
 }
@@ -1930,14 +1959,14 @@ audiobellopen(dev_t dev, audio_file_t **
 	if (sc == NULL || sc->hw_if == NULL)
 		return ENXIO;
 
-	error = audio_enter_exclusive(sc);
+	error = audio_exlock_enter(sc);
 	if (error)
 		return error;
 
 	device_active(sc->sc_dev, DVA_SYSTEM);
 	error = audio_open(dev, sc, FWRITE, 0, curlwp, filep);
 
-	audio_exit_exclusive(sc);
+	audio_exlock_exit(sc);
 	return error;
 }
 
@@ -1980,11 +2009,11 @@ audiobellsetrate(audio_file_t *file, u_i
 	AUDIO_INITINFO(&ai);
 	ai.play.sample_rate = sample_rate;
 
-	error = audio_enter_exclusive(sc);
+	error = audio_exlock_enter(sc);
 	if (error)
 		goto done;
 	error = audio_file_setinfo(sc, file, &ai);
-	audio_exit_exclusive(sc);
+	audio_exlock_exit(sc);
 
 done:
 	audio_file_exit(sc, &sc_ref);
@@ -2013,6 +2042,10 @@ audiobellwrite(audio_file_t *file, struc
 /*
  * Audio driver
  */
+
+/*
+ * Must be called with sc_exlock held and without sc_lock held.
+ */
 int
 audio_open(dev_t dev, struct audio_softc *sc, int flags, int ifmt,
 	struct lwp *l, audio_file_t **bellfile)
@@ -2025,7 +2058,6 @@ audio_open(dev_t dev, struct audio_softc
 	int fd;
 	int error;
 
-	KASSERT(mutex_owned(sc->sc_lock));
 	KASSERT(sc->sc_exlock);
 
 	TRACE(1, "%sdev=%s flags=0x%x po=%d ro=%d",
@@ -2147,9 +2179,11 @@ audio_open(dev_t dev, struct audio_softc
 					hwflags |= FREAD;
 			}
 
+			mutex_enter(sc->sc_lock);
 			mutex_enter(sc->sc_intr_lock);
 			error = sc->hw_if->open(sc->hw_hdl, hwflags);
 			mutex_exit(sc->sc_intr_lock);
+			mutex_exit(sc->sc_lock);
 			if (error)
 				goto bad2;
 		}
@@ -2166,9 +2200,11 @@ audio_open(dev_t dev, struct audio_softc
 				} else {
 					on = 0;
 				}
+				mutex_enter(sc->sc_lock);
 				mutex_enter(sc->sc_intr_lock);
 				error = sc->hw_if->speaker_ctl(sc->hw_hdl, on);
 				mutex_exit(sc->sc_intr_lock);
+				mutex_exit(sc->sc_lock);
 				if (error)
 					goto bad3;
 			}
@@ -2185,12 +2221,14 @@ audio_open(dev_t dev, struct audio_softc
 	if (af->ptrack && sc->sc_popens == 0) {
 		if (sc->hw_if->init_output) {
 			hwbuf = &sc->sc_pmixer->hwbuf;
+			mutex_enter(sc->sc_lock);
 			mutex_enter(sc->sc_intr_lock);
 			error = sc->hw_if->init_output(sc->hw_hdl,
 			    hwbuf->mem,
 			    hwbuf->capacity *
 			    hwbuf->fmt.channels * hwbuf->fmt.stride / NBBY);
 			mutex_exit(sc->sc_intr_lock);
+			mutex_exit(sc->sc_lock);
 			if (error)
 				goto bad3;
 		}
@@ -2199,12 +2237,14 @@ audio_open(dev_t dev, struct audio_softc
 	if (af->rtrack && sc->sc_ropens == 0) {
 		if (sc->hw_if->init_input) {
 			hwbuf = &sc->sc_rmixer->hwbuf;
+			mutex_enter(sc->sc_lock);
 			mutex_enter(sc->sc_intr_lock);
 			error = sc->hw_if->init_input(sc->hw_hdl,
 			    hwbuf->mem,
 			    hwbuf->capacity *
 			    hwbuf->fmt.channels * hwbuf->fmt.stride / NBBY);
 			mutex_exit(sc->sc_intr_lock);
+			mutex_exit(sc->sc_lock);
 			if (error)
 				goto bad3;
 		}
@@ -2220,6 +2260,7 @@ audio_open(dev_t dev, struct audio_softc
 	 * Count up finally.
 	 * Don't fail from here.
 	 */
+	mutex_enter(sc->sc_lock);
 	if (af->ptrack)
 		sc->sc_popens++;
 	if (af->rtrack)
@@ -2227,6 +2268,7 @@ audio_open(dev_t dev, struct audio_softc
 	mutex_enter(sc->sc_intr_lock);
 	SLIST_INSERT_HEAD(&sc->sc_files, af, entry);
 	mutex_exit(sc->sc_intr_lock);
+	mutex_exit(sc->sc_lock);
 
 	if (bellfile) {
 		*bellfile = af;
@@ -2245,9 +2287,11 @@ audio_open(dev_t dev, struct audio_softc
 bad3:
 	if (sc->sc_popens + sc->sc_ropens == 0) {
 		if (sc->hw_if->close) {
+			mutex_enter(sc->sc_lock);
 			mutex_enter(sc->sc_intr_lock);
 			sc->hw_if->close(sc->hw_hdl);
 			mutex_exit(sc->sc_intr_lock);
+			mutex_exit(sc->sc_lock);
 		}
 	}
 bad2:
@@ -2276,7 +2320,7 @@ audio_close(struct audio_softc *sc, audi
 
 	/*
 	 * Drain first.
-	 * It must be done before unlinking(acquiring exclusive lock).
+	 * It must be done before unlinking(acquiring exlock).
 	 */
 	if (file->ptrack) {
 		mutex_enter(sc->sc_lock);
@@ -2296,6 +2340,8 @@ audio_unlink(struct audio_softc *sc, aud
 {
 	int error;
 
+	mutex_enter(sc->sc_lock);
+
 	TRACEF(1, file, "%spid=%d.%d po=%d ro=%d",
 	    (audiodebug >= 3) ? "start " : "",
 	    (int)curproc->p_pid, (int)curlwp->l_lid,
@@ -2304,10 +2350,9 @@ audio_unlink(struct audio_softc *sc, aud
 	    "sc->sc_popens=%d, sc->sc_ropens=%d",
 	    sc->sc_popens, sc->sc_ropens);
 
-	mutex_enter(sc->sc_lock);
 	/*
-	 * Acquire exclusive lock to protect counters.
-	 * Does not use audio_enter_exclusive() due to sc_dying.
+	 * Acquire exlock to protect counters.
+	 * Does not use audio_exlock_enter() due to sc_dying.
 	 */
 	while (__predict_false(sc->sc_exlock != 0)) {
 		error = cv_timedwait_sig(&sc->sc_exlockcv, sc->sc_lock,
@@ -2381,12 +2426,14 @@ audio_unlink(struct audio_softc *sc, aud
 			sc->hw_if->close(sc->hw_hdl);
 			mutex_exit(sc->sc_intr_lock);
 		}
+	}
 
+	mutex_exit(sc->sc_lock);
+	if (sc->sc_popens + sc->sc_ropens == 0)
 		kauth_cred_free(sc->sc_cred);
-	}
 
 	TRACE(3, "done");
-	audio_exit_exclusive(sc);
+	audio_exlock_exit(sc);
 
 	return 0;
 }
@@ -2419,27 +2466,26 @@ audio_read(struct audio_softc *sc, struc
 
 	TRACET(2, track, "resid=%zd", uio->uio_resid);
 
+	error = audio_exlock_mutex_enter(sc);
+	if (error)
+		return error;
+
 #ifdef AUDIO_PM_IDLE
-	mutex_enter(sc->sc_lock);
 	if (device_is_active(&sc->sc_dev) || sc->sc_idle)
 		device_active(&sc->sc_dev, DVA_SYSTEM);
-	mutex_exit(sc->sc_lock);
 #endif
 
-	usrbuf = &track->usrbuf;
-	input = track->input;
-
 	/*
 	 * The first read starts rmixer.
 	 */
-	error = audio_enter_exclusive(sc);
-	if (error)
-		return error;
 	if (sc->sc_rbusy == false)
 		audio_rmixer_start(sc);
-	audio_exit_exclusive(sc);
+	audio_exlock_mutex_exit(sc);
 
+	usrbuf = &track->usrbuf;
+	input = track->input;
 	error = 0;
+
 	while (uio->uio_resid > 0 && error == 0) {
 		int bytes;
 
@@ -2547,28 +2593,27 @@ audio_write(struct audio_softc *sc, stru
 		return 0;
 	}
 
+	error = audio_exlock_mutex_enter(sc);
+	if (error)
+		return error;
+
 #ifdef AUDIO_PM_IDLE
-	mutex_enter(sc->sc_lock);
 	if (device_is_active(&sc->sc_dev) || sc->sc_idle)
 		device_active(&sc->sc_dev, DVA_SYSTEM);
-	mutex_exit(sc->sc_lock);
 #endif
 
-	usrbuf = &track->usrbuf;
-	outbuf = &track->outbuf;
-
 	/*
 	 * The first write starts pmixer.
 	 */
-	error = audio_enter_exclusive(sc);
-	if (error)
-		return error;
 	if (sc->sc_pbusy == false)
 		audio_pmixer_start(sc, false);
-	audio_exit_exclusive(sc);
+	audio_exlock_mutex_exit(sc);
 
+	usrbuf = &track->usrbuf;
+	outbuf = &track->outbuf;
 	track->pstate = AUDIO_STATE_RUNNING;
 	error = 0;
+
 	while (uio->uio_resid > 0 && error == 0) {
 		int bytes;
 
@@ -2797,32 +2842,34 @@ audio_ioctl(dev_t dev, struct audio_soft
 		break;
 
 	case AUDIO_SETINFO:
-		error = audio_enter_exclusive(sc);
+		error = audio_exlock_enter(sc);
 		if (error)
 			break;
 		error = audio_file_setinfo(sc, file, (struct audio_info *)addr);
 		if (error) {
-			audio_exit_exclusive(sc);
+			audio_exlock_exit(sc);
 			break;
 		}
 		/* XXX TODO: update last_ai if /dev/sound ? */
 		if (ISDEVSOUND(dev))
 			error = audiogetinfo(sc, &sc->sc_ai, 0, file);
-		audio_exit_exclusive(sc);
+		audio_exlock_exit(sc);
 		break;
 
 	case AUDIO_GETINFO:
-		error = audio_enter_exclusive(sc);
+		error = audio_exlock_enter(sc);
 		if (error)
 			break;
 		error = audiogetinfo(sc, (struct audio_info *)addr, 1, file);
-		audio_exit_exclusive(sc);
+		audio_exlock_exit(sc);
 		break;
 
 	case AUDIO_GETBUFINFO:
-		mutex_enter(sc->sc_lock);
+		error = audio_exlock_enter(sc);
+		if (error)
+			break;
 		error = audiogetinfo(sc, (struct audio_info *)addr, 0, file);
-		mutex_exit(sc->sc_lock);
+		audio_exlock_exit(sc);
 		break;
 
 	case AUDIO_DRAIN:
@@ -2865,10 +2912,12 @@ audio_ioctl(dev_t dev, struct audio_soft
 		 * If HW has full duplex mode and there are two mixers,
 		 * it is full duplex.  Otherwise half duplex.
 		 */
-		mutex_enter(sc->sc_lock);
+		error = audio_exlock_enter(sc);
+		if (error)
+			break;
 		fd = (sc->sc_props & AUDIO_PROP_FULLDUPLEX)
 		    && (sc->sc_pmixer && sc->sc_rmixer);
-		mutex_exit(sc->sc_lock);
+		audio_exlock_exit(sc);
 		*(int *)addr = fd;
 		break;
 
@@ -2886,18 +2935,22 @@ audio_ioctl(dev_t dev, struct audio_soft
 		break;
 
 	case AUDIO_GETFORMAT:
+		error = audio_exlock_enter(sc);
+		if (error)
+			break;
 		audio_mixers_get_format(sc, (struct audio_info *)addr);
+		audio_exlock_exit(sc);
 		break;
 
 	case AUDIO_SETFORMAT:
-		mutex_enter(sc->sc_lock);
+		error = audio_exlock_enter(sc);
 		audio_mixers_get_format(sc, &ai);
 		error = audio_mixers_set_format(sc, (struct audio_info *)addr);
 		if (error) {
 			/* Rollback */
 			audio_mixers_set_format(sc, &ai);
 		}
-		mutex_exit(sc->sc_lock);
+		audio_exlock_exit(sc);
 		break;
 
 	case AUDIO_SETFD:
@@ -2908,12 +2961,10 @@ audio_ioctl(dev_t dev, struct audio_soft
 
 	default:
 		if (sc->hw_if->dev_ioctl) {
-			error = audio_enter_exclusive(sc);
-			if (error)
-				break;
+			mutex_enter(sc->sc_lock);
 			error = sc->hw_if->dev_ioctl(sc->hw_hdl,
 			    cmd, addr, flag, l);
-			audio_exit_exclusive(sc);
+			mutex_exit(sc->sc_lock);
 		} else {
 			TRACEF(2, file, "unknown ioctl");
 			error = EINVAL;
@@ -3116,6 +3167,7 @@ audio_kqfilter(struct audio_softc *sc, a
 
 	TRACEF(3, file, "kn=%p kn_filter=%x", kn, (int)kn->kn_filter);
 
+	mutex_enter(sc->sc_lock);
 	switch (kn->kn_filter) {
 	case EVFILT_READ:
 		klist = &sc->sc_rsel.sel_klist;
@@ -3128,12 +3180,12 @@ audio_kqfilter(struct audio_softc *sc, a
 		break;
 
 	default:
+		mutex_exit(sc->sc_lock);
 		return EINVAL;
 	}
 
 	kn->kn_hook = file;
 
-	mutex_enter(sc->sc_lock);
 	SLIST_INSERT_HEAD(klist, kn, kn_selnext);
 	mutex_exit(sc->sc_lock);
 
@@ -3194,12 +3246,12 @@ audio_mmap(struct audio_softc *sc, off_t
 		track->mmapped = true;
 
 		if (!track->is_pause) {
-			error = audio_enter_exclusive(sc);
+			error = audio_exlock_mutex_enter(sc);
 			if (error)
 				return error;
 			if (sc->sc_pbusy == false)
 				audio_pmixer_start(sc, true);
-			audio_exit_exclusive(sc);
+			audio_exlock_mutex_exit(sc);
 		}
 		/* XXX mmapping record buffer is not supported */
 	}
@@ -3218,6 +3270,7 @@ audio_mmap(struct audio_softc *sc, off_t
 /*
  * /dev/audioctl has to be able to open at any time without interference
  * with any /dev/audio or /dev/sound.
+ * Must be called with sc_exlock held and without sc_lock held.
  */
 static int
 audioctl_open(dev_t dev, struct audio_softc *sc, int flags, int ifmt,
@@ -3228,7 +3281,6 @@ audioctl_open(dev_t dev, struct audio_so
 	int fd;
 	int error;
 
-	KASSERT(mutex_owned(sc->sc_lock));
 	KASSERT(sc->sc_exlock);
 
 	TRACE(1, "");
@@ -3719,6 +3771,7 @@ audio_track_freq_down(audio_filter_arg_t
 
 /*
  * Creates track and returns it.
+ * Must be called without sc_lock held.
  */
 audio_track_t *
 audio_track_create(struct audio_softc *sc, audio_trackmixer_t *mixer)
@@ -4691,7 +4744,7 @@ audio_track_record(audio_track_t *track)
 
 /*
  * Calcurate blktime [msec] from mixer(.hwbuf.fmt).
- * Must be called with sc_lock held.
+ * Must be called with sc_exlock held.
  */
 static u_int
 audio_mixer_calc_blktime(struct audio_softc *sc, audio_trackmixer_t *mixer)
@@ -4700,7 +4753,7 @@ audio_mixer_calc_blktime(struct audio_so
 	u_int blktime;
 	u_int frames_per_block;
 
-	KASSERT(mutex_owned(sc->sc_lock));
+	KASSERT(sc->sc_exlock);
 
 	fmt = &mixer->hwbuf.fmt;
 	blktime = sc->sc_blk_ms;
@@ -4728,7 +4781,7 @@ audio_mixer_calc_blktime(struct audio_so
  * Set AUMODE_PLAY to the 'mode' for playback or AUMODE_RECORD for recording.
  * sc->sc_[pr]mixer (corresponding to the 'mode') must be zero-filled.
  * This function returns 0 on successful.  Otherwise returns errno.
- * Must be called with sc_lock held.
+ * Must be called with sc_exlock held and without sc_lock held.
  */
 static int
 audio_mixer_init(struct audio_softc *sc, int mode,
@@ -4747,7 +4800,7 @@ audio_mixer_init(struct audio_softc *sc,
 
 	KASSERT(hwfmt != NULL);
 	KASSERT(reg != NULL);
-	KASSERT(mutex_owned(sc->sc_lock));
+	KASSERT(sc->sc_exlock);
 
 	error = 0;
 	if (mode == AUMODE_PLAY)
@@ -4770,8 +4823,10 @@ audio_mixer_init(struct audio_softc *sc,
 	if (sc->hw_if->round_blocksize) {
 		int rounded;
 		audio_params_t p = format2_to_params(&mixer->hwbuf.fmt);
+		mutex_enter(sc->sc_lock);
 		rounded = sc->hw_if->round_blocksize(sc->hw_hdl, blksize,
 		    mode, &p);
+		mutex_exit(sc->sc_lock);
 		TRACE(1, "round_blocksize %d -> %d", blksize, rounded);
 		if (rounded != blksize) {
 			if ((rounded * NBBY) % (mixer->hwbuf.fmt.stride *
@@ -4800,8 +4855,10 @@ audio_mixer_init(struct audio_softc *sc,
 	bufsize = frametobyte(&mixer->hwbuf.fmt, capacity);
 	if (sc->hw_if->round_buffersize) {
 		size_t rounded;
+		mutex_enter(sc->sc_lock);
 		rounded = sc->hw_if->round_buffersize(sc->hw_hdl, mode,
 		    bufsize);
+		mutex_exit(sc->sc_lock);
 		TRACE(1, "round_buffersize %zd -> %zd", bufsize, rounded);
 		if (rounded < bufsize) {
 			/* buffersize needs NBLKHW blocks at least. */
@@ -4939,14 +4996,14 @@ abort:
 /*
  * Releases all resources of 'mixer'.
  * Note that it does not release the memory area of 'mixer' itself.
- * Must be called with sc_lock held.
+ * Must be called with sc_exlock held and without sc_lock held.
  */
 static void
 audio_mixer_destroy(struct audio_softc *sc, audio_trackmixer_t *mixer)
 {
 	int bufsize;
 
-	KASSERT(mutex_owned(sc->sc_lock));
+	KASSERT(sc->sc_exlock == 1);
 
 	bufsize = frametobyte(&mixer->hwbuf.fmt, mixer->hwbuf.capacity);
 
@@ -5884,31 +5941,24 @@ audio_track_drain(struct audio_softc *sc
 /*
  * Send signal to process.
  * This is intended to be called only from audio_softintr_{rd,wr}.
- * Must be called with sc_lock && sc_intr_lock held.
+ * Must be called without sc_intr_lock held.
  */
 static inline void
 audio_psignal(struct audio_softc *sc, pid_t pid, int signum)
 {
 	proc_t *p;
 
-	KASSERT(mutex_owned(sc->sc_lock));
-	KASSERT(mutex_owned(sc->sc_intr_lock));
 	KASSERT(pid != 0);
 
 	/*
 	 * psignal() must be called without spin lock held.
-	 * So leave intr_lock temporarily here.
 	 */
-	mutex_exit(sc->sc_intr_lock);
 
 	mutex_enter(proc_lock);
 	p = proc_find(pid);
 	if (p)
 		psignal(p, signum);
 	mutex_exit(proc_lock);
-
-	/* Enter intr_lock again */
-	mutex_enter(sc->sc_intr_lock);
 }
 
 /*
@@ -5932,7 +5982,6 @@ audio_softintr_rd(void *cookie)
 	pid_t pid;
 
 	mutex_enter(sc->sc_lock);
-	mutex_enter(sc->sc_intr_lock);
 
 	SLIST_FOREACH(f, &sc->sc_files, entry) {
 		audio_track_t *track = f->rtrack;
@@ -5951,7 +6000,6 @@ audio_softintr_rd(void *cookie)
 			audio_psignal(sc, pid, SIGIO);
 		}
 	}
-	mutex_exit(sc->sc_intr_lock);
 
 	/* Notify that data has arrived. */
 	selnotify(&sc->sc_rsel, 0, NOTE_SUBMIT);
@@ -5983,7 +6031,6 @@ audio_softintr_wr(void *cookie)
 	found = false;
 
 	mutex_enter(sc->sc_lock);
-	mutex_enter(sc->sc_intr_lock);
 
 	SLIST_FOREACH(f, &sc->sc_files, entry) {
 		audio_track_t *track = f->ptrack;
@@ -6013,7 +6060,6 @@ audio_softintr_wr(void *cookie)
 			}
 		}
 	}
-	mutex_exit(sc->sc_intr_lock);
 
 	/*
 	 * Notify for select/poll when someone become writable.
@@ -6117,7 +6163,7 @@ audio_check_params(audio_format2_t *p)
  * phwfmt and rhwfmt indicate the hardware format.  pfil and rfil indicate
  * the filter registration information.  These four must not be NULL.
  * If successful returns 0.  Otherwise returns errno.
- * Must be called with sc_lock held.
+ * Must be called with sc_exlock held and without sc_lock held.
  * Must not be called if there are any tracks.
  * Caller should check that the initialization succeed by whether
  * sc_[pr]mixer is not NULL.
@@ -6133,7 +6179,7 @@ audio_mixers_init(struct audio_softc *sc
 	KASSERT(rhwfmt != NULL);
 	KASSERT(pfil != NULL);
 	KASSERT(rfil != NULL);
-	KASSERT(mutex_owned(sc->sc_lock));
+	KASSERT(sc->sc_exlock);
 
 	if ((mode & AUMODE_PLAY)) {
 		if (sc->sc_pmixer == NULL) {
@@ -6340,7 +6386,7 @@ audio_hw_probe(struct audio_softc *sc, a
  * Validate fmt with query_format.
  * If fmt is included in the result of query_format, returns 0.
  * Otherwise returns EINVAL.
- * Must be called with sc_lock held.
+ * Must be called without sc_lock held.
  */ 
 static int
 audio_hw_validate_format(struct audio_softc *sc, int mode,
@@ -6352,11 +6398,11 @@ audio_hw_validate_format(struct audio_so
 	int error;
 	int j;
 
-	KASSERT(mutex_owned(sc->sc_lock));
-
 	for (index = 0; ; index++) {
 		query.index = index;
+		mutex_enter(sc->sc_lock);
 		error = sc->hw_if->query_format(sc->hw_hdl, &query);
+		mutex_exit(sc->sc_lock);
 		if (error == EINVAL)
 			break;
 		if (error)
@@ -6413,7 +6459,7 @@ audio_hw_validate_format(struct audio_so
  * All other fields in ai are ignored.
  * If successful returns 0.  Otherwise returns errno.
  * This function does not roll back even if it fails.
- * Must be called with sc_lock held.
+ * Must be called with sc_exlock held and without sc_lock held.
  */
 static int
 audio_mixers_set_format(struct audio_softc *sc, const struct audio_info *ai)
@@ -6425,7 +6471,7 @@ audio_mixers_set_format(struct audio_sof
 	int mode;
 	int error;
 
-	KASSERT(mutex_owned(sc->sc_lock));
+	KASSERT(sc->sc_exlock);
 
 	/*
 	 * Even when setting either one of playback and recording,
@@ -6529,10 +6575,14 @@ audio_mixers_set_format(struct audio_sof
 
 /*
  * Store current mixers format into *ai.
+ * Must be called with sc_exlock held.
  */
 static void
 audio_mixers_get_format(struct audio_softc *sc, struct audio_info *ai)
 {
+
+	KASSERT(sc->sc_exlock);
+
 	/*
 	 * There is no stride information in audio_info but it doesn't matter.
 	 * trackmixer always treats stride and precision as the same.
@@ -6644,7 +6694,7 @@ audio_mixers_get_format(struct audio_sof
 /*
  * Set both track's parameters within a file depending on ai.
  * Update sc_sound_[pr]* if set.
- * Must be called with sc_lock and sc_exlock held.
+ * Must be called with sc_exlock held and without sc_lock held.
  */
 static int
 audio_file_setinfo(struct audio_softc *sc, audio_file_t *file,
@@ -6664,7 +6714,6 @@ audio_file_setinfo(struct audio_softc *s
 	audio_format2_t saved_rfmt;
 	int error;
 
-	KASSERT(mutex_owned(sc->sc_lock));
 	KASSERT(sc->sc_exlock);
 
 	pi = &ai->play;
@@ -6851,7 +6900,9 @@ audio_file_setinfo(struct audio_softc *s
 	}
 
 	/* Set mixer parameters */
+	mutex_enter(sc->sc_lock);
 	error = audio_hw_setinfo(sc, ai, &saved_ai);
+	mutex_exit(sc->sc_lock);
 	if (error)
 		goto abort1;
 
@@ -6925,7 +6976,9 @@ abort2:
 	sc->sc_sound_pparams = saved_pfmt;
 	file->mode = saved_ai.mode;
 abort1:
+	mutex_enter(sc->sc_lock);
 	audio_hw_setinfo(sc, &saved_ai, NULL);
+	mutex_exit(sc->sc_lock);
 
 	return error;
 }
@@ -7036,7 +7089,7 @@ audio_track_setinfo_water(audio_track_t 
  * The parameters handled here are *.port, *.gain, *.balance and monitor_gain.
  * If oldai is specified, previous parameters are stored.
  * This function itself does not roll back if error occurred.
- * Must be called with sc_lock and sc_exlock held.
+ * Must be called with sc_lock && sc_exlock held.
  */
 static int
 audio_hw_setinfo(struct audio_softc *sc, const struct audio_info *newai,
@@ -7185,7 +7238,7 @@ abort:
  * - pfil, rfil will be filled with filter information specified by the
  *   hardware driver.
  * and then returns 0.  Otherwise returns errno.
- * Must be called with sc_lock held.
+ * Must be called without sc_lock held.
  */
 static int
 audio_hw_set_format(struct audio_softc *sc, int setmode,
@@ -7195,16 +7248,17 @@ audio_hw_set_format(struct audio_softc *
 	audio_params_t pp, rp;
 	int error;
 
-	KASSERT(mutex_owned(sc->sc_lock));
 	KASSERT(phwfmt != NULL);
 	KASSERT(rhwfmt != NULL);
 
 	pp = format2_to_params(phwfmt);
 	rp = format2_to_params(rhwfmt);
 
+	mutex_enter(sc->sc_lock);
 	error = sc->hw_if->set_format(sc->hw_hdl, setmode,
 	    &pp, &rp, pfil, rfil);
 	if (error) {
+		mutex_exit(sc->sc_lock);
 		device_printf(sc->sc_dev,
 		    "set_format failed with %d\n", error);
 		return error;
@@ -7213,11 +7267,13 @@ audio_hw_set_format(struct audio_softc *
 	if (sc->hw_if->commit_settings) {
 		error = sc->hw_if->commit_settings(sc->hw_hdl);
 		if (error) {
+			mutex_exit(sc->sc_lock);
 			device_printf(sc->sc_dev,
 			    "commit_settings failed with %d\n", error);
 			return error;
 		}
 	}
+	mutex_exit(sc->sc_lock);
 
 	return 0;
 }
@@ -7225,9 +7281,7 @@ audio_hw_set_format(struct audio_softc *
 /*
  * Fill audio_info structure.  If need_mixerinfo is true, it will also
  * fill the hardware mixer information.
- * Must be called with sc_lock held.
- * Must be called with sc_exlock held, in addition, if need_mixerinfo is
- * true.
+ * Must be called with sc_exlock held and without sc_lock held.
  */
 static int
 audiogetinfo(struct audio_softc *sc, struct audio_info *ai, int need_mixerinfo,
@@ -7239,7 +7293,7 @@ audiogetinfo(struct audio_softc *sc, str
 	audio_track_t *rtrack;
 	int gain;
 
-	KASSERT(mutex_owned(sc->sc_lock));
+	KASSERT(sc->sc_exlock);
 
 	ri = &ai->record;
 	pi = &ai->play;
@@ -7332,7 +7386,7 @@ audiogetinfo(struct audio_softc *sc, str
 	}
 
 	if (need_mixerinfo) {
-		KASSERT(sc->sc_exlock);
+		mutex_enter(sc->sc_lock);
 
 		pi->port = au_get_port(sc, &sc->sc_outports);
 		ri->port = au_get_port(sc, &sc->sc_inports);
@@ -7348,6 +7402,7 @@ audiogetinfo(struct audio_softc *sc, str
 			if (gain != -1)
 				ai->monitor_gain = gain;
 		}
+		mutex_exit(sc->sc_lock);
 	}
 
 	return 0;
@@ -7486,7 +7541,9 @@ audio_sysctl_blk_ms(SYSCTLFN_ARGS)
 	node = *rnode;
 	sc = node.sysctl_data;
 
-	mutex_enter(sc->sc_lock);
+	error = audio_exlock_enter(sc);
+	if (error)
+		return error;
 
 	old_blk_ms = sc->sc_blk_ms;
 	t = old_blk_ms;
@@ -7533,7 +7590,7 @@ audio_sysctl_blk_ms(SYSCTLFN_ARGS)
 	}
 	error = 0;
 abort:
-	mutex_exit(sc->sc_lock);
+	audio_exlock_exit(sc);
 	return error;
 }
 
@@ -7551,7 +7608,9 @@ audio_sysctl_multiuser(SYSCTLFN_ARGS)
 	node = *rnode;
 	sc = node.sysctl_data;
 
-	mutex_enter(sc->sc_lock);
+	error = audio_exlock_enter(sc);
+	if (error)
+		return error;
 
 	t = sc->sc_multiuser;
 	node.sysctl_data = &t;
@@ -7562,7 +7621,7 @@ audio_sysctl_multiuser(SYSCTLFN_ARGS)
 	sc->sc_multiuser = t;
 	error = 0;
 abort:
-	mutex_exit(sc->sc_lock);
+	audio_exlock_exit(sc);
 	return error;
 }
 
@@ -7642,7 +7701,7 @@ audio_suspend(device_t dv, const pmf_qua
 	struct audio_softc *sc = device_private(dv);
 	int error;
 
-	error = audio_enter_exclusive(sc);
+	error = audio_exlock_mutex_enter(sc);
 	if (error)
 		return error;
 	audio_mixer_capture(sc);
@@ -7660,7 +7719,7 @@ audio_suspend(device_t dv, const pmf_qua
 #ifdef AUDIO_PM_IDLE
 	callout_halt(&sc->sc_idle_counter, sc->sc_lock);
 #endif
-	audio_exit_exclusive(sc);
+	audio_exlock_mutex_exit(sc);
 
 	return true;
 }
@@ -7672,7 +7731,7 @@ audio_resume(device_t dv, const pmf_qual
 	struct audio_info ai;
 	int error;
 
-	error = audio_enter_exclusive(sc);
+	error = audio_exlock_mutex_enter(sc);
 	if (error)
 		return error;
 
@@ -7686,7 +7745,7 @@ audio_resume(device_t dv, const pmf_qual
 	if (sc->sc_rbusy)
 		audio_rmixer_start(sc);
 
-	audio_exit_exclusive(sc);
+	audio_exlock_mutex_exit(sc);
 
 	return true;
 }
@@ -7787,6 +7846,10 @@ audio_diagnostic_ring(const char *where,
 /*
  * Mixer driver
  */
+
+/*
+ * Must be called without sc_lock held.
+ */
 int
 mixer_open(dev_t dev, struct audio_softc *sc, int flags, int ifmt,
 	struct lwp *l)
@@ -7795,8 +7858,6 @@ mixer_open(dev_t dev, struct audio_softc
 	audio_file_t *af;
 	int error, fd;
 
-	KASSERT(mutex_owned(sc->sc_lock));
-
 	TRACE(1, "flags=0x%x", flags);
 
 	error = fd_allocfile(&fp, &fd);
@@ -7816,14 +7877,14 @@ mixer_open(dev_t dev, struct audio_softc
 /*
  * Add a process to those to be signalled on mixer activity.
  * If the process has already been added, do nothing.
- * Must be called with sc_lock held.
+ * Must be called with sc_exlock held and without sc_lock held.
  */
 static void
 mixer_async_add(struct audio_softc *sc, pid_t pid)
 {
 	int i;
 
-	KASSERT(mutex_owned(sc->sc_lock));
+	KASSERT(sc->sc_exlock);
 
 	/* If already exists, returns without doing anything. */
 	for (i = 0; i < sc->sc_am_used; i++) {
@@ -7846,14 +7907,14 @@ mixer_async_add(struct audio_softc *sc, 
 /*
  * Remove a process from those to be signalled on mixer activity.
  * If the process has not been added, do nothing.
- * Must be called with sc_lock held.
+ * Must be called with sc_exlock held and without sc_lock held.
  */
 static void
 mixer_async_remove(struct audio_softc *sc, pid_t pid)
 {
 	int i;
 
-	KASSERT(mutex_owned(sc->sc_lock));
+	KASSERT(sc->sc_exlock);
 
 	for (i = 0; i < sc->sc_am_used; i++) {
 		if (sc->sc_am[i] == pid) {
@@ -7875,7 +7936,7 @@ mixer_async_remove(struct audio_softc *s
 
 /*
  * Signal all processes waiting for the mixer.
- * Must be called with sc_lock held.
+ * Must be called with sc_exlock held.
  */
 static void
 mixer_signal(struct audio_softc *sc)
@@ -7883,7 +7944,7 @@ mixer_signal(struct audio_softc *sc)
 	proc_t *p;
 	int i;
 
-	KASSERT(mutex_owned(sc->sc_lock));
+	KASSERT(sc->sc_exlock);
 
 	for (i = 0; i < sc->sc_am_used; i++) {
 		mutex_enter(proc_lock);
@@ -7900,11 +7961,14 @@ mixer_signal(struct audio_softc *sc)
 int
 mixer_close(struct audio_softc *sc, audio_file_t *file)
 {
+	int error;
 
-	mutex_enter(sc->sc_lock);
+	error = audio_exlock_enter(sc);
+	if (error)
+		return error;
 	TRACE(1, "");
 	mixer_async_remove(sc, curproc->p_pid);
-	mutex_exit(sc->sc_lock);
+	audio_exlock_exit(sc);
 
 	return 0;
 }
@@ -7933,23 +7997,22 @@ mixer_ioctl(struct audio_softc *sc, u_lo
 
 	switch (cmd) {
 	case FIOASYNC:
-		mutex_enter(sc->sc_lock);
+		error = audio_exlock_enter(sc);
+		if (error)
+			break;
 		if (*(int *)addr) {
 			mixer_async_add(sc, curproc->p_pid);
 		} else {
 			mixer_async_remove(sc, curproc->p_pid);
 		}
-		mutex_exit(sc->sc_lock);
-		error = 0;
+		audio_exlock_exit(sc);
 		break;
 
 	case AUDIO_GETDEV:
 		TRACE(2, "AUDIO_GETDEV");
-		error = audio_enter_exclusive(sc);
-		if (error)
-			break;
+		mutex_enter(sc->sc_lock);
 		error = sc->hw_if->getdev(sc->hw_hdl, (audio_device_t *)addr);
-		audio_exit_exclusive(sc);
+		mutex_exit(sc->sc_lock);
 		break;
 
 	case AUDIO_MIXER_DEVINFO:
@@ -7966,7 +8029,7 @@ mixer_ioctl(struct audio_softc *sc, u_lo
 		TRACE(2, "AUDIO_MIXER_READ");
 		mc = (mixer_ctrl_t *)addr;
 
-		error = audio_enter_exclusive(sc);
+		error = audio_exlock_mutex_enter(sc);
 		if (error)
 			break;
 		if (device_is_active(sc->hw_dev))
@@ -7979,39 +8042,38 @@ mixer_ioctl(struct audio_softc *sc, u_lo
 			    sizeof(mixer_ctrl_t));
 			error = 0;
 		}
-		audio_exit_exclusive(sc);
+		audio_exlock_mutex_exit(sc);
 		break;
 
 	case AUDIO_MIXER_WRITE:
 		TRACE(2, "AUDIO_MIXER_WRITE");
-		error = audio_enter_exclusive(sc);
+		error = audio_exlock_mutex_enter(sc);
 		if (error)
 			break;
 		error = audio_set_port(sc, (mixer_ctrl_t *)addr);
 		if (error) {
-			audio_exit_exclusive(sc);
+			audio_exlock_mutex_exit(sc);
 			break;
 		}
 
 		if (sc->hw_if->commit_settings) {
 			error = sc->hw_if->commit_settings(sc->hw_hdl);
 			if (error) {
-				audio_exit_exclusive(sc);
+				audio_exlock_mutex_exit(sc);
 				break;
 			}
 		}
+		mutex_exit(sc->sc_lock);
 		mixer_signal(sc);
-		audio_exit_exclusive(sc);
+		audio_exlock_exit(sc);
 		break;
 
 	default:
 		if (sc->hw_if->dev_ioctl) {
-			error = audio_enter_exclusive(sc);
-			if (error)
-				break;
+			mutex_enter(sc->sc_lock);
 			error = sc->hw_if->dev_ioctl(sc->hw_hdl,
 			    cmd, addr, flag, l);
-			audio_exit_exclusive(sc);
+			mutex_exit(sc->sc_lock);
 		} else
 			error = EINVAL;
 		break;
@@ -8532,7 +8594,7 @@ audio_volume_down(device_t dv)
 	u_int gain;
 	u_char balance;
 
-	if (audio_enter_exclusive(sc) != 0)
+	if (audio_exlock_mutex_enter(sc) != 0)
 		return;
 	if (sc->sc_outports.index == -1 && sc->sc_outports.master != -1) {
 		mi.index = sc->sc_outports.master;
@@ -8545,7 +8607,7 @@ audio_volume_down(device_t dv)
 			au_set_gain(sc, &sc->sc_outports, newgain, balance);
 		}
 	}
-	audio_exit_exclusive(sc);
+	audio_exlock_mutex_exit(sc);
 }
 
 static void
@@ -8556,7 +8618,7 @@ audio_volume_up(device_t dv)
 	u_int gain, newgain;
 	u_char balance;
 
-	if (audio_enter_exclusive(sc) != 0)
+	if (audio_exlock_mutex_enter(sc) != 0)
 		return;
 	if (sc->sc_outports.index == -1 && sc->sc_outports.master != -1) {
 		mi.index = sc->sc_outports.master;
@@ -8569,7 +8631,7 @@ audio_volume_up(device_t dv)
 			au_set_gain(sc, &sc->sc_outports, newgain, balance);
 		}
 	}
-	audio_exit_exclusive(sc);
+	audio_exlock_mutex_exit(sc);
 }
 
 static void
@@ -8579,7 +8641,7 @@ audio_volume_toggle(device_t dv)
 	u_int gain, newgain;
 	u_char balance;
 
-	if (audio_enter_exclusive(sc) != 0)
+	if (audio_exlock_mutex_enter(sc) != 0)
 		return;
 	au_get_gain(sc, &sc->sc_outports, &gain, &balance);
 	if (gain != 0) {
@@ -8588,9 +8650,12 @@ audio_volume_toggle(device_t dv)
 	} else
 		newgain = sc->sc_lastgain;
 	au_set_gain(sc, &sc->sc_outports, newgain, balance);
-	audio_exit_exclusive(sc);
+	audio_exlock_mutex_exit(sc);
 }
 
+/*
+ * Must be called with sc_lock held.
+ */
 static int
 audio_query_devinfo(struct audio_softc *sc, mixer_devinfo_t *di)
 {

Index: src/sys/dev/audio/audiovar.h
diff -u src/sys/dev/audio/audiovar.h:1.10 src/sys/dev/audio/audiovar.h:1.11
--- src/sys/dev/audio/audiovar.h:1.10	Thu Mar  5 15:18:55 2020
+++ src/sys/dev/audio/audiovar.h	Sat Mar  7 06:25:57 2020
@@ -1,4 +1,4 @@
-/*	$NetBSD: audiovar.h,v 1.10 2020/03/05 15:18:55 riastradh Exp $	*/
+/*	$NetBSD: audiovar.h,v 1.11 2020/03/07 06:25:57 isaki Exp $	*/
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -150,34 +150,37 @@ struct audio_softc {
 
 	/*
 	 * Blocksize in msec.
-	 * Must be protected by sc_lock.
+	 * Must be protected by sc_exlock.
 	 */
 	int sc_blk_ms;
 
 	/*
 	 * Track mixer for playback and recording.
 	 * If null, the mixer is disabled.
+	 * Must be protected by sc_exlock.
 	 */
 	audio_trackmixer_t *sc_pmixer;
 	audio_trackmixer_t *sc_rmixer;
 
 	/*
 	 * Opening track counter.
-	 * Must be protected by sc_lock.
+	 * Must be protected by sc_lock && sc_exlock for modifying.
+	 * Must be protected by sc_lock || sc_exlock for reference.
 	 */
 	int sc_popens;
 	int sc_ropens;
 
 	/*
 	 * true if the track mixer is running.
-	 * Must be protected by sc_lock.
+	 * Must be protected by sc_exlock && sc_intr_lock for modifying.
+	 * Must be protected by sc_exlock || sc_intr_lock for reference.
 	 */
 	bool sc_pbusy;
 	bool sc_rbusy;
 
 	/*
 	 * These four are the parameters sustained with /dev/sound.
-	 * Must be protected by sc_lock.
+	 * Must be protected by sc_exlock.
 	 */
 	audio_format2_t sc_sound_pparams;
 	audio_format2_t sc_sound_rparams;
@@ -200,7 +203,7 @@ struct audio_softc {
 	 * sc_am is an array of pids, or NULL if empty.
 	 * sc_am_capacity is the number of allocated elements.
 	 * sc_am_used is the number of elements actually used.
-	 * Must be protected by sc_lock.
+	 * Must be protected by sc_exlock.
 	 */
 	pid_t *sc_am;
 	int sc_am_capacity;
@@ -234,7 +237,7 @@ struct audio_softc {
 	/*
 	 * If multiuser is false, other users who have different euid
 	 * than the first user cannot open this device.
-	 * Must be protected by sc_lock.
+	 * Must be protected by sc_exlock.
 	 */
 	bool sc_multiuser;
 	kauth_cred_t sc_cred;

Reply via email to