diff options
author | Pierre Ossman <ossman@cendio.se> | 2006-01-05 20:56:17 +0000 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2006-01-05 20:56:17 +0000 |
commit | 29a5b850a7d8e9c4fc878afae336e16cba0c6c25 (patch) | |
tree | 1819dd616088908d3a234a3107408ae668c836c5 | |
parent | d3bc7b27b7b0da1a8d9de2cd93ac10096b6b0b17 (diff) |
Emulate poll() through select() where needed.
git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/ossman@397 fefdeb5f-60dc-0310-8127-8f9354f1896f
-rw-r--r-- | polyp/Makefile.am | 4 | ||||
-rw-r--r-- | polyp/mainloop.c | 7 | ||||
-rw-r--r-- | polyp/module-alsa-sink.c | 5 | ||||
-rw-r--r-- | polyp/module-alsa-source.c | 5 | ||||
-rw-r--r-- | polyp/poll.c | 173 | ||||
-rw-r--r-- | polyp/poll.h | 57 |
6 files changed, 249 insertions, 2 deletions
diff --git a/polyp/Makefile.am b/polyp/Makefile.am index 2cd2a1f3..6ec75d4c 100644 --- a/polyp/Makefile.am +++ b/polyp/Makefile.am @@ -327,7 +327,8 @@ libpolyp_error_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 libpolyp_mainloop_@PA_MAJORMINOR@_la_SOURCES = \ mainloop.c mainloop.h \ mainloop-api.h mainloop-api.c \ - mainloop-signal.c mainloop-signal.h + mainloop-signal.c mainloop-signal.h \ + poll.c poll.h libpolyp_mainloop_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) libpolyp_mainloop_@PA_MAJORMINOR@_la_LIBADD = $(AM_LIBADD) libpolyp-@PA_MAJORMINOR@.la $(WINSOCK_LIBS) libpolyp_mainloop_@PA_MAJORMINOR@_la_LDFLAGS = -version-info 0:0:0 @@ -413,6 +414,7 @@ libpolypcore_la_SOURCES = \ module.c module.h \ namereg.c namereg.h \ play-memchunk.c play-memchunk.h \ + poll.c poll.h \ props.c props.h \ queue.c queue.h \ random.c random.h \ diff --git a/polyp/mainloop.c b/polyp/mainloop.c index a0d27827..90243bdf 100644 --- a/polyp/mainloop.c +++ b/polyp/mainloop.c @@ -26,13 +26,18 @@ #include <stdio.h> #include <signal.h> #include <unistd.h> -#include <sys/poll.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include <fcntl.h> #include <errno.h> +#ifdef HAVE_SYS_POLL_H +#include <sys/poll.h> +#else +#include "poll.h" +#endif + #include "mainloop.h" #include "util.h" #include "idxset.h" diff --git a/polyp/module-alsa-sink.c b/polyp/module-alsa-sink.c index 69db2875..dde5d8b6 100644 --- a/polyp/module-alsa-sink.c +++ b/polyp/module-alsa-sink.c @@ -25,7 +25,12 @@ #include <assert.h> #include <stdio.h> + +#ifdef HAVE_SYS_POLL_H #include <sys/poll.h> +#else +#include "poll.h" +#endif #include <asoundlib.h> diff --git a/polyp/module-alsa-source.c b/polyp/module-alsa-source.c index 55abe8e0..5b4076f8 100644 --- a/polyp/module-alsa-source.c +++ b/polyp/module-alsa-source.c @@ -25,7 +25,12 @@ #include <assert.h> #include <stdio.h> + +#ifdef HAVE_SYS_POLL_H #include <sys/poll.h> +#else +#include "poll.h" +#endif #include <asoundlib.h> diff --git a/polyp/poll.c b/polyp/poll.c new file mode 100644 index 00000000..82ea3d88 --- /dev/null +++ b/polyp/poll.c @@ -0,0 +1,173 @@ +/* $Id: mainloop.c 302 2004-11-21 17:02:25Z lennart $ */ + +/*** + Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc. + Copyright (C) 2005, Cendio AB. + This file is part of polypaudio. + Based on work for the GNU C Library. + + polypaudio is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with polypaudio; If not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. +***/ + +/* Poll the file descriptors described by the NFDS structures starting at + FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for + an event to occur; if TIMEOUT is -1, block until an event occurs. + Returns the number of file descriptors with events, zero if timed out, + or -1 for errors. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_SYS_SELECT_H +#include <sys/select.h> +#endif + +#ifndef HAVE_SYS_POLL_H + +#include "util.h" +#include "poll.h" + +int poll (struct pollfd *fds, unsigned long int nfds, int timeout) { + struct timeval tv; + fd_set rset, wset, xset; + struct pollfd *f; + int ready; + int maxfd = 0; + char data[64]; + + FD_ZERO (&rset); + FD_ZERO (&wset); + FD_ZERO (&xset); + + if (nfds == 0) { + if (timeout >= 0) { + pa_msleep(timeout); + return 0; + } + + return select(0, NULL, NULL, NULL, NULL); + } + + for (f = fds; f < &fds[nfds]; ++f) { + if (f->fd != -1) { + if (f->events & POLLIN) + FD_SET (f->fd, &rset); + if (f->events & POLLOUT) + FD_SET (f->fd, &wset); + if (f->events & POLLPRI) + FD_SET (f->fd, &xset); + if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI))) + maxfd = f->fd; + } + } + + tv.tv_sec = timeout / 1000; + tv.tv_usec = (timeout % 1000) * 1000; + + ready = select ((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 &rset, + SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset, + SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv)); + if ((ready == -1) && (errno == EBADF)) { + ready = 0; + + FD_ZERO (&rset); + FD_ZERO (&wset); + FD_ZERO (&xset); + + maxfd = -1; + + for (f = fds; f < &fds[nfds]; ++f) { + if (f->fd != -1) { + fd_set sngl_rset, sngl_wset, sngl_xset; + + FD_ZERO (&sngl_rset); + FD_ZERO (&sngl_wset); + FD_ZERO (&sngl_xset); + + if (f->events & POLLIN) + FD_SET (f->fd, &sngl_rset); + if (f->events & POLLOUT) + FD_SET (f->fd, &sngl_wset); + if (f->events & POLLPRI) + FD_SET (f->fd, &sngl_xset); + if (f->events & (POLLIN|POLLOUT|POLLPRI)) { + struct timeval singl_tv; + + singl_tv.tv_sec = 0; + singl_tv.tv_usec = 0; + + if (select((SELECT_TYPE_ARG1) f->fd, SELECT_TYPE_ARG234 &rset, + SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset, + SELECT_TYPE_ARG5 &singl_tv) != -1) { + if (f->events & POLLIN) + FD_SET (f->fd, &rset); + if (f->events & POLLOUT) + FD_SET (f->fd, &wset); + if (f->events & POLLPRI) + FD_SET (f->fd, &xset); + if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI))) + maxfd = f->fd; + ++ready; + } else if (errno == EBADF) + f->revents |= POLLNVAL; + } + } + } + + if (ready) { + /* Linux alters the tv struct... but it shouldn't matter here ... + * as we're going to be a little bit out anyway as we've just eaten + * more than a couple of cpu cycles above */ + ready = select ((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 &rset, + SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset, + SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv)); + } + } + + if (ready > 0) { + ready = 0; + for (f = fds; f < &fds[nfds]; ++f) { + f->revents = 0; + if (f->fd != -1) { + if (FD_ISSET (f->fd, &rset)) { + /* support for POLLHUP. An hung up descriptor does not + increase the return value! */ + if (recv (f->fd, data, 64, MSG_PEEK) == -1) { + if (errno == ESHUTDOWN || errno == ECONNRESET || + errno == ECONNABORTED || errno == ENETRESET) { + fprintf(stderr, "Hangup\n"); + f->revents |= POLLHUP; + } + } + + if (f->revents == 0) + f->revents |= POLLIN; + } + if (FD_ISSET (f->fd, &wset)) + f->revents |= POLLOUT; + if (FD_ISSET (f->fd, &xset)) + f->revents |= POLLPRI; + } + if (f->revents) + ready++; + } + } + + return ready; +} + +#endif /* HAVE_SYS_POLL_H */ diff --git a/polyp/poll.h b/polyp/poll.h new file mode 100644 index 00000000..573f90ea --- /dev/null +++ b/polyp/poll.h @@ -0,0 +1,57 @@ +/* $Id: mainloop.c 302 2004-11-21 17:02:25Z lennart $ */ + +/*** + Compatibility definitions for System V `poll' interface. + Copyright (C) 1994,96,97,98,99,2000,2001,2004 Free Software Foundation, Inc. + Copyright (C) 2005, Cendio AB. + This file is part of polypaudio. + Based on work for the GNU C Library. + + polypaudio is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + polypaudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with polypaudio; If not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. +***/ + +/* Event types that can be polled for. These bits may be set in `events' + to indicate the interesting event types; they will appear in `revents' + to indicate the status of the file descriptor. */ +#define POLLIN 0x001 /* There is data to read. */ +#define POLLPRI 0x002 /* There is urgent data to read. */ +#define POLLOUT 0x004 /* Writing now will not block. */ + +/* Event types always implicitly polled for. These bits need not be set in + `events', but they will appear in `revents' to indicate the status of + the file descriptor. */ +#define POLLERR 0x008 /* Error condition. */ +#define POLLHUP 0x010 /* Hung up. */ +#define POLLNVAL 0x020 /* Invalid polling request. */ + + +/* Type used for the number of file descriptors. */ +typedef unsigned long int nfds_t; + +/* Data structure describing a polling request. */ +struct pollfd + { + int fd; /* File descriptor to poll. */ + short int events; /* Types of events poller cares about. */ + short int revents; /* Types of events that actually occurred. */ + }; + +/* Poll the file descriptors described by the NFDS structures starting at + FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for + an event to occur; if TIMEOUT is -1, block until an event occurs. + Returns the number of file descriptors with events, zero if timed out, + or -1 for errors. */ +extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout); |