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:
parent
62340837c3
commit
28ef3fb011
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user