Module Name: src Committed By: nat Date: Tue Feb 21 20:23:37 UTC 2017
Modified Files: src/sys/dev: audio.c Log Message: Ensure we still have a virtual channel after sleeping on sc_lock. Addresses PR kern/51746: Panics from audio. To generate a diff of this commit: cvs rdiff -u -r1.306 -r1.307 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.306 src/sys/dev/audio.c:1.307 --- src/sys/dev/audio.c:1.306 Tue Feb 14 09:41:29 2017 +++ src/sys/dev/audio.c Tue Feb 21 20:23:37 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: audio.c,v 1.306 2017/02/14 09:41:29 nat Exp $ */ +/* $NetBSD: audio.c,v 1.307 2017/02/21 20:23:37 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.306 2017/02/14 09:41:29 nat Exp $"); +__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.307 2017/02/21 20:23:37 nat Exp $"); #include "audio.h" #if NAUDIO > 0 @@ -339,7 +339,8 @@ static void audio_softintr_wr(void *); static int audio_enter(dev_t, krw_t, struct audio_softc **); static void audio_exit(struct audio_softc *); -static int audio_waitio(struct audio_softc *, kcondvar_t *); +static int audio_waitio(struct audio_softc *, kcondvar_t *, + struct virtual_channel *); int audioclose(struct file *); int audioread(struct file *, off_t *, struct uio *, kauth_cred_t, int); @@ -1516,8 +1517,10 @@ audio_exit(struct audio_softc *sc) * Wait for I/O to complete, releasing device lock. */ static int -audio_waitio(struct audio_softc *sc, kcondvar_t *chan) +audio_waitio(struct audio_softc *sc, kcondvar_t *chan, struct virtual_channel *vc) { + struct audio_chan *vchan; + bool found = false; int error; KASSERT(mutex_owned(sc->sc_lock)); @@ -1526,6 +1529,16 @@ audio_waitio(struct audio_softc *sc, kco /* Wait for pending I/O to complete. */ error = cv_wait_sig(chan, sc->sc_lock); + found = false; + SIMPLEQ_FOREACH(vchan, &sc->sc_audiochan, entries) { + if (vchan->vc == vc) { + found = true; + break; + } + } + if (found == false) + error = EIO; + return error; } @@ -2325,7 +2338,7 @@ audio_drain(struct audio_softc *sc, stru audio_stream_get_used(&vc->sc_mpr.s), cb->drops)); mutex_exit(sc->sc_intr_lock); - error = audio_waitio(sc, &sc->sc_wchan); + error = audio_waitio(sc, &sc->sc_wchan, vc); mutex_enter(sc->sc_intr_lock); if (sc->sc_dying) error = EIO; @@ -2476,7 +2489,7 @@ audio_read(struct audio_softc *sc, struc vc->sc_mpr.stamp, vc->sc_wstamp)); if (ioflag & IO_NDELAY) return EWOULDBLOCK; - error = audio_waitio(sc, &sc->sc_rchan); + error = audio_waitio(sc, &sc->sc_rchan, vc); if (sc->sc_dying) error = EIO; if (error) @@ -2504,7 +2517,7 @@ audio_read(struct audio_softc *sc, struc if (ioflag & IO_NDELAY) return EWOULDBLOCK; DPRINTFN(2, ("audio_read: sleep used=%d\n", used)); - error = audio_waitio(sc, &sc->sc_rchan); + error = audio_waitio(sc, &sc->sc_rchan, vc); if (sc->sc_dying) error = EIO; if (error) @@ -2832,7 +2845,7 @@ audio_write(struct audio_softc *sc, stru mutex_exit(sc->sc_intr_lock); if (ioflag & IO_NDELAY) return EWOULDBLOCK; - error = audio_waitio(sc, &sc->sc_wchan); + error = audio_waitio(sc, &sc->sc_wchan, vc); if (sc->sc_dying) error = EIO; if (error)