Mercurial > illumos > illumos-gate
changeset 10570:c21442694040
6881646 crash during mplayer/sun video
author | Garrett D'Amore <gdamore@opensolaris.org> |
---|---|
date | Wed, 16 Sep 2009 22:11:59 -0700 |
parents | 4d3eb0bc0c83 |
children | 6d0b902a4da8 |
files | usr/src/uts/common/io/audio/impl/audio_client.c usr/src/uts/common/io/audio/impl/audio_ctrl.c usr/src/uts/common/io/audio/impl/audio_ddi.c usr/src/uts/common/io/audio/impl/audio_engine.c usr/src/uts/common/io/audio/impl/audio_impl.h |
diffstat | 5 files changed, 83 insertions(+), 61 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/io/audio/impl/audio_client.c Mon Sep 14 21:48:21 2009 -0700 +++ b/usr/src/uts/common/io/audio/impl/audio_client.c Wed Sep 16 22:11:59 2009 -0700 @@ -58,7 +58,7 @@ * */ -const uint16_t auimpl_db_table[AUDIO_DB_SIZE + 1] = { +static const uint16_t auimpl_db_table[AUDIO_DB_SIZE + 1] = { 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, @@ -67,6 +67,10 @@ 256 }; +static list_t auimpl_clients; +static krwlock_t auimpl_client_lock; +static audio_client_ops_t *audio_client_ops[AUDIO_MN_TYPE_MASK + 1]; + void * auclnt_get_private(audio_client_t *c) { @@ -641,7 +645,8 @@ return (sp->s_user_parms->p_nchan); } -void + +static void auimpl_set_gain_master(audio_stream_t *sp, uint8_t gain) { uint32_t scaled; @@ -675,6 +680,38 @@ */ } +int +auimpl_set_pcmvol(void *arg, uint64_t val) +{ + audio_dev_t *d = arg; + list_t *l = &d->d_clients; + audio_client_t *c; + + if (val > 100) { + return (EINVAL); + } + rw_enter(&auimpl_client_lock, RW_WRITER); + d->d_pcmvol = val & 0xff; + rw_downgrade(&auimpl_client_lock); + + for (c = list_head(l); c; c = list_next(l, c)) { + /* don't need to check is_active here, its safe */ + auimpl_set_gain_master(&c->c_ostream, (uint8_t)val); + } + rw_exit(&auimpl_client_lock); + + return (0); +} + +int +auimpl_get_pcmvol(void *arg, uint64_t *val) +{ + audio_dev_t *d = arg; + + *val = d->d_pcmvol; + return (0); +} + void auclnt_set_gain(audio_stream_t *sp, uint8_t gain) { @@ -842,10 +879,6 @@ * implementations, but are for private framework use only. */ -static list_t auimpl_clients; -static krwlock_t auimpl_client_lock; -static audio_client_ops_t *audio_client_ops[AUDIO_MN_TYPE_MASK + 1]; - void auimpl_client_init(void) { @@ -1157,6 +1190,22 @@ } void +auimpl_client_activate(audio_client_t *c) +{ + rw_enter(&auimpl_client_lock, RW_WRITER); + c->c_is_active = B_TRUE; + rw_exit(&auimpl_client_lock); +} + +void +auimpl_client_deactivate(audio_client_t *c) +{ + rw_enter(&auimpl_client_lock, RW_WRITER); + c->c_is_active = B_FALSE; + rw_exit(&auimpl_client_lock); +} + +void auclnt_close(audio_client_t *c) { audio_dev_t *d = c->c_dev; @@ -1165,9 +1214,9 @@ auclnt_stop(&c->c_istream); auclnt_stop(&c->c_ostream); - rw_enter(&d->d_clnt_lock, RW_WRITER); + rw_enter(&auimpl_client_lock, RW_WRITER); list_remove(&d->d_clients, c); - rw_exit(&d->d_clnt_lock); + rw_exit(&auimpl_client_lock); mutex_enter(&c->c_lock); /* if in transition need to wait for other thread to release */ @@ -1212,7 +1261,7 @@ for (c = list_head(list); c != NULL; c = list_next(list, c)) { if ((c->c_major == mj) && (c->c_minor == mn)) { mutex_enter(&c->c_lock); - if (c->c_is_open) { + if (c->c_is_active) { c->c_refcnt++; mutex_exit(&c->c_lock); } else { @@ -1246,9 +1295,11 @@ audio_client_t *c; int rv; - rw_enter(&d->d_clnt_lock, RW_READER); + rw_enter(&auimpl_client_lock, RW_READER); restart: for (c = list_head(l); c != NULL; c = list_next(l, c)) { + if (!c->c_is_active) + continue; rv = (walker(c, arg)); if (rv == AUDIO_WALK_STOP) { break; @@ -1256,7 +1307,7 @@ goto restart; } } - rw_exit(&d->d_clnt_lock); + rw_exit(&auimpl_client_lock); } @@ -1317,11 +1368,11 @@ auimpl_engine_close(&c->c_ostream); auimpl_engine_close(&c->c_istream); } else { - rw_enter(&d->d_clnt_lock, RW_WRITER); + rw_enter(&auimpl_client_lock, RW_WRITER); list_insert_tail(&d->d_clients, c); c->c_ostream.s_gain_master = d->d_pcmvol; c->c_istream.s_gain_master = 100; - rw_exit(&d->d_clnt_lock); + rw_exit(&auimpl_client_lock); auclnt_set_gain(&c->c_ostream, 100); auclnt_set_gain(&c->c_istream, 100); } @@ -1465,14 +1516,16 @@ list_t *l = &dev->d_clients; audio_client_t *c; - rw_enter(&dev->d_clnt_lock, RW_READER); + rw_enter(&auimpl_client_lock, RW_READER); for (c = list_head(l); c != NULL; c = list_next(l, c)) { + if (!c->c_is_active) + continue; mutex_enter(&c->c_lock); c->c_do_notify = B_TRUE; cv_broadcast(&c->c_cv); mutex_exit(&c->c_lock); } - rw_exit(&dev->d_clnt_lock); + rw_exit(&auimpl_client_lock); } uint64_t
--- a/usr/src/uts/common/io/audio/impl/audio_ctrl.c Mon Sep 14 21:48:21 2009 -0700 +++ b/usr/src/uts/common/io/audio/impl/audio_ctrl.c Wed Sep 16 22:11:59 2009 -0700 @@ -239,34 +239,6 @@ kmem_free(ctrl, sizeof (*ctrl)); } -static int -auimpl_set_pcmvol(void *arg, uint64_t val) -{ - audio_dev_t *d = arg; - list_t *l = &d->d_clients; - audio_client_t *c; - - if (val > 100) { - return (EINVAL); - } - rw_enter(&d->d_clnt_lock, RW_WRITER); - d->d_pcmvol = val & 0xff; - for (c = list_head(l); c; c = list_next(l, c)) { - auimpl_set_gain_master(&c->c_ostream, (uint8_t)val); - } - rw_exit(&d->d_clnt_lock); - return (0); -} - -static int -auimpl_get_pcmvol(void *arg, uint64_t *val) -{ - audio_dev_t *d = arg; - - *val = d->d_pcmvol; - return (0); -} - int audio_dev_add_soft_volume(audio_dev_t *d) {
--- a/usr/src/uts/common/io/audio/impl/audio_ddi.c Mon Sep 14 21:48:21 2009 -0700 +++ b/usr/src/uts/common/io/audio/impl/audio_ddi.c Wed Sep 16 22:11:59 2009 -0700 @@ -180,9 +180,8 @@ /* we do device cloning! */ *devp = makedevice(c->c_major, c->c_minor); - mutex_enter(&c->c_lock); - c->c_is_open = B_TRUE; - mutex_exit(&c->c_lock); + /* now we can receive upcalls */ + auimpl_client_activate(c); auclnt_notify_dev(c->c_dev); @@ -240,14 +239,13 @@ /* we do device cloning! */ *devp = makedevice(c->c_major, c->c_minor); - mutex_enter(&c->c_lock); - c->c_is_open = B_TRUE; - mutex_exit(&c->c_lock); + qprocson(rq); + + /* now we can receive upcalls */ + auimpl_client_activate(c); auclnt_notify_dev(c->c_dev); - qprocson(rq); - return (0); } @@ -268,9 +266,8 @@ rv = auclnt_drain(c); } - mutex_enter(&c->c_lock); - c->c_is_open = B_FALSE; - mutex_exit(&c->c_lock); + /* make sure we won't get any upcalls */ + auimpl_client_deactivate(c); /* * Pick up any data sitting around in input buffers. This @@ -316,9 +313,8 @@ return (ENXIO); } - mutex_enter(&c->c_lock); - c->c_is_open = B_FALSE; - mutex_exit(&c->c_lock); + /* we don't want any upcalls anymore */ + auimpl_client_deactivate(c); /* * Pick up any data sitting around in input buffers. This
--- a/usr/src/uts/common/io/audio/impl/audio_engine.c Mon Sep 14 21:48:21 2009 -0700 +++ b/usr/src/uts/common/io/audio/impl/audio_engine.c Wed Sep 16 22:11:59 2009 -0700 @@ -75,7 +75,6 @@ mutex_init(&d->d_lock, NULL, MUTEX_DRIVER, NULL); cv_init(&d->d_cv, NULL, CV_DRIVER, NULL); rw_init(&d->d_ctrl_lock, NULL, RW_DRIVER, NULL); - rw_init(&d->d_clnt_lock, NULL, RW_DRIVER, NULL); list_create(&d->d_clients, sizeof (struct audio_client), offsetof(struct audio_client, c_dev_linkage)); list_create(&d->d_engines, sizeof (struct audio_engine), @@ -107,7 +106,6 @@ rw_destroy(&d->d_ctrl_lock); mutex_destroy(&d->d_lock); cv_destroy(&d->d_cv); - rw_destroy(&d->d_clnt_lock); kmem_free(d, sizeof (*d)); }
--- a/usr/src/uts/common/io/audio/impl/audio_impl.h Mon Sep 14 21:48:21 2009 -0700 +++ b/usr/src/uts/common/io/audio/impl/audio_impl.h Wed Sep 16 22:11:59 2009 -0700 @@ -189,7 +189,7 @@ boolean_t c_do_notify; boolean_t c_do_drain; boolean_t c_closing; - boolean_t c_is_open; + boolean_t c_is_active; /* * Client wide settings... e.g. ops vector, etc. @@ -442,9 +442,12 @@ void auimpl_client_fini(void); audio_client_t *auimpl_client_create(dev_t); void auimpl_client_destroy(audio_client_t *); +void auimpl_client_activate(audio_client_t *); +void auimpl_client_deactivate(audio_client_t *); int auimpl_create_minors(audio_dev_t *); void auimpl_remove_minors(audio_dev_t *); -void auimpl_set_gain_master(audio_stream_t *, uint8_t); +int auimpl_set_pcmvol(void *, uint64_t); +int auimpl_get_pcmvol(void *, uint64_t *); /* audio_engine.c */ void auimpl_dev_init(void);