From 932b912ae28a5bfd99565c98c1d2a0799b69c4bb Mon Sep 17 00:00:00 2001 From: truckman Date: Fri, 10 Sep 2004 09:37:06 +0000 Subject: 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 --- sys/dev/sound/pcm/sndstat.c | 55 ++++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/sys/dev/sound/pcm/sndstat.c b/sys/dev/sound/pcm/sndstat.c index 0b391a7..c8e6387 100644 --- a/sys/dev/sound/pcm/sndstat.c +++ b/sys/dev/sound/pcm/sndstat.c @@ -26,6 +26,9 @@ #include #include +#ifdef USING_MUTEX +#include +#endif SND_DECLARE_FILE("$FreeBSD$"); @@ -59,7 +62,7 @@ struct sndstat_entry { }; #ifdef USING_MUTEX -static struct mtx sndstat_lock; +static struct sx sndstat_lock; #endif static struct sbuf sndstat_sbuf; 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); if (error == 0 && req->newptr != NULL) { s = spltty(); - mtx_lock(&sndstat_lock); + sx_xlock(&sndstat_lock); if (verbose < 0 || verbose > 3) error = EINVAL; else sndstat_verbose = verbose; - mtx_unlock(&sndstat_lock); + sx_xunlock(&sndstat_lock); splx(s); } return error; @@ -109,14 +112,14 @@ sndstat_open(struct cdev *i_dev, int flags, int mode, struct thread *td) int error; s = spltty(); - mtx_lock(&sndstat_lock); + sx_xlock(&sndstat_lock); if (sndstat_isopen) { - mtx_unlock(&sndstat_lock); + sx_xunlock(&sndstat_lock); splx(s); return EBUSY; } sndstat_isopen = 1; - mtx_unlock(&sndstat_lock); + sx_xunlock(&sndstat_lock); splx(s); if (sbuf_new(&sndstat_sbuf, NULL, 4096, 0) == NULL) { error = ENXIO; @@ -127,9 +130,9 @@ sndstat_open(struct cdev *i_dev, int flags, int mode, struct thread *td) out: if (error) { s = spltty(); - mtx_lock(&sndstat_lock); + sx_xlock(&sndstat_lock); sndstat_isopen = 0; - mtx_unlock(&sndstat_lock); + sx_xunlock(&sndstat_lock); splx(s); } return (error); @@ -141,16 +144,16 @@ sndstat_close(struct cdev *i_dev, int flags, int mode, struct thread *td) intrmask_t s; s = spltty(); - mtx_lock(&sndstat_lock); + sx_xlock(&sndstat_lock); if (!sndstat_isopen) { - mtx_unlock(&sndstat_lock); + sx_xunlock(&sndstat_lock); splx(s); return EBADF; } sbuf_delete(&sndstat_sbuf); sndstat_isopen = 0; - mtx_unlock(&sndstat_lock); + sx_xunlock(&sndstat_lock); splx(s); return 0; } @@ -162,9 +165,9 @@ sndstat_read(struct cdev *i_dev, struct uio *buf, int flag) int l, err; s = spltty(); - mtx_lock(&sndstat_lock); + sx_xlock(&sndstat_lock); if (!sndstat_isopen) { - mtx_unlock(&sndstat_lock); + sx_xunlock(&sndstat_lock); splx(s); 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; sndstat_bufptr += l; - mtx_unlock(&sndstat_lock); + sx_xunlock(&sndstat_lock); splx(s); return err; } @@ -227,12 +230,12 @@ sndstat_register(device_t dev, char *str, sndstat_handler handler) ent->handler = handler; s = spltty(); - mtx_lock(&sndstat_lock); + 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; - mtx_unlock(&sndstat_lock); + sx_xunlock(&sndstat_lock); splx(s); return 0; @@ -251,18 +254,18 @@ sndstat_unregister(device_t dev) struct sndstat_entry *ent; s = spltty(); - mtx_lock(&sndstat_lock); + sx_xlock(&sndstat_lock); SLIST_FOREACH(ent, &sndstat_devlist, link) { if (ent->dev == dev) { SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link); - mtx_unlock(&sndstat_lock); + sx_xunlock(&sndstat_lock); splx(s); free(ent, M_DEVBUF); return 0; } } - mtx_unlock(&sndstat_lock); + sx_xunlock(&sndstat_lock); splx(s); return ENXIO; @@ -275,19 +278,19 @@ sndstat_unregisterfile(char *str) struct sndstat_entry *ent; s = spltty(); - mtx_lock(&sndstat_lock); + 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--; - mtx_unlock(&sndstat_lock); + sx_xunlock(&sndstat_lock); splx(s); free(ent, M_DEVBUF); return 0; } } - mtx_unlock(&sndstat_lock); + sx_xunlock(&sndstat_lock); splx(s); return ENXIO; @@ -342,7 +345,7 @@ sndstat_prepare(struct sbuf *s) static int 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"); return (sndstat_dev != 0)? 0 : ENXIO; @@ -354,9 +357,9 @@ sndstat_uninit(void) intrmask_t s; s = spltty(); - mtx_lock(&sndstat_lock); + sx_xlock(&sndstat_lock); if (sndstat_isopen) { - mtx_unlock(&sndstat_lock); + sx_xunlock(&sndstat_lock); splx(s); return EBUSY; } @@ -366,7 +369,7 @@ sndstat_uninit(void) sndstat_dev = 0; splx(s); - mtx_destroy(&sndstat_lock); + sx_destroy(&sndstat_lock); return 0; } -- cgit v1.1