From 199a8df5ed7529b2c8a02c660b39e3b9ba7295f6 Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Thu, 3 Jun 2021 23:19:03 +0000 Subject: [PATCH] audio(4): When closing /dev/audioN, drain before removing from list. Previously, in revision 1.100, I factored the SLIST_REMOVE out of audio_unlink and audio_close up into audioclose since it is now used by /dev/audio, /dev/audioctl, and /dev/mixer alike. But I didn't realize that the order 1. audio_track_drain 2. SLIST_REMOVE from sc_files was significant; it matters because audio_track_drain waits for wakeups that are delivered by hardware interrupts only to files listed in sc_files. For now, duplicate the SLIST_REMOVE calls in a few more places -- this is suboptimal but I want to make sure the logic works before factoring it all out to tidy up. --- sys/dev/audio/audio.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/sys/dev/audio/audio.c b/sys/dev/audio/audio.c index b74fd417e579..5c56b1af7e05 100644 --- a/sys/dev/audio/audio.c +++ b/sys/dev/audio/audio.c @@ -1747,20 +1747,25 @@ audioclose(struct file *fp) bound = curlwp_bind(); sc = audio_sc_acquire_fromfile(file, &sc_ref); if (sc) { - mutex_enter(sc->sc_lock); - mutex_enter(sc->sc_intr_lock); - SLIST_REMOVE(&sc->sc_files, file, audio_file, entry); - mutex_exit(sc->sc_intr_lock); - mutex_exit(sc->sc_lock); switch (AUDIODEV(dev)) { case SOUND_DEVICE: case AUDIO_DEVICE: error = audio_close(sc, file); break; case AUDIOCTL_DEVICE: + mutex_enter(sc->sc_lock); + mutex_enter(sc->sc_intr_lock); + SLIST_REMOVE(&sc->sc_files, file, audio_file, entry); + mutex_exit(sc->sc_intr_lock); + mutex_exit(sc->sc_lock); error = 0; break; case MIXER_DEVICE: + mutex_enter(sc->sc_lock); + mutex_enter(sc->sc_intr_lock); + SLIST_REMOVE(&sc->sc_files, file, audio_file, entry); + mutex_exit(sc->sc_intr_lock); + mutex_exit(sc->sc_lock); error = mixer_close(sc, file); break; default: @@ -2569,6 +2574,12 @@ audio_close(struct audio_softc *sc, audio_file_t *file) mutex_exit(sc->sc_lock); } + mutex_enter(sc->sc_lock); + mutex_enter(sc->sc_intr_lock); + SLIST_REMOVE(&sc->sc_files, file, audio_file, entry); + mutex_exit(sc->sc_intr_lock); + mutex_exit(sc->sc_lock); + error = audio_exlock_enter(sc); if (error) { /*