[alsa-devel] speaker-test stalls

Takashi Iwai tiwai at suse.de
Wed Dec 19 12:46:17 CET 2007


At Fri, 14 Dec 2007 12:40:04 -0500,
Dave Dillow wrote:
> 
> On Fri, Dec 14, 2007 at 04:39:37PM +0100, Takashi Iwai wrote:
> > At Sat, 08 Dec 2007 15:58:40 -0500,
> > Dave Dillow wrote:
> > > 
> > > While working with Fernando to get the sis7019 driver working in his
> > > buildroot setup, we kept running into a lockup of the PCM stream when
> > > using speaker-test. aplay was fine, as was other I finally tracked it
> > > down to a combination of uclibc not doing block reads, which led to
> > > XRUNs, and what I thought was issue in snd_pcm_lib_write1() when trying
> > > to fill up the tail of the PCM buffer with a large write, when there was
> > > an intervening small write.
> > > 
> > > As it turns out, the lockup problem may simply be in speaker-write's
> > > sw_params settings -- it calls snd_pcm_sw_params_set_avail_min() to set
> > > the minium write to the period size, and
> > > snd_pcm_sw_params_set_start_threshold() to start once the buffer has
> > > been filled. This doesn't account for odd wave file lengths and XRUNs.
> > > 
> > > The problem arises when the wave data is not a multiple of the period
> > > size, and you get an XRUN when there is less than buffer_size samples
> > > remaining in the current loop. 
> > 
> > Hm, it sounds weird.  Basically XRUN means that you have *no* data in
> > the buffer while the stream is running.  So, when you get XRUN, the
> > data must be empty, no matter which buffer or period size is.
> 
> Right, the buffer empties, and then the loop in speaker-test::write_buffer()
> starts filling the buffer again, as expected.
> 
> However, the sample data in the wave file is not a multiple of the buffer
> size, so it does a small write (ie, not period sized) to finish out the file,
> and the main routine calls back in to do the next loop.
> 
> So, you get a pattern (buffer_size is 32768):
> 
> write len	buffer available before write
> XRUN happens	N/A
> 8192		32768
> 8192		24576
> 5506		16384
> 8192		10878
> 8192		2686
> 
> Because speaker-test sets avail_min to 8192, and the start threshold to
> 32768, snd_pcm_lib_write1() will loop forever waiting for 8192 bytes to
> become available in the buffer. That will never happen, because the XRUN
> stopped the channel, and we cannot reach the start threshold, as this last
> write that would do it is the one that blocked.

OK, point taken.  It's a problem in the PCM core indeed.
The patch below should solve the problem, but it's ad hoc.


Takashi

diff -r 6f193b381db3 core/pcm_lib.c
--- a/core/pcm_lib.c	Wed Dec 19 12:13:44 2007 +0100
+++ b/core/pcm_lib.c	Wed Dec 19 14:36:04 2007 +0100
@@ -1655,8 +1655,11 @@ static snd_pcm_sframes_t snd_pcm_lib_wri
 		if (runtime->sleep_min == 0 && runtime->status->state == SNDRV_PCM_STATE_RUNNING)
 			snd_pcm_update_hw_ptr(substream);
 		avail = snd_pcm_playback_avail(runtime);
-		if (((avail < runtime->control->avail_min && size > avail) ||
-		   (size >= runtime->xfer_align && avail < runtime->xfer_align))) {
+		if (!avail ||
+		    (snd_pcm_running(substream) &&
+		     ((avail < runtime->control->avail_min && size > avail) ||
+		      (size >= runtime->xfer_align &&
+		       avail < runtime->xfer_align)))) {
 			wait_queue_t wait;
 			enum { READY, SIGNALED, ERROR, SUSPENDED, EXPIRED, DROPPED } state;
 			long tout;


More information about the Alsa-devel mailing list