Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/audio Simplify async_mixer handling.



details:   https://anonhg.NetBSD.org/src/rev/e51d5aebac08
branches:  trunk
changeset: 467038:e51d5aebac08
user:      isaki <isaki%NetBSD.org@localhost>
date:      Sat Jan 11 04:53:10 2020 +0000

description:
Simplify async_mixer handling.
- It makes FIOASYNC code in mixer_ioctl() symmetric.
- For readability, mixer_async_{add,remove}() should take pid argument
  though pid is always curproc.

diffstat:

 sys/dev/audio/audio.c    |  100 +++++++++++++++++++++++++++++++++-------------
 sys/dev/audio/audiovar.h |   14 +++--
 2 files changed, 79 insertions(+), 35 deletions(-)

diffs (217 lines):

diff -r 75dbb745f8bb -r e51d5aebac08 sys/dev/audio/audio.c
--- a/sys/dev/audio/audio.c     Sat Jan 11 04:06:13 2020 +0000
+++ b/sys/dev/audio/audio.c     Sat Jan 11 04:53:10 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: audio.c,v 1.40 2020/01/11 04:06:13 isaki Exp $ */
+/*     $NetBSD: audio.c,v 1.41 2020/01/11 04:53:10 isaki Exp $ */
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -142,7 +142,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.40 2020/01/11 04:06:13 isaki Exp $");
+__KERNEL_RCSID(0, "$NetBSD: audio.c,v 1.41 2020/01/11 04:53:10 isaki Exp $");
 
 #ifdef _KERNEL_OPT
 #include "audio.h"
@@ -463,6 +463,9 @@
 int audio_idle_timeout = 30;
 #endif
 
+/* Number of elements of async mixer's pid */
+#define AM_CAPACITY    (4)
+
 struct portname {
        const char *name;
        int mask;
@@ -604,7 +607,8 @@
 static int mixer_open(dev_t, struct audio_softc *, int, int, struct lwp *);
 static int mixer_close(struct audio_softc *, audio_file_t *);
 static int mixer_ioctl(struct audio_softc *, u_long, void *, int, struct lwp *);
-static void mixer_remove(struct audio_softc *);
+static void mixer_async_add(struct audio_softc *, pid_t);
+static void mixer_async_remove(struct audio_softc *, pid_t);
 static void mixer_signal(struct audio_softc *);
 
 static int au_portof(struct audio_softc *, char *, int);
@@ -878,6 +882,9 @@
        sc->sc_blk_ms = AUDIO_BLK_MS;
        SLIST_INIT(&sc->sc_files);
        cv_init(&sc->sc_exlockcv, "audiolk");
+       sc->sc_am_capacity = 0;
+       sc->sc_am_used = 0;
+       sc->sc_am = NULL;
 
        mutex_enter(sc->sc_lock);
        sc->sc_props = hw_if->get_props(sc->hw_hdl);
@@ -1283,6 +1290,8 @@
                kmem_free(sc->sc_rmixer, sizeof(*sc->sc_rmixer));
        }
        mutex_exit(sc->sc_lock);
+       if (sc->sc_am)
+               kern_free(sc->sc_am);
 
        seldestroy(&sc->sc_wsel);
        seldestroy(&sc->sc_rsel);
@@ -7604,23 +7613,60 @@
 }
 
 /*
- * Remove a process from those to be signalled on mixer activity.
+ * Add a process to those to be signalled on mixer activity.
+ * If the process has already been added, do nothing.
  * Must be called with sc_lock held.
  */
 static void
-mixer_remove(struct audio_softc *sc)
-{
-       struct mixer_asyncs **pm, *m;
-       pid_t pid;
+mixer_async_add(struct audio_softc *sc, pid_t pid)
+{
+       int i;
 
        KASSERT(mutex_owned(sc->sc_lock));
 
-       pid = curproc->p_pid;
-       for (pm = &sc->sc_async_mixer; *pm; pm = &(*pm)->next) {
-               if ((*pm)->pid == pid) {
-                       m = *pm;
-                       *pm = m->next;
-                       kmem_free(m, sizeof(*m));
+       /* If already exists, returns without doing anything. */
+       for (i = 0; i < sc->sc_am_used; i++) {
+               if (sc->sc_am[i] == pid)
+                       return;
+       }
+
+       /* Extend array if necessary. */
+       if (sc->sc_am_used >= sc->sc_am_capacity) {
+               sc->sc_am_capacity += AM_CAPACITY;
+               sc->sc_am = kern_realloc(sc->sc_am,
+                   sc->sc_am_capacity * sizeof(pid_t), M_WAITOK);
+               TRACE(2, "realloc am_capacity=%d", sc->sc_am_capacity);
+       }
+
+       TRACE(2, "am[%d]=%d", sc->sc_am_used, (int)pid);
+       sc->sc_am[sc->sc_am_used++] = pid;
+}
+
+/*
+ * Remove a process from those to be signalled on mixer activity.
+ * If the process has not been added, do nothing.
+ * Must be called with sc_lock held.
+ */
+static void
+mixer_async_remove(struct audio_softc *sc, pid_t pid)
+{
+       int i;
+
+       KASSERT(mutex_owned(sc->sc_lock));
+
+       for (i = 0; i < sc->sc_am_used; i++) {
+               if (sc->sc_am[i] == pid) {
+                       sc->sc_am[i] = sc->sc_am[--sc->sc_am_used];
+                       TRACE(2, "am[%d](%d) removed, used=%d",
+                           i, (int)pid, sc->sc_am_used);
+
+                       /* Empty array if no longer necessary. */
+                       if (sc->sc_am_used == 0) {
+                               kern_free(sc->sc_am);
+                               sc->sc_am = NULL;
+                               sc->sc_am_capacity = 0;
+                               TRACE(2, "released");
+                       }
                        return;
                }
        }
@@ -7633,12 +7679,15 @@
 static void
 mixer_signal(struct audio_softc *sc)
 {
-       struct mixer_asyncs *m;
        proc_t *p;
-
-       for (m = sc->sc_async_mixer; m; m = m->next) {
+       int i;
+
+       KASSERT(mutex_owned(sc->sc_lock));
+
+       for (i = 0; i < sc->sc_am_used; i++) {
                mutex_enter(proc_lock);
-               if ((p = proc_find(m->pid)) != NULL)
+               p = proc_find(sc->sc_am[i]);
+               if (p)
                        psignal(p, SIGIO);
                mutex_exit(proc_lock);
        }
@@ -7653,7 +7702,7 @@
 
        mutex_enter(sc->sc_lock);
        TRACE(1, "");
-       mixer_remove(sc);
+       mixer_async_remove(sc, curproc->p_pid);
        mutex_exit(sc->sc_lock);
 
        kmem_free(file, sizeof(*file));
@@ -7664,7 +7713,6 @@
 mixer_ioctl(struct audio_softc *sc, u_long cmd, void *addr, int flag,
        struct lwp *l)
 {
-       struct mixer_asyncs *ma;
        mixer_devinfo_t *mi;
        mixer_ctrl_t *mc;
        int error;
@@ -7684,17 +7732,11 @@
 
        switch (cmd) {
        case FIOASYNC:
+               mutex_enter(sc->sc_lock);
                if (*(int *)addr) {
-                       ma = kmem_alloc(sizeof(struct mixer_asyncs), KM_SLEEP);
+                       mixer_async_add(sc, curproc->p_pid);
                } else {
-                       ma = NULL;
-               }
-               mutex_enter(sc->sc_lock);
-               mixer_remove(sc);       /* remove old entry */
-               if (ma != NULL) {
-                       ma->next = sc->sc_async_mixer;
-                       ma->pid = curproc->p_pid;
-                       sc->sc_async_mixer = ma;
+                       mixer_async_remove(sc, curproc->p_pid);
                }
                mutex_exit(sc->sc_lock);
                error = 0;
diff -r 75dbb745f8bb -r e51d5aebac08 sys/dev/audio/audiovar.h
--- a/sys/dev/audio/audiovar.h  Sat Jan 11 04:06:13 2020 +0000
+++ b/sys/dev/audio/audiovar.h  Sat Jan 11 04:53:10 2020 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: audiovar.h,v 1.6 2020/01/11 04:06:13 isaki Exp $       */
+/*     $NetBSD: audiovar.h,v 1.7 2020/01/11 04:53:10 isaki Exp $       */
 
 /*-
  * Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -194,13 +194,15 @@
        struct selinfo sc_rsel;
 
        /*
-        * processes who want mixer SIGIO.
+        * Processes who want mixer SIGIO.
+        * sc_am is an array of pids, or NULL if empty.
+        * sc_am_capacity is the number of allocated elements.
+        * sc_am_used is the number of elements actually used.
         * Must be protected by sc_lock.
         */
-       struct  mixer_asyncs {
-               struct mixer_asyncs *next;
-               pid_t   pid;
-       } *sc_async_mixer;
+       pid_t *sc_am;
+       int sc_am_capacity;
+       int sc_am_used;
 
        /*
         * Thread lock and interrupt lock obtained by get_locks().



Home | Main Index | Thread Index | Old Index