From 28ef3fb011011127527f8057c33b87dc6e66a2fb Mon Sep 17 00:00:00 2001 From: Alexander Leidinger Date: Sun, 2 Oct 2005 15:43:57 +0000 Subject: [PATCH] sys/dev/sound/pcm/sndstat.c: * General spl* cleanup. It doesn't serve any purpose anymore. * Nuke sndstat_busy(). Addition of sndstat_acquire() / sndstat_release() for sndstat exclusive access. [1] sys/dev/sound/pcm/sound.c: * Remove duplicate SLIST_INIT() * Use sndstat_acquire() / release() to lock / release the entire sndstat during pcm_unregister(). This should fix LOR #159 [1] sys/dev/sound/pcm/sound.h: * Definition of SD_F_SOFTVOL (part of feeder volume) * Nuke sndstat_busy(). Addition of sndstat_acquire() / sndstat_release() for exclusive sndstat access. [1] Submitted by: Ariff Abdullah LOR: 159 [1] Discussed with: yongari [1] --- sys/dev/sound/pcm/sndstat.c | 66 +++++++++++++++---------------------- sys/dev/sound/pcm/sound.c | 21 +++++++----- sys/dev/sound/pcm/sound.h | 6 ++-- 3 files changed, 42 insertions(+), 51 deletions(-) diff --git a/sys/dev/sound/pcm/sndstat.c b/sys/dev/sound/pcm/sndstat.c index 5ccf0b7a6d72..5b07ece13d2f 100644 --- a/sys/dev/sound/pcm/sndstat.c +++ b/sys/dev/sound/pcm/sndstat.c @@ -84,20 +84,17 @@ static int sndstat_prepare(struct sbuf *s); static int sysctl_hw_sndverbose(SYSCTL_HANDLER_ARGS) { - intrmask_t s; int error, verbose; verbose = sndstat_verbose; error = sysctl_handle_int(oidp, &verbose, sizeof(verbose), req); if (error == 0 && req->newptr != NULL) { - s = spltty(); sx_xlock(&sndstat_lock); if (verbose < 0 || verbose > 3) error = EINVAL; else sndstat_verbose = verbose; sx_xunlock(&sndstat_lock); - splx(s); } return error; } @@ -107,19 +104,15 @@ SYSCTL_PROC(_hw_snd, OID_AUTO, verbose, CTLTYPE_INT | CTLFLAG_RW, static int sndstat_open(struct cdev *i_dev, int flags, int mode, struct thread *td) { - intrmask_t s; int error; - s = spltty(); sx_xlock(&sndstat_lock); if (sndstat_isopen) { sx_xunlock(&sndstat_lock); - splx(s); return EBUSY; } sndstat_isopen = 1; sx_xunlock(&sndstat_lock); - splx(s); if (sbuf_new(&sndstat_sbuf, NULL, 4096, 0) == NULL) { error = ENXIO; goto out; @@ -128,11 +121,9 @@ sndstat_open(struct cdev *i_dev, int flags, int mode, struct thread *td) error = (sndstat_prepare(&sndstat_sbuf) > 0) ? 0 : ENOMEM; out: if (error) { - s = spltty(); sx_xlock(&sndstat_lock); sndstat_isopen = 0; sx_xunlock(&sndstat_lock); - splx(s); } return (error); } @@ -140,34 +131,26 @@ sndstat_open(struct cdev *i_dev, int flags, int mode, struct thread *td) static int sndstat_close(struct cdev *i_dev, int flags, int mode, struct thread *td) { - intrmask_t s; - - s = spltty(); sx_xlock(&sndstat_lock); if (!sndstat_isopen) { sx_xunlock(&sndstat_lock); - splx(s); return EBADF; } sbuf_delete(&sndstat_sbuf); sndstat_isopen = 0; sx_xunlock(&sndstat_lock); - splx(s); return 0; } static int sndstat_read(struct cdev *i_dev, struct uio *buf, int flag) { - intrmask_t s; int l, err; - s = spltty(); sx_xlock(&sndstat_lock); if (!sndstat_isopen) { sx_xunlock(&sndstat_lock); - splx(s); return EBADF; } l = min(buf->uio_resid, sbuf_len(&sndstat_sbuf) - sndstat_bufptr); @@ -175,7 +158,6 @@ sndstat_read(struct cdev *i_dev, struct uio *buf, int flag) sndstat_bufptr += l; sx_xunlock(&sndstat_lock); - splx(s); return err; } @@ -194,10 +176,35 @@ sndstat_find(int type, int unit) return NULL; } +int +sndstat_acquire(void) +{ + sx_xlock(&sndstat_lock); + if (sndstat_isopen) { + sx_xunlock(&sndstat_lock); + return EBUSY; + } + sndstat_isopen = 1; + sx_xunlock(&sndstat_lock); + return 0; +} + +int +sndstat_release(void) +{ + sx_xlock(&sndstat_lock); + if (!sndstat_isopen) { + sx_xunlock(&sndstat_lock); + return EBADF; + } + sndstat_isopen = 0; + sx_xunlock(&sndstat_lock); + return 0; +} + int sndstat_register(device_t dev, char *str, sndstat_handler handler) { - intrmask_t s; struct sndstat_entry *ent; const char *devtype; int type, unit; @@ -228,14 +235,12 @@ sndstat_register(device_t dev, char *str, sndstat_handler handler) ent->unit = unit; ent->handler = handler; - s = spltty(); sx_xlock(&sndstat_lock); SLIST_INSERT_HEAD(&sndstat_devlist, ent, link); if (type == SS_TYPE_MODULE) sndstat_files++; sndstat_maxunit = (unit > sndstat_maxunit)? unit : sndstat_maxunit; sx_xunlock(&sndstat_lock); - splx(s); return 0; } @@ -249,23 +254,19 @@ sndstat_registerfile(char *str) int sndstat_unregister(device_t dev) { - intrmask_t s; struct sndstat_entry *ent; - s = spltty(); sx_xlock(&sndstat_lock); SLIST_FOREACH(ent, &sndstat_devlist, link) { if (ent->dev == dev) { SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link); sx_xunlock(&sndstat_lock); - splx(s); free(ent, M_DEVBUF); return 0; } } sx_xunlock(&sndstat_lock); - splx(s); return ENXIO; } @@ -273,24 +274,20 @@ sndstat_unregister(device_t dev) int sndstat_unregisterfile(char *str) { - intrmask_t s; struct sndstat_entry *ent; - s = spltty(); sx_xlock(&sndstat_lock); SLIST_FOREACH(ent, &sndstat_devlist, link) { if (ent->dev == NULL && ent->str == str) { SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link); sndstat_files--; sx_xunlock(&sndstat_lock); - splx(s); free(ent, M_DEVBUF); return 0; } } sx_xunlock(&sndstat_lock); - splx(s); return ENXIO; } @@ -353,13 +350,9 @@ sndstat_init(void) static int sndstat_uninit(void) { - intrmask_t s; - - s = spltty(); sx_xlock(&sndstat_lock); if (sndstat_isopen) { sx_xunlock(&sndstat_lock); - splx(s); return EBUSY; } @@ -367,18 +360,11 @@ sndstat_uninit(void) destroy_dev(sndstat_dev); sndstat_dev = 0; - splx(s); sx_xunlock(&sndstat_lock); sx_destroy(&sndstat_lock); return 0; } -int -sndstat_busy(void) -{ - return (sndstat_isopen); -} - static void sndstat_sysinit(void *p) { diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c index a5ce1d3e9013..4a9b2f92870c 100644 --- a/sys/dev/sound/pcm/sound.c +++ b/sys/dev/sound/pcm/sound.c @@ -718,7 +718,6 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec) d->vchancount = 0; d->inprog = 0; - SLIST_INIT(&d->channels); SLIST_INIT(&d->channels); if (((numplay == 0) || (numrec == 0)) && (numplay != numrec)) @@ -758,24 +757,25 @@ pcm_unregister(device_t dev) struct snddev_channel *sce; struct pcm_channel *ch; + if (sndstat_acquire() != 0) { + device_printf(dev, "unregister: sndstat busy\n"); + return EBUSY; + } + snd_mtxlock(d->lock); if (d->inprog) { device_printf(dev, "unregister: operation in progress\n"); snd_mtxunlock(d->lock); + sndstat_release(); return EBUSY; } - if (sndstat_busy() != 0) { - device_printf(dev, "unregister: sndstat busy\n"); - snd_mtxunlock(d->lock); - return EBUSY; - } - SLIST_FOREACH(sce, &d->channels, link) { ch = sce->channel; if (ch->refcount > 0) { device_printf(dev, "unregister: channel %s busy (pid %d)\n", ch->name, ch->pid); snd_mtxunlock(d->lock); + sndstat_release(); return EBUSY; } } @@ -783,6 +783,7 @@ pcm_unregister(device_t dev) if (mixer_uninit(dev)) { device_printf(dev, "unregister: mixer busy\n"); snd_mtxunlock(d->lock); + sndstat_release(); return EBUSY; } @@ -807,9 +808,10 @@ pcm_unregister(device_t dev) chn_kill(d->fakechan); fkchan_kill(d->fakechan); - sndstat_unregister(dev); snd_mtxunlock(d->lock); snd_mtxfree(d->lock); + sndstat_unregister(dev); + sndstat_release(); return 0; } @@ -905,7 +907,8 @@ sndstat_prepare_pcm(struct sbuf *s, device_t dev, int verbose) sbuf_printf(s, "(0x%08x -> 0x%08x)", f->desc->in, f->desc->out); if (f->desc->type == FEEDER_RATE) sbuf_printf(s, "(%d -> %d)", FEEDER_GET(f, FEEDRATE_SRC), FEEDER_GET(f, FEEDRATE_DST)); - if (f->desc->type == FEEDER_ROOT || f->desc->type == FEEDER_MIXER) + if (f->desc->type == FEEDER_ROOT || f->desc->type == FEEDER_MIXER || + f->desc->type == FEEDER_VOLUME) sbuf_printf(s, "(0x%08x)", f->desc->out); sbuf_printf(s, " -> "); f = f->parent; diff --git a/sys/dev/sound/pcm/sound.h b/sys/dev/sound/pcm/sound.h index 471e51dc9a2a..af539a66bf0b 100644 --- a/sys/dev/sound/pcm/sound.h +++ b/sys/dev/sound/pcm/sound.h @@ -130,7 +130,8 @@ currently minor = (channel << 16) + (unit << 4) + dev #define PCMMKMINOR(u, d, c) ((((c) & 0xff) << 16) | (((u) & 0x0f) << 4) | ((d) & 0x0f)) #define SD_F_SIMPLEX 0x00000001 -#define SD_F_AUTOVCHAN 0x00000002 +#define SD_F_AUTOVCHAN 0x00000002 +#define SD_F_SOFTVOL 0x00000004 #define SD_F_PRIO_RD 0x10000000 #define SD_F_PRIO_WR 0x20000000 #define SD_F_PRIO_SET (SD_F_PRIO_RD | SD_F_PRIO_WR) @@ -238,11 +239,12 @@ void snd_mtxassert(void *m); int sysctl_hw_snd_vchans(SYSCTL_HANDLER_ARGS); typedef int (*sndstat_handler)(struct sbuf *s, device_t dev, int verbose); +int sndstat_acquire(void); +int sndstat_release(void); int sndstat_register(device_t dev, char *str, sndstat_handler handler); int sndstat_registerfile(char *str); int sndstat_unregister(device_t dev); int sndstat_unregisterfile(char *str); -int sndstat_busy(void); #define SND_DECLARE_FILE(version) \ _SND_DECLARE_FILE(__LINE__, version)