Convert sndstat_lock from a mutex to an sx lock. sndstat_read()
holds sndstat_lock across a call to uiomove(), which is not legal to do with a mutex because of the possibility that the data transfer could sleep because of a page fault. It is not possible to just unlock the mutex for the uiomove() call without introducing another locking mechanism to prevent the body of sndstat_read() from being re-entered. Converting sndstat_lock to an sx lock is the least complicated change. This is a candidate for RELENG_5. LOR: 030 MFC after: 4 days
This commit is contained in:
parent
8d70d0c0be
commit
ca219d048a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=135033
@ -26,6 +26,9 @@
|
|||||||
|
|
||||||
#include <dev/sound/pcm/sound.h>
|
#include <dev/sound/pcm/sound.h>
|
||||||
#include <dev/sound/pcm/vchan.h>
|
#include <dev/sound/pcm/vchan.h>
|
||||||
|
#ifdef USING_MUTEX
|
||||||
|
#include <sys/sx.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
SND_DECLARE_FILE("$FreeBSD$");
|
SND_DECLARE_FILE("$FreeBSD$");
|
||||||
|
|
||||||
@ -59,7 +62,7 @@ struct sndstat_entry {
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifdef USING_MUTEX
|
#ifdef USING_MUTEX
|
||||||
static struct mtx sndstat_lock;
|
static struct sx sndstat_lock;
|
||||||
#endif
|
#endif
|
||||||
static struct sbuf sndstat_sbuf;
|
static struct sbuf sndstat_sbuf;
|
||||||
static struct cdev *sndstat_dev = 0;
|
static struct cdev *sndstat_dev = 0;
|
||||||
@ -89,12 +92,12 @@ sysctl_hw_sndverbose(SYSCTL_HANDLER_ARGS)
|
|||||||
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();
|
s = spltty();
|
||||||
mtx_lock(&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;
|
||||||
mtx_unlock(&sndstat_lock);
|
sx_xunlock(&sndstat_lock);
|
||||||
splx(s);
|
splx(s);
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
@ -109,14 +112,14 @@ sndstat_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
|
|||||||
int error;
|
int error;
|
||||||
|
|
||||||
s = spltty();
|
s = spltty();
|
||||||
mtx_lock(&sndstat_lock);
|
sx_xlock(&sndstat_lock);
|
||||||
if (sndstat_isopen) {
|
if (sndstat_isopen) {
|
||||||
mtx_unlock(&sndstat_lock);
|
sx_xunlock(&sndstat_lock);
|
||||||
splx(s);
|
splx(s);
|
||||||
return EBUSY;
|
return EBUSY;
|
||||||
}
|
}
|
||||||
sndstat_isopen = 1;
|
sndstat_isopen = 1;
|
||||||
mtx_unlock(&sndstat_lock);
|
sx_xunlock(&sndstat_lock);
|
||||||
splx(s);
|
splx(s);
|
||||||
if (sbuf_new(&sndstat_sbuf, NULL, 4096, 0) == NULL) {
|
if (sbuf_new(&sndstat_sbuf, NULL, 4096, 0) == NULL) {
|
||||||
error = ENXIO;
|
error = ENXIO;
|
||||||
@ -127,9 +130,9 @@ sndstat_open(struct cdev *i_dev, int flags, int mode, struct thread *td)
|
|||||||
out:
|
out:
|
||||||
if (error) {
|
if (error) {
|
||||||
s = spltty();
|
s = spltty();
|
||||||
mtx_lock(&sndstat_lock);
|
sx_xlock(&sndstat_lock);
|
||||||
sndstat_isopen = 0;
|
sndstat_isopen = 0;
|
||||||
mtx_unlock(&sndstat_lock);
|
sx_xunlock(&sndstat_lock);
|
||||||
splx(s);
|
splx(s);
|
||||||
}
|
}
|
||||||
return (error);
|
return (error);
|
||||||
@ -141,16 +144,16 @@ sndstat_close(struct cdev *i_dev, int flags, int mode, struct thread *td)
|
|||||||
intrmask_t s;
|
intrmask_t s;
|
||||||
|
|
||||||
s = spltty();
|
s = spltty();
|
||||||
mtx_lock(&sndstat_lock);
|
sx_xlock(&sndstat_lock);
|
||||||
if (!sndstat_isopen) {
|
if (!sndstat_isopen) {
|
||||||
mtx_unlock(&sndstat_lock);
|
sx_xunlock(&sndstat_lock);
|
||||||
splx(s);
|
splx(s);
|
||||||
return EBADF;
|
return EBADF;
|
||||||
}
|
}
|
||||||
sbuf_delete(&sndstat_sbuf);
|
sbuf_delete(&sndstat_sbuf);
|
||||||
sndstat_isopen = 0;
|
sndstat_isopen = 0;
|
||||||
|
|
||||||
mtx_unlock(&sndstat_lock);
|
sx_xunlock(&sndstat_lock);
|
||||||
splx(s);
|
splx(s);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -162,9 +165,9 @@ sndstat_read(struct cdev *i_dev, struct uio *buf, int flag)
|
|||||||
int l, err;
|
int l, err;
|
||||||
|
|
||||||
s = spltty();
|
s = spltty();
|
||||||
mtx_lock(&sndstat_lock);
|
sx_xlock(&sndstat_lock);
|
||||||
if (!sndstat_isopen) {
|
if (!sndstat_isopen) {
|
||||||
mtx_unlock(&sndstat_lock);
|
sx_xunlock(&sndstat_lock);
|
||||||
splx(s);
|
splx(s);
|
||||||
return EBADF;
|
return EBADF;
|
||||||
}
|
}
|
||||||
@ -172,7 +175,7 @@ sndstat_read(struct cdev *i_dev, struct uio *buf, int flag)
|
|||||||
err = (l > 0)? uiomove(sbuf_data(&sndstat_sbuf) + sndstat_bufptr, l, buf) : 0;
|
err = (l > 0)? uiomove(sbuf_data(&sndstat_sbuf) + sndstat_bufptr, l, buf) : 0;
|
||||||
sndstat_bufptr += l;
|
sndstat_bufptr += l;
|
||||||
|
|
||||||
mtx_unlock(&sndstat_lock);
|
sx_xunlock(&sndstat_lock);
|
||||||
splx(s);
|
splx(s);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -227,12 +230,12 @@ sndstat_register(device_t dev, char *str, sndstat_handler handler)
|
|||||||
ent->handler = handler;
|
ent->handler = handler;
|
||||||
|
|
||||||
s = spltty();
|
s = spltty();
|
||||||
mtx_lock(&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;
|
||||||
mtx_unlock(&sndstat_lock);
|
sx_xunlock(&sndstat_lock);
|
||||||
splx(s);
|
splx(s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -251,18 +254,18 @@ sndstat_unregister(device_t dev)
|
|||||||
struct sndstat_entry *ent;
|
struct sndstat_entry *ent;
|
||||||
|
|
||||||
s = spltty();
|
s = spltty();
|
||||||
mtx_lock(&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);
|
||||||
mtx_unlock(&sndstat_lock);
|
sx_xunlock(&sndstat_lock);
|
||||||
splx(s);
|
splx(s);
|
||||||
free(ent, M_DEVBUF);
|
free(ent, M_DEVBUF);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mtx_unlock(&sndstat_lock);
|
sx_xunlock(&sndstat_lock);
|
||||||
splx(s);
|
splx(s);
|
||||||
|
|
||||||
return ENXIO;
|
return ENXIO;
|
||||||
@ -275,19 +278,19 @@ sndstat_unregisterfile(char *str)
|
|||||||
struct sndstat_entry *ent;
|
struct sndstat_entry *ent;
|
||||||
|
|
||||||
s = spltty();
|
s = spltty();
|
||||||
mtx_lock(&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--;
|
||||||
mtx_unlock(&sndstat_lock);
|
sx_xunlock(&sndstat_lock);
|
||||||
splx(s);
|
splx(s);
|
||||||
free(ent, M_DEVBUF);
|
free(ent, M_DEVBUF);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mtx_unlock(&sndstat_lock);
|
sx_xunlock(&sndstat_lock);
|
||||||
splx(s);
|
splx(s);
|
||||||
|
|
||||||
return ENXIO;
|
return ENXIO;
|
||||||
@ -342,7 +345,7 @@ sndstat_prepare(struct sbuf *s)
|
|||||||
static int
|
static int
|
||||||
sndstat_init(void)
|
sndstat_init(void)
|
||||||
{
|
{
|
||||||
mtx_init(&sndstat_lock, "sndstat", NULL, MTX_DEF);
|
sx_init(&sndstat_lock, "sndstat");
|
||||||
sndstat_dev = make_dev(&sndstat_cdevsw, SND_DEV_STATUS, UID_ROOT, GID_WHEEL, 0444, "sndstat");
|
sndstat_dev = make_dev(&sndstat_cdevsw, SND_DEV_STATUS, UID_ROOT, GID_WHEEL, 0444, "sndstat");
|
||||||
|
|
||||||
return (sndstat_dev != 0)? 0 : ENXIO;
|
return (sndstat_dev != 0)? 0 : ENXIO;
|
||||||
@ -354,9 +357,9 @@ sndstat_uninit(void)
|
|||||||
intrmask_t s;
|
intrmask_t s;
|
||||||
|
|
||||||
s = spltty();
|
s = spltty();
|
||||||
mtx_lock(&sndstat_lock);
|
sx_xlock(&sndstat_lock);
|
||||||
if (sndstat_isopen) {
|
if (sndstat_isopen) {
|
||||||
mtx_unlock(&sndstat_lock);
|
sx_xunlock(&sndstat_lock);
|
||||||
splx(s);
|
splx(s);
|
||||||
return EBUSY;
|
return EBUSY;
|
||||||
}
|
}
|
||||||
@ -366,7 +369,7 @@ sndstat_uninit(void)
|
|||||||
sndstat_dev = 0;
|
sndstat_dev = 0;
|
||||||
|
|
||||||
splx(s);
|
splx(s);
|
||||||
mtx_destroy(&sndstat_lock);
|
sx_destroy(&sndstat_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user