[alsa-devel] Timer instability
mznyfn at 0pointer.de
Thu Feb 19 03:46:11 CET 2009
As you might now PulseAudio schedules audio by system timers, not by
sound card interrupts. Unfortunately there are are couple of issues
with the reliability of the timing/buffering information we get from
For example, on an ens1371 I have tracked down the following issue: I
use the full buffer that the sound card provides (64K, i.e. 371ms). I
sleep for about 350 ms, then fill up again, and sleep 350ms, and so
and so on. Everytime I wake up I check snd_pcm_avail() and write
exactly as much as this call tells me to. I also listen to POLLOUT
events on the fd, however I call snd_pcm_sw_params_set_period_event(,
0) for it to make sure I actually don't get any real events on that.
After a couple of minutes of running this loop I can reliably
reproduce that _avail() tells me I should fill the buffer up, I do so,
query it again and it shows the buffer is filled up. I then go to
sleep but immediately get POLLIN (although I shouldnt, given that I
called snd_pcm_sw_params_set_period_event()), wake up again, call
snd_pcm_avail() and according to it the buffer ran completely
empty. The poll() took less than 1 ms time, and the last thing I did
before going to sleep was checking that the buffer was full. So
certainly ALSA is lying to me here... The buffer couldn't have run
empty in less than 1 ms!
The same with real numbers as one example:
1. ... we are woken up
2. _avail() returns 15496 samples (i.e. 350ms to fill up)
3. we gather and write 15496 samples
4. _avail() returns 48 samples, which we consider "filled up enough" to go to sleep
5. we call poll()
6. after < 1ms we are woken up by a POLLIN (which we actually thought we had explicitly disabled)
7. _avail() returns 16448 samples (i.e. 372ms to fill up -- larger than the actual buffer of 16384 samples!)
This smells a lot like some kind of overflow to me, given that in every
case where I could reproduce this it was possible to 'fix' the issue
by substracting the buffer size from the _avail() after the
poll(). After that substraction the value started to make sense
again. (i.e. in the example above it then becomes 64 samples, which is
reasonable after sleep less than 1ms I guess).
The stop threshold is set to the boundary here btw.
If necessary I could extract a test case for this, but my hope that
you guys might have an idea what goes on without a test case, given
that this smells so "overflowy" ;-)
And of course, how come ALSA triggers POLLIN if I asked it not to?
This is alsa-libs 1.0.19 on a 2.6.27 kernel.
Lennart Poettering Red Hat, Inc.
lennart [at] poettering [dot] net ICQ# 11060553
http://0pointer.net/lennart/ GnuPG 0x1A015CC4
More information about the Alsa-devel