diff options
author | Max Kellermann <max@musicpd.org> | 2018-11-08 14:29:04 +0100 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2018-11-11 12:37:29 +0100 |
commit | fee75dc766995d9946af03b40861f19412b5edd9 (patch) | |
tree | 242adc4b5e923f637cfc1df9ca3c38dd54094856 | |
parent | ba5c856f154fcfbbb6643e32e020c1c3bc2e8feb (diff) |
{output,mixer}/alsa: use snd_pcm_poll_descriptors_revents()
This call was missing, causing very high CPU usage when the ALSA
output plugin was used with dmix.
Closes #391
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | src/input/plugins/AlsaInputPlugin.cxx | 2 | ||||
-rw-r--r-- | src/lib/alsa/NonBlock.cxx | 48 | ||||
-rw-r--r-- | src/lib/alsa/NonBlock.hxx | 12 | ||||
-rw-r--r-- | src/mixer/plugins/AlsaMixerPlugin.cxx | 2 | ||||
-rw-r--r-- | src/output/plugins/AlsaOutputPlugin.cxx | 2 |
6 files changed, 67 insertions, 0 deletions
@@ -3,6 +3,7 @@ ver 0.21.2 (not yet released) - ffmpeg: require FFmpeg 3.1 or later - ffmpeg: fix broken sound with certain codecs * output + - alsa: fix high CPU usage with dmix - httpd: fix two crash bugs * mixer - alsa: fix more rounding errors diff --git a/src/input/plugins/AlsaInputPlugin.cxx b/src/input/plugins/AlsaInputPlugin.cxx index 801a16fd0..29578ebc8 100644 --- a/src/input/plugins/AlsaInputPlugin.cxx +++ b/src/input/plugins/AlsaInputPlugin.cxx @@ -185,6 +185,8 @@ AlsaInputStream::PrepareSockets() noexcept void AlsaInputStream::DispatchSockets() noexcept { + non_block.DispatchSockets(*this, capture_handle); + const std::lock_guard<Mutex> protect(mutex); auto w = PrepareWriteBuffer(); diff --git a/src/lib/alsa/NonBlock.cxx b/src/lib/alsa/NonBlock.cxx index 589def151..5b6667302 100644 --- a/src/lib/alsa/NonBlock.cxx +++ b/src/lib/alsa/NonBlock.cxx @@ -49,6 +49,30 @@ AlsaNonBlockPcm::PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm) return std::chrono::steady_clock::duration(-1); } +void +AlsaNonBlockPcm::DispatchSockets(MultiSocketMonitor &m, + snd_pcm_t *pcm) noexcept +{ + int count = snd_pcm_poll_descriptors_count(pcm); + if (count <= 0) + return; + + const auto pfds = pfd_buffer.Get(count), end = pfds + count; + + auto *i = pfds; + m.ForEachReturnedEvent([&i, end](SocketDescriptor s, unsigned events){ + if (i >= end) + return; + + i->fd = s.Get(); + i->events = i->revents = events; + ++i; + }); + + unsigned short dummy; + snd_pcm_poll_descriptors_revents(pcm, pfds, i - pfds, &dummy); +} + std::chrono::steady_clock::duration AlsaNonBlockMixer::PrepareSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noexcept { @@ -67,3 +91,27 @@ AlsaNonBlockMixer::PrepareSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noe m.ReplaceSocketList(pfds, count); return std::chrono::steady_clock::duration(-1); } + +void +AlsaNonBlockMixer::DispatchSockets(MultiSocketMonitor &m, + snd_mixer_t *mixer) noexcept +{ + int count = snd_mixer_poll_descriptors_count(mixer); + if (count <= 0) + return; + + const auto pfds = pfd_buffer.Get(count), end = pfds + count; + + auto *i = pfds; + m.ForEachReturnedEvent([&i, end](SocketDescriptor s, unsigned events){ + if (i >= end) + return; + + i->fd = s.Get(); + i->events = i->revents = events; + ++i; + }); + + unsigned short dummy; + snd_mixer_poll_descriptors_revents(mixer, pfds, i - pfds, &dummy); +} diff --git a/src/lib/alsa/NonBlock.hxx b/src/lib/alsa/NonBlock.hxx index 8d6e42458..8e9e2c7f2 100644 --- a/src/lib/alsa/NonBlock.hxx +++ b/src/lib/alsa/NonBlock.hxx @@ -42,6 +42,12 @@ public: */ std::chrono::steady_clock::duration PrepareSockets(MultiSocketMonitor &m, snd_pcm_t *pcm); + + /** + * Wrapper for snd_pcm_poll_descriptors_revents(), to be + * called from MultiSocketMonitor::DispatchSockets(). + */ + void DispatchSockets(MultiSocketMonitor &m, snd_pcm_t *pcm) noexcept; }; /** @@ -54,6 +60,12 @@ class AlsaNonBlockMixer { public: std::chrono::steady_clock::duration PrepareSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noexcept; + + /** + * Wrapper for snd_mixer_poll_descriptors_revents(), to be + * called from MultiSocketMonitor::DispatchSockets(). + */ + void DispatchSockets(MultiSocketMonitor &m, snd_mixer_t *mixer) noexcept; }; #endif diff --git a/src/mixer/plugins/AlsaMixerPlugin.cxx b/src/mixer/plugins/AlsaMixerPlugin.cxx index dbc74d941..f6f8bf290 100644 --- a/src/mixer/plugins/AlsaMixerPlugin.cxx +++ b/src/mixer/plugins/AlsaMixerPlugin.cxx @@ -117,6 +117,8 @@ AlsaMixerMonitor::DispatchSockets() noexcept { assert(mixer != nullptr); + non_block.DispatchSockets(*this, mixer); + int err = snd_mixer_handle_events(mixer); if (err < 0) { FormatError(alsa_mixer_domain, diff --git a/src/output/plugins/AlsaOutputPlugin.cxx b/src/output/plugins/AlsaOutputPlugin.cxx index 02b3dfe86..8d875ed26 100644 --- a/src/output/plugins/AlsaOutputPlugin.cxx +++ b/src/output/plugins/AlsaOutputPlugin.cxx @@ -889,6 +889,8 @@ AlsaOutput::PrepareSockets() noexcept void AlsaOutput::DispatchSockets() noexcept try { + non_block.DispatchSockets(*this, pcm); + { const std::lock_guard<Mutex> lock(mutex); |