
On Thu, May 10, 2012 at 12:06 PM, Russell King - ARM Linux linux@arm.linux.org.uk wrote:
The question is - what would cause ALSA to hammer away at the buffer like that - checking it every 16 or 8 DMA bytes transferred? I'm also seeing around 75% system CPU time, which really isn't good.
The above was captured while aplay was running, with no apparant audio corruption.
I've had this happen, but not with aplay. I sent something to the list a few months ago about it.
The problem is triggered when writing to ALSA with writes that are unequal to the period size and using sampling rate conversion in an ALSA plugin. Code in alsa-lib will get into a loop calling poll() on the pcm fd, and ALSA's poll() calls the pointer method to figure out if there is enough buffer space free to return or if it poll() should block.
That is all fine, but rather than write more data when poll() returns, alsa-lib decides to call poll() again. So it's stuck in a tight loop calling poll() which isn't blocking. Eventually there will be enough space in the buffer that alsa will write some data and poll() will block.
Basically poll() will return when there is at least X bytes available in the buffer. X = avail_min. ALSA will only write more data when there is at least Y bytes free in the buffer. The bug is X < Y. This only happens when sample rate conversion and only if the app doesn't call snd_pcm_writei() with full periods. While the available space in the buffer is > X and < Y, ALSA is in a tight loop calling poll() which calls the PCM's pointer method. If X == Y, then this would never happen.