[alsa-devel] PCM states and snd_pcm_drain()

Takashi Iwai tiwai at suse.de
Mon May 21 12:10:54 CEST 2012


At Sun, 20 May 2012 18:25:30 +0100,
Alan Horstmann wrote:
> 
> Hi,
> 
> Can snd_pcm_drain() be safely called on a non-running stream - particularly 
> one in SND_PCM_STATE_XRUN?  I can demonstrate lock-ups (on rather old Alsa 
> versions, though) when _drain is called on a stream in Xrun but it does seem 
> to vary between hardwares.

Hm, that's odd.  At least there should be no lock up in the core code.
Are you running the recent kernel?

> However, the docs at:
> 
> http://www.alsa-project.org/alsa-doc/alsa-lib/pcm.html
> 
> suggest that it should be fine.

The snd_pcm_drop() calls simply ignore streams other than RUNNING,
PREPARE and PAUSED.  So, it's basically safe.

OTOH, it'd be better to drop XRUN streams to SETUP after this call,
and there should be sane state checks at the beginning.
I committed the patch below to my tree now.


Takashi

---
From: Takashi Iwai <tiwai at suse.de>
Subject: [PATCH] ALSA: pcm - Add proper state checks to snd_pcm_drain()

The handling for some PCM states is missing for snd_pcm_drain().
At least, XRUN streams should be simply dropped to SETUP, and a few
initial invalid states should be rejected.

Signed-off-by: Takashi Iwai <tiwai at suse.de>
---
 sound/core/pcm_native.c |   12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 3fe99e6..53b5ada 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -1360,7 +1360,14 @@ static int snd_pcm_prepare(struct snd_pcm_substream *substream,
 
 static int snd_pcm_pre_drain_init(struct snd_pcm_substream *substream, int state)
 {
-	substream->runtime->trigger_master = substream;
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	switch (runtime->status->state) {
+	case SNDRV_PCM_STATE_OPEN:
+	case SNDRV_PCM_STATE_DISCONNECTED:
+	case SNDRV_PCM_STATE_SUSPENDED:
+		return -EBADFD;
+	}
+	runtime->trigger_master = substream;
 	return 0;
 }
 
@@ -1379,6 +1386,9 @@ static int snd_pcm_do_drain_init(struct snd_pcm_substream *substream, int state)
 		case SNDRV_PCM_STATE_RUNNING:
 			runtime->status->state = SNDRV_PCM_STATE_DRAINING;
 			break;
+		case SNDRV_PCM_STATE_XRUN:
+			runtime->status->state = SNDRV_PCM_STATE_SETUP;
+			break;
 		default:
 			break;
 		}
-- 
1.7.9.2



More information about the Alsa-devel mailing list