[alsa-devel] [PATCH] jack: use eventfd which never blocks.
Alexander E. Patrakov
patrakov at gmail.com
Sun Nov 21 11:15:40 CET 2010
19.11.2010 19:22, Torben Hohn wrote:
> the use of the socketpair for synchronisation is not correct.
> jack does not allow blocking calls in the process_callback,
> the socket buffers are quite small, and seem to overflow under some
> conditions.
Some remarks.
First, your patch preserves the incorrect code for the case when eventfd
is not available. While this is not a regression, I think you can do
better (possibly in a separate patch).
Second, I disagree that socketpair()-based synchronization cannot be
made correct and thus that eventfd is needed for correctness. It might
be needed for efficiency, though.
> the result was write(2) blocking, and jack kicking the client.
So why not just make the file descriptor non-blocking? This way, instead
of blocking the write(2), the socket pair would lose data when it gets
too many writes. No problem - the reader will still see its file
descriptor as active, eat a byte from the socket in
snd_pcm_jack_poll_revents() and presumably do something to fill the
audio buffer.
> (jack needs to be running in RT mode, with a pretty low period size (<=128)
> but this really is the normal usecase)
>
> this patch uses eventfd(2) when its available to mitigate the problem.
>
> Signed-off-by: Torben Hohn<torbenh at gmx.de>
> ---
> configure.in | 5 +++++
> jack/pcm_jack.c | 30 +++++++++++++++++++++++++++---
> 2 files changed, 32 insertions(+), 3 deletions(-)
>
> diff --git a/configure.in b/configure.in
> index 5d71cae..9fa7f27 100644
> --- a/configure.in
> +++ b/configure.in
> @@ -21,6 +21,11 @@ AC_CHECK_LIB(asound, snd_pcm_ioplug_create,,
> AC_ARG_ENABLE([jack],
> AS_HELP_STRING([--disable-jack], [Disable building of JACK plugin]))
>
> +AC_CHECK_HEADER([sys/eventfd.h], [HAVE_EVENTFD=yes], [HAVE_EVENTFD=no])
> +if test "$HAVE_EVENTFD" = "yes"; then
> + AC_DEFINE(HAVE_EVENTFD, 1,"eventfd is available")
> +fi
> +
> if test "x$enable_jack" != "xno"; then
> PKG_CHECK_MODULES(JACK, jack>= 0.98, [HAVE_JACK=yes], [HAVE_JACK=no])
> fi
> diff --git a/jack/pcm_jack.c b/jack/pcm_jack.c
> index 3370a26..83ac56a 100644
> --- a/jack/pcm_jack.c
> +++ b/jack/pcm_jack.c
> @@ -20,6 +20,8 @@
> *
> */
>
> +#include "config.h"
> +
> #include<byteswap.h>
> #include<sys/shm.h>
> #include<sys/types.h>
> @@ -28,6 +30,10 @@
> #include<alsa/asoundlib.h>
> #include<alsa/pcm_external.h>
>
> +#ifdef HAVE_EVENTFD
> +#include<sys/eventfd.h>
> +#endif
> +
> typedef enum _jack_format {
> SND_PCM_JACK_FORMAT_RAW
> } snd_pcm_jack_format_t;
> @@ -63,8 +69,10 @@ static void snd_pcm_jack_free(snd_pcm_jack_t *jack)
> }
> if (jack->fd>= 0)
> close(jack->fd);
> +#ifndef HAVE_EVENTFD
> if (jack->io.poll_fd>= 0)
> close(jack->io.poll_fd);
> +#endif
> free(jack->areas);
> free(jack);
> }
> @@ -81,11 +89,19 @@ static int snd_pcm_jack_poll_revents(snd_pcm_ioplug_t *io ATTRIBUTE_UNUSED,
> struct pollfd *pfds, unsigned int nfds,
> unsigned short *revents)
> {
> +#ifdef HAVE_EVENTFD
> + eventfd_t buf[1];
> +#else
> static char buf[1];
> -
> +#endif
> +
> assert(pfds&& nfds == 1&& revents);
>
> - read(pfds[0].fd, buf, 1);
> + read(pfds[0].fd, buf, sizeof(buf));
> +#ifdef HAVE_EVENTFD
> + buf[0] -= 1;
> + write(pfds[0].fd, buf, sizeof(buf));
> +#endif
>
> *revents = pfds[0].revents;
> return 0;
> @@ -103,7 +119,11 @@ snd_pcm_jack_process_cb(jack_nframes_t nframes, snd_pcm_ioplug_t *io)
> snd_pcm_jack_t *jack = io->private_data;
> const snd_pcm_channel_area_t *areas;
> snd_pcm_uframes_t xfer = 0;
> +#ifdef HAVE_EVENTFD
> + static eventfd_t buf[1] = { 0x00000001 };
> +#else
> static char buf[1];
> +#endif
> unsigned int channel;
>
> for (channel = 0; channel< io->channels; channel++) {
> @@ -143,7 +163,7 @@ snd_pcm_jack_process_cb(jack_nframes_t nframes, snd_pcm_ioplug_t *io)
> xfer += frames;
> }
>
> - write(jack->fd, buf, 1); /* for polling */
> + write(jack->fd, buf, sizeof(buf)); /* for polling */
>
> return 0;
> }
> @@ -361,7 +381,11 @@ static int snd_pcm_jack_open(snd_pcm_t **pcmp, const char *name,
> return -ENOMEM;
> }
>
> +#ifdef HAVE_EVENTFD
> + fd[0] = fd[1] = eventfd(0, 0);
> +#else
> socketpair(AF_LOCAL, SOCK_STREAM, 0, fd);
> +#endif
>
> jack->fd = fd[0];
>
More information about the Alsa-devel
mailing list