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);