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 <skywizard@MyBSD.org.my>
LOR:		159 [1]
Discussed with:	yongari [1]
This commit is contained in:
Alexander Leidinger 2005-10-02 15:43:57 +00:00
parent 62340837c3
commit 28ef3fb011
3 changed files with 42 additions and 51 deletions

View File

@ -84,20 +84,17 @@ static int sndstat_prepare(struct sbuf *s);
static int static int
sysctl_hw_sndverbose(SYSCTL_HANDLER_ARGS) sysctl_hw_sndverbose(SYSCTL_HANDLER_ARGS)
{ {
intrmask_t s;
int error, verbose; int error, verbose;
verbose = sndstat_verbose; verbose = sndstat_verbose;
error = sysctl_handle_int(oidp, &verbose, sizeof(verbose), req); error = sysctl_handle_int(oidp, &verbose, sizeof(verbose), req);
if (error == 0 && req->newptr != NULL) { if (error == 0 && req->newptr != NULL) {
s = spltty();
sx_xlock(&sndstat_lock); sx_xlock(&sndstat_lock);
if (verbose < 0 || verbose > 3) if (verbose < 0 || verbose > 3)
error = EINVAL; error = EINVAL;
else else
sndstat_verbose = verbose; sndstat_verbose = verbose;
sx_xunlock(&sndstat_lock); sx_xunlock(&sndstat_lock);
splx(s);
} }
return error; return error;
} }
@ -107,19 +104,15 @@ SYSCTL_PROC(_hw_snd, OID_AUTO, verbose, CTLTYPE_INT | CTLFLAG_RW,
static int static int
sndstat_open(struct cdev *i_dev, int flags, int mode, struct thread *td) sndstat_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
{ {
intrmask_t s;
int error; int error;
s = spltty();
sx_xlock(&sndstat_lock); sx_xlock(&sndstat_lock);
if (sndstat_isopen) { if (sndstat_isopen) {
sx_xunlock(&sndstat_lock); sx_xunlock(&sndstat_lock);
splx(s);
return EBUSY; return EBUSY;
} }
sndstat_isopen = 1; sndstat_isopen = 1;
sx_xunlock(&sndstat_lock); sx_xunlock(&sndstat_lock);
splx(s);
if (sbuf_new(&sndstat_sbuf, NULL, 4096, 0) == NULL) { if (sbuf_new(&sndstat_sbuf, NULL, 4096, 0) == NULL) {
error = ENXIO; error = ENXIO;
goto out; 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; error = (sndstat_prepare(&sndstat_sbuf) > 0) ? 0 : ENOMEM;
out: out:
if (error) { if (error) {
s = spltty();
sx_xlock(&sndstat_lock); sx_xlock(&sndstat_lock);
sndstat_isopen = 0; sndstat_isopen = 0;
sx_xunlock(&sndstat_lock); sx_xunlock(&sndstat_lock);
splx(s);
} }
return (error); return (error);
} }
@ -140,34 +131,26 @@ sndstat_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
static int static int
sndstat_close(struct cdev *i_dev, int flags, int mode, struct thread *td) sndstat_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
{ {
intrmask_t s;
s = spltty();
sx_xlock(&sndstat_lock); sx_xlock(&sndstat_lock);
if (!sndstat_isopen) { if (!sndstat_isopen) {
sx_xunlock(&sndstat_lock); sx_xunlock(&sndstat_lock);
splx(s);
return EBADF; return EBADF;
} }
sbuf_delete(&sndstat_sbuf); sbuf_delete(&sndstat_sbuf);
sndstat_isopen = 0; sndstat_isopen = 0;
sx_xunlock(&sndstat_lock); sx_xunlock(&sndstat_lock);
splx(s);
return 0; return 0;
} }
static int static int
sndstat_read(struct cdev *i_dev, struct uio *buf, int flag) sndstat_read(struct cdev *i_dev, struct uio *buf, int flag)
{ {
intrmask_t s;
int l, err; int l, err;
s = spltty();
sx_xlock(&sndstat_lock); sx_xlock(&sndstat_lock);
if (!sndstat_isopen) { if (!sndstat_isopen) {
sx_xunlock(&sndstat_lock); sx_xunlock(&sndstat_lock);
splx(s);
return EBADF; return EBADF;
} }
l = min(buf->uio_resid, sbuf_len(&sndstat_sbuf) - sndstat_bufptr); 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; sndstat_bufptr += l;
sx_xunlock(&sndstat_lock); sx_xunlock(&sndstat_lock);
splx(s);
return err; return err;
} }
@ -194,10 +176,35 @@ sndstat_find(int type, int unit)
return NULL; 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 int
sndstat_register(device_t dev, char *str, sndstat_handler handler) sndstat_register(device_t dev, char *str, sndstat_handler handler)
{ {
intrmask_t s;
struct sndstat_entry *ent; struct sndstat_entry *ent;
const char *devtype; const char *devtype;
int type, unit; int type, unit;
@ -228,14 +235,12 @@ sndstat_register(device_t dev, char *str, sndstat_handler handler)
ent->unit = unit; ent->unit = unit;
ent->handler = handler; ent->handler = handler;
s = spltty();
sx_xlock(&sndstat_lock); sx_xlock(&sndstat_lock);
SLIST_INSERT_HEAD(&sndstat_devlist, ent, link); SLIST_INSERT_HEAD(&sndstat_devlist, ent, link);
if (type == SS_TYPE_MODULE) if (type == SS_TYPE_MODULE)
sndstat_files++; sndstat_files++;
sndstat_maxunit = (unit > sndstat_maxunit)? unit : sndstat_maxunit; sndstat_maxunit = (unit > sndstat_maxunit)? unit : sndstat_maxunit;
sx_xunlock(&sndstat_lock); sx_xunlock(&sndstat_lock);
splx(s);
return 0; return 0;
} }
@ -249,23 +254,19 @@ sndstat_registerfile(char *str)
int int
sndstat_unregister(device_t dev) sndstat_unregister(device_t dev)
{ {
intrmask_t s;
struct sndstat_entry *ent; struct sndstat_entry *ent;
s = spltty();
sx_xlock(&sndstat_lock); sx_xlock(&sndstat_lock);
SLIST_FOREACH(ent, &sndstat_devlist, link) { SLIST_FOREACH(ent, &sndstat_devlist, link) {
if (ent->dev == dev) { if (ent->dev == dev) {
SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link); SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
sx_xunlock(&sndstat_lock); sx_xunlock(&sndstat_lock);
splx(s);
free(ent, M_DEVBUF); free(ent, M_DEVBUF);
return 0; return 0;
} }
} }
sx_xunlock(&sndstat_lock); sx_xunlock(&sndstat_lock);
splx(s);
return ENXIO; return ENXIO;
} }
@ -273,24 +274,20 @@ sndstat_unregister(device_t dev)
int int
sndstat_unregisterfile(char *str) sndstat_unregisterfile(char *str)
{ {
intrmask_t s;
struct sndstat_entry *ent; struct sndstat_entry *ent;
s = spltty();
sx_xlock(&sndstat_lock); sx_xlock(&sndstat_lock);
SLIST_FOREACH(ent, &sndstat_devlist, link) { SLIST_FOREACH(ent, &sndstat_devlist, link) {
if (ent->dev == NULL && ent->str == str) { if (ent->dev == NULL && ent->str == str) {
SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link); SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link);
sndstat_files--; sndstat_files--;
sx_xunlock(&sndstat_lock); sx_xunlock(&sndstat_lock);
splx(s);
free(ent, M_DEVBUF); free(ent, M_DEVBUF);
return 0; return 0;
} }
} }
sx_xunlock(&sndstat_lock); sx_xunlock(&sndstat_lock);
splx(s);
return ENXIO; return ENXIO;
} }
@ -353,13 +350,9 @@ sndstat_init(void)
static int static int
sndstat_uninit(void) sndstat_uninit(void)
{ {
intrmask_t s;
s = spltty();
sx_xlock(&sndstat_lock); sx_xlock(&sndstat_lock);
if (sndstat_isopen) { if (sndstat_isopen) {
sx_xunlock(&sndstat_lock); sx_xunlock(&sndstat_lock);
splx(s);
return EBUSY; return EBUSY;
} }
@ -367,18 +360,11 @@ sndstat_uninit(void)
destroy_dev(sndstat_dev); destroy_dev(sndstat_dev);
sndstat_dev = 0; sndstat_dev = 0;
splx(s);
sx_xunlock(&sndstat_lock); sx_xunlock(&sndstat_lock);
sx_destroy(&sndstat_lock); sx_destroy(&sndstat_lock);
return 0; return 0;
} }
int
sndstat_busy(void)
{
return (sndstat_isopen);
}
static void static void
sndstat_sysinit(void *p) sndstat_sysinit(void *p)
{ {

View File

@ -718,7 +718,6 @@ pcm_register(device_t dev, void *devinfo, int numplay, int numrec)
d->vchancount = 0; d->vchancount = 0;
d->inprog = 0; d->inprog = 0;
SLIST_INIT(&d->channels);
SLIST_INIT(&d->channels); SLIST_INIT(&d->channels);
if (((numplay == 0) || (numrec == 0)) && (numplay != numrec)) if (((numplay == 0) || (numrec == 0)) && (numplay != numrec))
@ -758,24 +757,25 @@ pcm_unregister(device_t dev)
struct snddev_channel *sce; struct snddev_channel *sce;
struct pcm_channel *ch; struct pcm_channel *ch;
if (sndstat_acquire() != 0) {
device_printf(dev, "unregister: sndstat busy\n");
return EBUSY;
}
snd_mtxlock(d->lock); snd_mtxlock(d->lock);
if (d->inprog) { if (d->inprog) {
device_printf(dev, "unregister: operation in progress\n"); device_printf(dev, "unregister: operation in progress\n");
snd_mtxunlock(d->lock); snd_mtxunlock(d->lock);
sndstat_release();
return EBUSY; 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) { SLIST_FOREACH(sce, &d->channels, link) {
ch = sce->channel; ch = sce->channel;
if (ch->refcount > 0) { if (ch->refcount > 0) {
device_printf(dev, "unregister: channel %s busy (pid %d)\n", ch->name, ch->pid); device_printf(dev, "unregister: channel %s busy (pid %d)\n", ch->name, ch->pid);
snd_mtxunlock(d->lock); snd_mtxunlock(d->lock);
sndstat_release();
return EBUSY; return EBUSY;
} }
} }
@ -783,6 +783,7 @@ pcm_unregister(device_t dev)
if (mixer_uninit(dev)) { if (mixer_uninit(dev)) {
device_printf(dev, "unregister: mixer busy\n"); device_printf(dev, "unregister: mixer busy\n");
snd_mtxunlock(d->lock); snd_mtxunlock(d->lock);
sndstat_release();
return EBUSY; return EBUSY;
} }
@ -807,9 +808,10 @@ pcm_unregister(device_t dev)
chn_kill(d->fakechan); chn_kill(d->fakechan);
fkchan_kill(d->fakechan); fkchan_kill(d->fakechan);
sndstat_unregister(dev);
snd_mtxunlock(d->lock); snd_mtxunlock(d->lock);
snd_mtxfree(d->lock); snd_mtxfree(d->lock);
sndstat_unregister(dev);
sndstat_release();
return 0; 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); sbuf_printf(s, "(0x%08x -> 0x%08x)", f->desc->in, f->desc->out);
if (f->desc->type == FEEDER_RATE) if (f->desc->type == FEEDER_RATE)
sbuf_printf(s, "(%d -> %d)", FEEDER_GET(f, FEEDRATE_SRC), FEEDER_GET(f, FEEDRATE_DST)); 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, "(0x%08x)", f->desc->out);
sbuf_printf(s, " -> "); sbuf_printf(s, " -> ");
f = f->parent; f = f->parent;

View File

@ -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 PCMMKMINOR(u, d, c) ((((c) & 0xff) << 16) | (((u) & 0x0f) << 4) | ((d) & 0x0f))
#define SD_F_SIMPLEX 0x00000001 #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_RD 0x10000000
#define SD_F_PRIO_WR 0x20000000 #define SD_F_PRIO_WR 0x20000000
#define SD_F_PRIO_SET (SD_F_PRIO_RD | SD_F_PRIO_WR) #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); int sysctl_hw_snd_vchans(SYSCTL_HANDLER_ARGS);
typedef int (*sndstat_handler)(struct sbuf *s, device_t dev, int verbose); 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_register(device_t dev, char *str, sndstat_handler handler);
int sndstat_registerfile(char *str); int sndstat_registerfile(char *str);
int sndstat_unregister(device_t dev); int sndstat_unregister(device_t dev);
int sndstat_unregisterfile(char *str); int sndstat_unregisterfile(char *str);
int sndstat_busy(void);
#define SND_DECLARE_FILE(version) \ #define SND_DECLARE_FILE(version) \
_SND_DECLARE_FILE(__LINE__, version) _SND_DECLARE_FILE(__LINE__, version)