Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F102955890
D44923.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
2 KB
Referenced Files
None
Subscribers
None
D44923.diff
View Options
diff --git a/sys/dev/sound/pcm/channel.h b/sys/dev/sound/pcm/channel.h
--- a/sys/dev/sound/pcm/channel.h
+++ b/sys/dev/sound/pcm/channel.h
@@ -264,6 +264,7 @@
int chn_init(struct pcm_channel *c, void *devinfo, int dir, int direction);
int chn_kill(struct pcm_channel *c);
+void chn_shutdown(struct pcm_channel *c);
int chn_reset(struct pcm_channel *c, u_int32_t fmt, u_int32_t spd);
int chn_setvolume_multi(struct pcm_channel *c, int vc, int left, int right,
int center);
diff --git a/sys/dev/sound/pcm/channel.c b/sys/dev/sound/pcm/channel.c
--- a/sys/dev/sound/pcm/channel.c
+++ b/sys/dev/sound/pcm/channel.c
@@ -1301,6 +1301,15 @@
return (0);
}
+void
+chn_shutdown(struct pcm_channel *c)
+{
+ CHN_LOCKASSERT(c);
+
+ chn_wakeup(c);
+ c->flags |= CHN_F_DEAD;
+}
+
int
chn_setvolume_multi(struct pcm_channel *c, int vc, int left, int right,
int center)
diff --git a/sys/dev/sound/pcm/sound.c b/sys/dev/sound/pcm/sound.c
--- a/sys/dev/sound/pcm/sound.c
+++ b/sys/dev/sound/pcm/sound.c
@@ -674,23 +674,50 @@
return (err);
}
-static int
-pcm_killchan(device_t dev)
+static void
+pcm_killchans(struct snddev_info *d)
{
- struct snddev_info *d = device_get_softc(dev);
struct pcm_channel *ch;
int error;
+ bool found;
PCM_BUSYASSERT(d);
+ do {
+ found = false;
+ CHN_FOREACH(ch, d, channels.pcm) {
+ CHN_LOCK(ch);
+ /*
+ * Make sure no channel has went to sleep in the
+ * meantime.
+ */
+ chn_shutdown(ch);
+ /*
+ * We have to give a thread sleeping in chn_sleep() a
+ * chance to observe that the channel is dead.
+ */
+ if ((ch->flags & CHN_F_SLEEPING) == 0) {
+ found = true;
+ CHN_UNLOCK(ch);
+ break;
+ }
+ CHN_UNLOCK(ch);
+ }
- ch = CHN_FIRST(d, channels.pcm);
+ /*
+ * All channels are still sleeping. Sleep for a bit and try
+ * again to see if any of them is awake now.
+ */
+ if (!found) {
+ pause_sbt("pcmkillchans", SBT_1MS * 5, 0, 0);
+ continue;
+ }
- PCM_LOCK(d);
- error = pcm_chn_remove(d, ch);
- PCM_UNLOCK(d);
- if (error)
- return (error);
- return (pcm_chn_destroy(ch));
+ PCM_LOCK(d);
+ error = pcm_chn_remove(d, ch);
+ PCM_UNLOCK(d);
+ if (error == 0)
+ pcm_chn_destroy(ch);
+ } while (!CHN_EMPTY(d, channels.pcm));
}
static int
@@ -1000,15 +1027,11 @@
CHN_FOREACH(ch, d, channels.pcm) {
CHN_LOCK(ch);
- if (ch->flags & CHN_F_SLEEPING) {
- /*
- * We are detaching, so do not wait for the timeout in
- * chn_read()/chn_write(). Wake up the thread and kill
- * the channel immediately.
- */
- CHN_BROADCAST(&ch->intr_cv);
- ch->flags |= CHN_F_DEAD;
- }
+ /*
+ * Do not wait for the timeout in chn_read()/chn_write(). Wake
+ * up the sleeping thread and kill the channel.
+ */
+ chn_shutdown(ch);
chn_abort(ch);
CHN_UNLOCK(ch);
}
@@ -1033,8 +1056,7 @@
dsp_destroy_dev(dev);
(void)mixer_uninit(dev);
- while (!CHN_EMPTY(d, channels.pcm))
- pcm_killchan(dev);
+ pcm_killchans(d);
PCM_LOCK(d);
PCM_RELEASE(d);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Wed, Nov 20, 4:20 AM (21 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
14730121
Default Alt Text
D44923.diff (2 KB)
Attached To
Mode
D44923: sound: Fix panic caused by sleeping-channel destruction during asynchronous detach
Attached
Detach File
Event Timeline
Log In to Comment