Index: sndstat.c =================================================================== RCS file: /home/ncvs/src/sys/dev/sound/pcm/sndstat.c,v retrieving revision 1.14 diff -u -r1.14 sndstat.c --- sndstat.c 7 Sep 2003 16:28:03 -0000 1.14 +++ sndstat.c 27 Nov 2003 18:21:06 -0000 @@ -56,44 +56,41 @@ int type, unit; }; -#ifdef USING_MUTEX -static struct mtx sndstat_lock; -#endif -static struct sbuf sndstat_sbuf; static dev_t sndstat_dev = 0; static int sndstat_isopen = 0; -static int sndstat_bufptr; + +struct sndstat { + void *rawbuf; + struct sbuf sbuf; + int bufptr; + int isopen; +}; + +static struct mtx sndstat_lock; static int sndstat_maxunit = -1; static int sndstat_files = 0; static SLIST_HEAD(, sndstat_entry) sndstat_devlist = SLIST_HEAD_INITIALIZER(none); static int sndstat_verbose = 1; -#ifdef USING_MUTEX TUNABLE_INT("hw.snd.verbose", &sndstat_verbose); -#else -TUNABLE_INT_DECL("hw.snd.verbose", 1, sndstat_verbose); -#endif 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(); mtx_lock(&sndstat_lock); if (verbose < 0 || verbose > 3) error = EINVAL; else sndstat_verbose = verbose; mtx_unlock(&sndstat_lock); - splx(s); } return error; } @@ -103,32 +100,26 @@ static int sndstat_open(dev_t i_dev, int flags, int mode, struct thread *td) { - intrmask_t s; + struct sndstat *s = i_dev->si_drv1; int error; - s = spltty(); + if (s == NULL) + return ENXIO; + mtx_lock(&sndstat_lock); if (sndstat_isopen) { mtx_unlock(&sndstat_lock); - splx(s); return EBUSY; } - sndstat_isopen = 1; + sndstat_isopen = s->isopen = 1; mtx_unlock(&sndstat_lock); - splx(s); - if (sbuf_new(&sndstat_sbuf, NULL, 4096, 0) == NULL) { - error = ENXIO; - goto out; - } - sndstat_bufptr = 0; - error = (sndstat_prepare(&sndstat_sbuf) > 0) ? 0 : ENOMEM; -out: + sbuf_clear(&s->sbuf); + s->bufptr = 0; + error = (sndstat_prepare(&s->sbuf) > 0) ? 0 : ENOMEM; if (error) { - s = spltty(); mtx_lock(&sndstat_lock); - sndstat_isopen = 0; + sndstat_isopen = s->isopen = 0; mtx_unlock(&sndstat_lock); - splx(s); } return (error); } @@ -136,42 +127,40 @@ static int sndstat_close(dev_t i_dev, int flags, int mode, struct thread *td) { - intrmask_t s; + struct sndstat *s = i_dev->si_drv1; + if (s == NULL) + return ENXIO; - s = spltty(); mtx_lock(&sndstat_lock); if (!sndstat_isopen) { mtx_unlock(&sndstat_lock); - splx(s); return EBADF; } - sbuf_delete(&sndstat_sbuf); - sndstat_isopen = 0; + sndstat_isopen = s->isopen = 0; mtx_unlock(&sndstat_lock); - splx(s); return 0; } static int sndstat_read(dev_t i_dev, struct uio *buf, int flag) { - intrmask_t s; + struct sndstat *s = i_dev->si_drv1; int l, err; - s = spltty(); + if (s == NULL) + return ENXIO; + mtx_lock(&sndstat_lock); if (!sndstat_isopen) { mtx_unlock(&sndstat_lock); - splx(s); return EBADF; } - l = min(buf->uio_resid, sbuf_len(&sndstat_sbuf) - sndstat_bufptr); - err = (l > 0)? uiomove(sbuf_data(&sndstat_sbuf) + sndstat_bufptr, l, buf) : 0; - sndstat_bufptr += l; + l = min(buf->uio_resid, sbuf_len(&s->sbuf) - s->bufptr); + err = (l > 0)? uiomove(sbuf_data(&s->sbuf) + s->bufptr, l, buf) : 0; + s->bufptr += l; mtx_unlock(&sndstat_lock); - splx(s); return err; } @@ -193,7 +182,6 @@ int sndstat_register(device_t dev, char *str, sndstat_handler handler) { - intrmask_t s; struct sndstat_entry *ent; const char *devtype; int type, unit; @@ -214,7 +202,7 @@ unit = -1; } - ent = malloc(sizeof *ent, M_DEVBUF, M_ZERO | M_WAITOK); + ent = malloc(sizeof *ent, M_DEVBUF, M_ZERO | M_NOWAIT); if (!ent) return ENOSPC; @@ -224,14 +212,12 @@ ent->unit = unit; ent->handler = handler; - s = spltty(); mtx_lock(&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); - splx(s); return 0; } @@ -245,23 +231,19 @@ int sndstat_unregister(device_t dev) { - intrmask_t s; struct sndstat_entry *ent; - s = spltty(); mtx_lock(&sndstat_lock); SLIST_FOREACH(ent, &sndstat_devlist, link) { if (ent->dev == dev) { SLIST_REMOVE(&sndstat_devlist, ent, sndstat_entry, link); mtx_unlock(&sndstat_lock); - splx(s); free(ent, M_DEVBUF); return 0; } } mtx_unlock(&sndstat_lock); - splx(s); return ENXIO; } @@ -269,24 +251,20 @@ int sndstat_unregisterfile(char *str) { - intrmask_t s; struct sndstat_entry *ent; - s = spltty(); mtx_lock(&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); - splx(s); free(ent, M_DEVBUF); return 0; } } mtx_unlock(&sndstat_lock); - splx(s); return ENXIO; } @@ -338,32 +316,83 @@ } static int -sndstat_init(void) -{ +sndstat_init(void) { + struct sndstat *s; + int ret; + mtx_init(&sndstat_lock, "sndstat", NULL, 0); - sndstat_dev = make_dev(&sndstat_cdevsw, SND_DEV_STATUS, UID_ROOT, GID_WHEEL, 0444, "sndstat"); - return (sndstat_dev != 0)? 0 : ENXIO; + /* + * Except for sndstat_lock, this is a generic device creation + * suitable for multiple devices. I don't know why you would + * want that though. + */ + ret = ENOMEM; + + + s = malloc(sizeof(s), M_DEVBUF, M_ZERO|M_NOWAIT); + if (s == NULL) + goto err; + + s->rawbuf = malloc(4096, M_TEMP, M_NOWAIT); + if (s->rawbuf == NULL) + goto err; + + sbuf_new(&s->sbuf, s->rawbuf, 4096, SBUF_FIXEDLEN); + + sndstat_dev = make_dev(&sndstat_cdevsw, SND_DEV_STATUS, UID_ROOT, GID_WHEEL, 0444, "sndstat"); + if (sndstat_dev == NULL) { + return ENXIO; + goto err; + } + sndstat_dev->si_drv1 = s; + + /* + * Device created OK + */ + ret = 0; + goto ok; + +err: if (s != NULL) { + if (s->rawbuf != NULL) { + free(s->rawbuf, M_TEMP); + sbuf_delete(&s->sbuf); + } + free(s, M_DEVBUF); + } +ok: + return ret; } static int -sndstat_uninit(void) -{ - intrmask_t s; +sndstat_uninit(void) { + + struct sndstat *s = sndstat_dev->si_drv1; + + if (s == NULL) + return ENXIO; + + /* + * XXX: I'm puzzled at what the correct behaviour should be since + * uninit might fail, do we destroy the lock anyway? Since init/unit + * is called from SYSINIT the return value is ignored and we can't + * veto. We aren't allowed to fail. + * Use old semantics until this is figured out. + */ - s = spltty(); mtx_lock(&sndstat_lock); if (sndstat_isopen) { mtx_unlock(&sndstat_lock); - splx(s); return EBUSY; } - if (sndstat_dev) - destroy_dev(sndstat_dev); + sbuf_delete(&s->sbuf); + free(s->rawbuf, M_TEMP); + free(s, M_DEVBUF); + + destroy_dev(sndstat_dev); sndstat_dev = 0; - splx(s); mtx_destroy(&sndstat_lock); return 0; }