PERFORCE change 100545 for review

Ryan Beasley ryanb at FreeBSD.org
Tue Jul 4 07:11:24 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=100545

Change 100545 by ryanb at ryanb_yuki on 2006/07/04 07:10:31

	In sound_oss_sysinfo and dsp_oss_audioinfo, add lock
	wrappers when iterating over PCM devices and audio channels.
	
	Fixed bug in dsp_oss_audioinfo where ai->dev was always set
	to 0, regardless of the real number of the channel probed.

Affected files ...

.. //depot/projects/soc2006/rbeasley_sound/sys/dev/sound/pcm/dsp.c#9 edit
.. //depot/projects/soc2006/rbeasley_sound/sys/dev/sound/pcm/sound.c#7 edit

Differences ...

==== //depot/projects/soc2006/rbeasley_sound/sys/dev/sound/pcm/dsp.c#9 (text+ko) ====

@@ -1315,6 +1315,9 @@
  * opened in read+write) and then assigns them to the si_drv[12] private
  * data fields.  As a result, any information returned linking a channel to
  * a specific character device isn't really accurate.
+ *
+ * @note
+ * Calling threads must not hold any snddev_info or pcm_channel locks.
  * 
  * @param dev		device on which the ioctl was issued
  * @param ai		ioctl request data container
@@ -1336,7 +1339,7 @@
 	struct pcm_channel *ch;
 	struct snddev_info *d;
 	struct cdev *t_cdev;
-	int i, nchan;
+	int i, nchan, ret;
 
 	/* If probing handling device, make sure it's a DSP device. */
 	if ((ai->dev == -1) && (i_dev->si_devsw != &dsp_cdevsw))
@@ -1345,15 +1348,20 @@
 	ch = NULL;
 	t_cdev = NULL;
 	nchan = 0;
-
+	ret = 0;
+	
 	/* Search for the requested audio device. */
 	for (i = 0; i < devclass_get_maxunit(pcm_devclass); i++) {
 		d = devclass_get_softc(pcm_devclass, i);
 		if (d == NULL)
 			continue;
 
+		pcm_inprog(d, 1);
+		pcm_lock(d);
+
 		SLIST_FOREACH(sce, &d->channels, link) {
 			ch = sce->channel;
+			CHN_LOCK(ch);
 			if (ai->dev == -1) {
 				if ((ch == i_dev->si_drv1) ||
 				    (ch == i_dev->si_drv2)) {
@@ -1364,12 +1372,32 @@
 				t_cdev = sce->dsp_devt;
 				goto dspfound;
 			}
+			CHN_UNLOCK(ch);
 			++nchan;
 		}
+
+		pcm_unlock(d);
+		pcm_inprog(d, -1);
 	}
+
+	/* Exhausted the search -- nothing is locked, so return. */
+	return EINVAL;
+
 dspfound:
-	if (t_cdev == NULL)
-		return EINVAL;
+	/* Should've found the device, but something isn't right */
+	if (t_cdev == NULL) {
+		ret = EINVAL;
+		goto out;
+	}
+
+	/*
+	 * At this point, the following synchronization stuff has happened:
+	 *   - a specific PCM device is locked and its "in progress
+	 *     operations" counter has been incremented, so be sure to unlock
+	 *     and decrement when exiting;
+	 *   - a specific audio channel has been locked, so be sure to unlock
+	 *     when exiting;
+	 */
 
 	caps = chn_getcaps(ch);
 
@@ -1379,6 +1407,7 @@
 	 */
 	bzero((void *)ai, sizeof(oss_audioinfo));
 
+	ai->dev = nchan;
 	strlcpy(ai->name, ch->name,  sizeof(ai->name));
 
 	if ((ch->flags & CHN_F_BUSY) == 0)
@@ -1450,6 +1479,11 @@
 	ai->min_rate = caps->minspeed;
 	ai->max_rate = caps->maxspeed;
 
-	return 0;
+out:
+	CHN_UNLOCK(ch);
+	pcm_unlock(d);
+	pcm_inprog(d, -1);
+
+	return ret;
 }
 #endif	/* !OSSV4_EXPERIMENT */

==== //depot/projects/soc2006/rbeasley_sound/sys/dev/sound/pcm/sound.c#7 (text+ko) ====

@@ -1132,6 +1132,9 @@
  * Also includes a bitmask showing which of the above types of devices
  * are open (busy).
  *
+ * @note
+ * Calling threads must not hold any snddev_info or pcm_channel locks.
+ *
  * @author	Ryan Beasley <ryanb at FreeBSD.org>
  */
 void
@@ -1167,6 +1170,11 @@
 			d = devclass_get_softc(pcm_devclass, i);
 			if (!d)
 				continue;
+
+			/* Increment device's "operations in progress" */
+			pcm_inprog(d, 1);
+			pcm_lock(d);
+
 			si->numaudios += d->devcount;
 			++ncards;
 
@@ -1179,6 +1187,9 @@
 				CHN_UNLOCK(c);
 				j++;
 			}
+
+			pcm_unlock(d);
+			pcm_inprog(d, -1);
 		}
 	}
 


More information about the p4-projects mailing list