Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-9]: src/sys/dev/audio Pull up following revision(s) (requested by...



details:   https://anonhg.NetBSD.org/src/rev/a6c53351f73d
branches:  netbsd-9
changeset: 953219:a6c53351f73d
user:      martin <martin%NetBSD.org@localhost>
date:      Mon Mar 01 16:00:08 2021 +0000

description:
Pull up following revision(s) (requested by isaki in ticket #1219):

        sys/dev/audio/audio.c: revision 1.89
        sys/dev/audio/audio.c: revision 1.90
        sys/dev/audio/audio.c: revision 1.91

Change the lock conditions to call audio_unlink().

This can remove a different copy of audio_exlock_enter() in audio_unlink()
and can use normal one.  Also, in audiodetach(), this can set the exlock
at more natual order (before calling audio_unlink()).

No noticeable functional changes are intended.
Thanks for comments, riastradh@.

Protect also audioopen() and audiobellopen() from audiodetach() with
psref(9), as well as others(audioread, audiowrite, etc..).
- Rename audio_file_enter to audio_sc_acquire_fromfile, audio_file_exit
  to audio_sc_release, for clarify.  These are the reference counter for
  this sc.
- Introduce audio_sc_acquire_foropen for audio{,bell}open.
- audio_open needs to examine sc_dying again before inserting it into
  sc_files, in order to keep sc_files consistency.

The race between audiodetach and audioopen is pointed out by riastradh@.
Thank you for many advices.

Add missing curlwp_bindx() corresponding to curlwp_bind().
Pointed out by riastradh@.

diffstat:

 sys/dev/audio/audio.c |  339 ++++++++++++++++++++++++++++++++++---------------
 1 files changed, 235 insertions(+), 104 deletions(-)

diffs (truncated from 717 to 300 lines):

diff -r ee6a11ec6c22 -r a6c53351f73d sys/dev/audio/audio.c
--- a/sys/dev/audio/audio.c     Sun Feb 28 07:09:00 2021 +0000
+++ b/sys/dev/audio/audio.c     Mon Mar 01 16:00:08 2021 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: audio.c,v 1.28.2.20 2021/02/28 07:07:38 martin Exp $   */
+/*     $NetBSD: audio.c,v 1.28.2.21 2021/03/01 16:00:08 martin Exp $   */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -138,7 +138,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.28.2.20 2021/02/28 07:07:38 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.28.2.21 2021/03/01 16:00:08 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "audio.h"
@@ -524,8 +524,10 @@
 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 void audio_sc_acquire_foropen(struct audio_softc *, struct psref *);
+static struct audio_softc *audio_sc_acquire_fromfile(audio_file_t *,
+       struct psref *);
+static void audio_sc_release(struct audio_softc *, struct psref *);
 static int audio_track_waitio(struct audio_softc *, audio_track_t *);
 
 static int audioclose(struct file *);
@@ -1295,7 +1297,10 @@
        if (error)
                return error;
 
-       /* delete sysctl nodes */
+       /*
+        * This waits currently running sysctls to finish if exists.
+        * After this, no more new sysctls will come.
+        */
        sysctl_teardown(&sc->sc_log);
 
        mutex_enter(sc->sc_lock);
@@ -1327,9 +1332,10 @@
         * 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.
+        * Clean up all open instances.
         * Here, we no longer need any locks to traverse sc_files.
         */
        while ((file = SLIST_FIRST(&sc->sc_files)) != NULL) {
@@ -1352,7 +1358,6 @@
        pmf_device_deregister(self);
 
        /* Free resources */
-       sc->sc_exlock = 1;
        if (sc->sc_pmixer) {
                audio_mixer_destroy(sc, sc->sc_pmixer);
                kmem_free(sc->sc_pmixer, sizeof(*sc->sc_pmixer));
@@ -1524,18 +1529,41 @@
 }
 
 /*
- * Acquire sc from file, and increment the psref count.
+ * Increment reference counter for this sc.
+ * This is intended to be used for open.
+ */
+void
+audio_sc_acquire_foropen(struct audio_softc *sc, struct psref *refp)
+{
+       int s;
+
+       /* Block audiodetach while we acquire a reference */
+       s = pserialize_read_enter();
+
+       /*
+        * We don't examine sc_dying here.  However, all open methods
+        * call audio_exlock_enter() right after this, so we can examine
+        * sc_dying in it.
+        */
+
+       /* Acquire a reference */
+       psref_acquire(refp, &sc->sc_psref, audio_psref_class);
+
+       /* Now sc won't go away until we drop the reference count */
+       pserialize_read_exit(s);
+}
+
+/*
+ * Get sc from file, and increment reference counter for this sc.
+ * This is intended to be used for methods other than open.
  * If successful, returns sc.  Otherwise returns NULL.
  */
 struct audio_softc *
-audio_file_enter(audio_file_t *file, struct psref *refp)
+audio_sc_acquire_fromfile(audio_file_t *file, struct psref *refp)
 {
        int s;
        bool dying;
 
-       /* psref(9) forbids to migrate CPUs */
-       curlwp_bind();
-
        /* Block audiodetach while we acquire a reference */
        s = pserialize_read_enter();
 
@@ -1556,10 +1584,10 @@
 }
 
 /*
- * Decrement the psref count.
+ * Decrement reference counter for this sc.
  */
 void
-audio_file_exit(struct audio_softc *sc, struct psref *refp)
+audio_sc_release(struct audio_softc *sc, struct psref *refp)
 {
 
        psref_release(refp, &sc->sc_psref, audio_psref_class);
@@ -1637,6 +1665,8 @@
 audioopen(dev_t dev, int flags, int ifmt, struct lwp *l)
 {
        struct audio_softc *sc;
+       struct psref sc_ref;
+       int bound;
        int error;
 
        /* Find the device */
@@ -1644,9 +1674,12 @@
        if (sc == NULL || sc->hw_if == NULL)
                return ENXIO;
 
+       bound = curlwp_bind();
+       audio_sc_acquire_foropen(sc, &sc_ref);
+
        error = audio_exlock_enter(sc);
        if (error)
-               return error;
+               goto done;
 
        device_active(sc->sc_dev, DVA_SYSTEM);
        switch (AUDIODEV(dev)) {
@@ -1666,6 +1699,9 @@
        }
        audio_exlock_exit(sc);
 
+done:
+       audio_sc_release(sc, &sc_ref);
+       curlwp_bindx(bound);
        return error;
 }
 
@@ -1675,6 +1711,7 @@
        struct audio_softc *sc;
        struct psref sc_ref;
        audio_file_t *file;
+       int bound;
        int error;
        dev_t dev;
 
@@ -1690,7 +1727,8 @@
         * - free all memory objects, regardless of sc.
         */
 
-       sc = audio_file_enter(file, &sc_ref);
+       bound = curlwp_bind();
+       sc = audio_sc_acquire_fromfile(file, &sc_ref);
        if (sc) {
                switch (AUDIODEV(dev)) {
                case SOUND_DEVICE:
@@ -1708,8 +1746,9 @@
                        break;
                }
 
-               audio_file_exit(sc, &sc_ref);
-       }
+               audio_sc_release(sc, &sc_ref);
+       }
+       curlwp_bindx(bound);
 
        /* Free memory objects anyway */
        TRACEF(2, file, "free memory");
@@ -1730,6 +1769,7 @@
        struct audio_softc *sc;
        struct psref sc_ref;
        audio_file_t *file;
+       int bound;
        int error;
        dev_t dev;
 
@@ -1737,9 +1777,12 @@
        file = fp->f_audioctx;
        dev = file->dev;
 
-       sc = audio_file_enter(file, &sc_ref);
-       if (sc == NULL)
-               return EIO;
+       bound = curlwp_bind();
+       sc = audio_sc_acquire_fromfile(file, &sc_ref);
+       if (sc == NULL) {
+               error = EIO;
+               goto done;
+       }
 
        if (fp->f_flag & O_NONBLOCK)
                ioflag |= IO_NDELAY;
@@ -1758,7 +1801,9 @@
                break;
        }
 
-       audio_file_exit(sc, &sc_ref);
+       audio_sc_release(sc, &sc_ref);
+done:
+       curlwp_bindx(bound);
        return error;
 }
 
@@ -1769,6 +1814,7 @@
        struct audio_softc *sc;
        struct psref sc_ref;
        audio_file_t *file;
+       int bound;
        int error;
        dev_t dev;
 
@@ -1776,9 +1822,12 @@
        file = fp->f_audioctx;
        dev = file->dev;
 
-       sc = audio_file_enter(file, &sc_ref);
-       if (sc == NULL)
-               return EIO;
+       bound = curlwp_bind();
+       sc = audio_sc_acquire_fromfile(file, &sc_ref);
+       if (sc == NULL) {
+               error = EIO;
+               goto done;
+       }
 
        if (fp->f_flag & O_NONBLOCK)
                ioflag |= IO_NDELAY;
@@ -1797,7 +1846,9 @@
                break;
        }
 
-       audio_file_exit(sc, &sc_ref);
+       audio_sc_release(sc, &sc_ref);
+done:
+       curlwp_bindx(bound);
        return error;
 }
 
@@ -1808,6 +1859,7 @@
        struct psref sc_ref;
        audio_file_t *file;
        struct lwp *l = curlwp;
+       int bound;
        int error;
        dev_t dev;
 
@@ -1815,9 +1867,12 @@
        file = fp->f_audioctx;
        dev = file->dev;
 
-       sc = audio_file_enter(file, &sc_ref);
-       if (sc == NULL)
-               return EIO;
+       bound = curlwp_bind();
+       sc = audio_sc_acquire_fromfile(file, &sc_ref);
+       if (sc == NULL) {
+               error = EIO;
+               goto done;
+       }
 
        switch (AUDIODEV(dev)) {
        case SOUND_DEVICE:
@@ -1840,7 +1895,9 @@
                break;
        }
 
-       audio_file_exit(sc, &sc_ref);
+       audio_sc_release(sc, &sc_ref);
+done:
+       curlwp_bindx(bound);
        return error;
 }
 
@@ -1850,14 +1907,20 @@
        struct audio_softc *sc;
        struct psref sc_ref;
        audio_file_t *file;
+       int bound;
+       int error;
 
        KASSERT(fp->f_audioctx);
        file = fp->f_audioctx;



Home | Main Index | Thread Index | Old Index