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.

This also fixes a bug introduced with the audiobell -- it was missing
the SLIST_REMOVE altogether.

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.
This commit is contained in:
riastradh 2021-06-04 08:57:05 +00:00
parent de71cbe121
commit 519578ce45
1 changed files with 18 additions and 7 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: audio.c,v 1.102 2021/06/01 21:27:36 riastradh Exp $ */ /* $NetBSD: audio.c,v 1.103 2021/06/04 08:57:05 riastradh Exp $ */
/*- /*-
* Copyright (c) 2008 The NetBSD Foundation, Inc. * Copyright (c) 2008 The NetBSD Foundation, Inc.
@ -138,7 +138,7 @@
*/ */
#include <sys/cdefs.h> #include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.102 2021/06/01 21:27:36 riastradh Exp $"); __KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.103 2021/06/04 08:57:05 riastradh Exp $");
#ifdef _KERNEL_OPT #ifdef _KERNEL_OPT
#include "audio.h" #include "audio.h"
@ -1747,20 +1747,25 @@ audioclose(struct file *fp)
bound = curlwp_bind(); bound = curlwp_bind();
sc = audio_sc_acquire_fromfile(file, &sc_ref); sc = audio_sc_acquire_fromfile(file, &sc_ref);
if (sc) { 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)) { switch (AUDIODEV(dev)) {
case SOUND_DEVICE: case SOUND_DEVICE:
case AUDIO_DEVICE: case AUDIO_DEVICE:
error = audio_close(sc, file); error = audio_close(sc, file);
break; break;
case AUDIOCTL_DEVICE: 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; error = 0;
break; break;
case MIXER_DEVICE: 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); error = mixer_close(sc, file);
break; break;
default: default:
@ -2569,6 +2574,12 @@ audio_close(struct audio_softc *sc, audio_file_t *file)
mutex_exit(sc->sc_lock); 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); error = audio_exlock_enter(sc);
if (error) { if (error) {
/* /*