Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/audio audio(4): Use d_cfdriver/devtounit to avoid op...



details:   https://anonhg.NetBSD.org/src/rev/e70876c624a4
branches:  trunk
changeset: 364531:e70876c624a4
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Mon Mar 28 12:39:57 2022 +0000

description:
audio(4): Use d_cfdriver/devtounit to avoid open/detach races.

diffstat:

 sys/dev/audio/audio.c |  99 +++++++++++++++++++++++---------------------------
 1 files changed, 45 insertions(+), 54 deletions(-)

diffs (178 lines):

diff -r 2446c6990afb -r e70876c624a4 sys/dev/audio/audio.c
--- a/sys/dev/audio/audio.c     Mon Mar 28 12:39:46 2022 +0000
+++ b/sys/dev/audio/audio.c     Mon Mar 28 12:39:57 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: audio.c,v 1.120 2022/03/26 06:49:27 isaki Exp $        */
+/*     $NetBSD: audio.c,v 1.121 2022/03/28 12:39:57 riastradh Exp $    */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -181,7 +181,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.120 2022/03/26 06:49:27 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.121 2022/03/28 12:39:57 riastradh Exp $");
 
 #ifdef _KERNEL_OPT
 #include "audio.h"
@@ -567,7 +567,6 @@
 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 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 *);
@@ -766,6 +765,13 @@
 static dev_type_open(audioopen);
 /* XXXMRG use more dev_type_xxx */
 
+static int
+audiounit(dev_t dev)
+{
+
+       return AUDIOUNIT(dev);
+}
+
 const struct cdevsw audio_cdevsw = {
        .d_open = audioopen,
        .d_close = noclose,
@@ -778,6 +784,8 @@
        .d_mmap = nommap,
        .d_kqfilter = nokqfilter,
        .d_discard = nodiscard,
+       .d_cfdriver = &audio_cd,
+       .d_devtounit = audiounit,
        .d_flag = D_OTHER | D_MPSAFE
 };
 
@@ -1590,31 +1598,6 @@
 }
 
 /*
- * 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.
@@ -1732,21 +1715,20 @@
 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 */
+       /*
+        * Find the device.  Because we wired the cdevsw to the audio
+        * autoconf instance, the system ensures it will not go away
+        * until after we return.
+        */
        sc = device_lookup_private(&audio_cd, AUDIOUNIT(dev));
        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)
-               goto done;
+               return error;
 
        device_active(sc->sc_dev, DVA_SYSTEM);
        switch (AUDIODEV(dev)) {
@@ -1766,9 +1748,6 @@
        }
        audio_exlock_exit(sc);
 
-done:
-       audio_sc_release(sc, &sc_ref);
-       curlwp_bindx(bound);
        return error;
 }
 
@@ -2150,30 +2129,42 @@
 int
 audiobellopen(dev_t dev, audio_file_t **filep)
 {
+       device_t audiodev = NULL;
        struct audio_softc *sc;
-       struct psref sc_ref;
-       int bound;
+       bool exlock = false;
        int error;
 
-       /* Find the device */
-       sc = device_lookup_private(&audio_cd, AUDIOUNIT(dev));
-       if (sc == NULL || sc->hw_if == NULL)
-               return ENXIO;
-
-       bound = curlwp_bind();
-       audio_sc_acquire_foropen(sc, &sc_ref);
-
+       /*
+        * Find the autoconf instance and make sure it doesn't go away
+        * while we are opening it.
+        */
+       audiodev = device_lookup_acquire(&audio_cd, AUDIOUNIT(dev));
+       if (audiodev == NULL) {
+               error = ENXIO;
+               goto out;
+       }
+
+       /* If attach failed, it's hopeless -- give up.  */
+       sc = device_private(audiodev);
+       if (sc->hw_if == NULL) {
+               error = ENXIO;
+               goto out;
+       }
+
+       /* Take the exclusive configuration lock.  */
        error = audio_exlock_enter(sc);
        if (error)
-               goto done;
-
+               goto out;
+       exlock = true;
+
+       /* Open the audio device.  */
        device_active(sc->sc_dev, DVA_SYSTEM);
        error = audio_open(dev, sc, FWRITE, 0, curlwp, filep);
 
-       audio_exlock_exit(sc);
-done:
-       audio_sc_release(sc, &sc_ref);
-       curlwp_bindx(bound);
+out:   if (exlock)
+               audio_exlock_exit(sc);
+       if (audiodev)
+               device_release(audiodev);
        return error;
 }
 



Home | Main Index | Thread Index | Old Index