diff options
| author | riastradh <riastradh@NetBSD.org> | 2021-06-04 08:57:05 +0000 |
|---|---|---|
| committer | riastradh <riastradh@NetBSD.org> | 2021-06-04 08:57:05 +0000 |
| commit | c2129c4ab3376e5c31c281bfb4d4657fd22827fe (patch) | |
| tree | ba4fa91c81bd60d76f35adef62f986ce6a415dc7 /sys/dev/audio | |
| parent | 76380197b3a03e58ae85ff68d762f3133b39151f (diff) | |
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.
Diffstat (limited to 'sys/dev/audio')
| -rw-r--r-- | sys/dev/audio/audio.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/sys/dev/audio/audio.c b/sys/dev/audio/audio.c index d6bc54de148..408269d617e 100644 --- a/sys/dev/audio/audio.c +++ b/sys/dev/audio/audio.c @@ -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. @@ -138,7 +138,7 @@ */ #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 #include "audio.h" @@ -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) { /* |
