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.
This commit is contained in:
parent
5ce2968c43
commit
febfde9c6a
@ -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, struct audio_track_debugbuf *buf)
|
||||
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_softc *);
|
||||
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 self, void *aux)
|
||||
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 *sc, int flags, int ifmt,
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
mixer_async_add(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));
|
||||
/* 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 @@ mixer_remove(struct audio_softc *sc)
|
||||
static void
|
||||
mixer_signal(struct audio_softc *sc)
|
||||
{
|
||||
struct mixer_asyncs *m;
|
||||
proc_t *p;
|
||||
int i;
|
||||
|
||||
for (m = sc->sc_async_mixer; m; m = m->next) {
|
||||
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 @@ mixer_close(struct audio_softc *sc, audio_file_t *file)
|
||||
|
||||
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_long cmd, void *addr, int flag,
|
||||
|
||||
switch (cmd) {
|
||||
case FIOASYNC:
|
||||
if (*(int *)addr) {
|
||||
ma = kmem_alloc(sizeof(struct mixer_asyncs), KM_SLEEP);
|
||||
} 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;
|
||||
if (*(int *)addr) {
|
||||
mixer_async_add(sc, curproc->p_pid);
|
||||
} else {
|
||||
mixer_async_remove(sc, curproc->p_pid);
|
||||
}
|
||||
mutex_exit(sc->sc_lock);
|
||||
error = 0;
|
||||
|
@ -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().
|
||||
|
Loading…
Reference in New Issue
Block a user