Module Name:    src
Committed By:   isaki
Date:           Sat Jan 11 04:53:10 UTC 2020

Modified Files:
        src/sys/dev/audio: audio.c audiovar.h

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.40 -r1.41 src/sys/dev/audio/audio.c
cvs rdiff -u -r1.6 -r1.7 src/sys/dev/audio/audiovar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/audio/audio.c
diff -u src/sys/dev/audio/audio.c:1.40 src/sys/dev/audio/audio.c:1.41
--- src/sys/dev/audio/audio.c:1.40	Sat Jan 11 04:06:13 2020
+++ src/sys/dev/audio/audio.c	Sat Jan 11 04:53:10 2020
@@ -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 @@ audio_track_bufstat(audio_track_t *track
 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 void mixer_init(struct audio_soft
 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 @@ audioattach(device_t parent, device_t se
 	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 @@ audiodetach(device_t self, int flags)
 		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 @@ mixer_open(dev_t dev, struct audio_softc
 }
 
 /*
+ * 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_async_add(struct audio_softc *sc, pid_t pid)
+{
+	int i;
+
+	KASSERT(mutex_owned(sc->sc_lock));
+
+	/* 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_remove(struct audio_softc *sc)
+mixer_async_remove(struct audio_softc *sc, pid_t pid)
 {
-	struct mixer_asyncs **pm, *m;
-	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));
+	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 @@ mixer_remove(struct audio_softc *sc)
 static void
 mixer_signal(struct audio_softc *sc)
 {
-	struct mixer_asyncs *m;
 	proc_t *p;
+	int i;
+
+	KASSERT(mutex_owned(sc->sc_lock));
 
-	for (m = sc->sc_async_mixer; m; m = m->next) {
+	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 @@ mixer_close(struct audio_softc *sc, audi
 
 	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 @@ int
 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 @@ mixer_ioctl(struct audio_softc *sc, u_lo
 
 	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;

Index: src/sys/dev/audio/audiovar.h
diff -u src/sys/dev/audio/audiovar.h:1.6 src/sys/dev/audio/audiovar.h:1.7
--- src/sys/dev/audio/audiovar.h:1.6	Sat Jan 11 04:06:13 2020
+++ src/sys/dev/audio/audiovar.h	Sat Jan 11 04:53:10 2020
@@ -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 audio_softc {
 	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().

Reply via email to