From 32309225ba462289fc6b51c22e6929d90f764dfa Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sat, 8 Oct 2011 19:16:14 +0200 Subject: [PATCH] alsa: Avoid busy loop with dmix. When using alsa's direct mixing plugin, the alsa poll fd might be ready for IO even though nothing can be written to the alsa handle. This leads to a busy loop in para_audiod and para_write and makes these applications eat up considerable amounts of CPU time during playback. This patch fixes the problem by reading from the alsa fd after a failed write. It also adjusts the test for when to return early from alsa_post_select(). The old code was not wrong, however, since we should never reach the test if poll_fd is negative. --- alsa_write.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/alsa_write.c b/alsa_write.c index 047e88f2..b89c8c31 100644 --- a/alsa_write.c +++ b/alsa_write.c @@ -248,12 +248,23 @@ again: wn->min_iqs = pad->bytes_per_frame; goto again; } - if (pad->poll_fd >= 0 && !FD_ISSET(pad->poll_fd, &s->rfds)) + if (pad->poll_fd < 0 || !FD_ISSET(pad->poll_fd, &s->rfds)) return; frames = bytes / pad->bytes_per_frame; frames = snd_pcm_writei(pad->handle, data, frames); - if (frames == 0 || frames == -EAGAIN) + if (frames == 0 || frames == -EAGAIN) { + /* + * The alsa poll fd was ready for IO but we failed to write to + * the alsa handle. This means another event is pending. We + * don't care about that but we have to dispatch the event in + * order to avoid a busy loop. So we simply read from the poll + * fd. + */ + char buf[100]; + if (read(pad->poll_fd, buf, 100)) + do_nothing; return; + } if (frames > 0) { btr_consume(btrn, frames * pad->bytes_per_frame); goto again; -- 2.39.5