Add copyright notices to all relevant files. (based on svn log)
[profile/ivi/pulseaudio.git] / src / pulsecore / poll.c
1 /* $Id$ */
2
3
4 /***
5   This file is part of PulseAudio.
6
7   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
8
9   PulseAudio is free software; you can redistribute it and/or modify
10   it under the terms of the GNU Lesser General Public License as published
11   by the Free Software Foundation; either version 2 of the License,
12   or (at your option) any later version.
13
14   PulseAudio is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with PulseAudio; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22   USA.
23 ***/
24
25 /***
26    Based on work for the GNU C Library.
27    Copyright (C) 1994, 1996, 1997 Free Software Foundation, Inc.
28 ***/
29
30 /* Poll the file descriptors described by the NFDS structures starting at
31    FDS.  If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
32    an event to occur; if TIMEOUT is -1, block until an event occurs.
33    Returns the number of file descriptors with events, zero if timed out,
34    or -1 for errors.  */
35
36 #ifdef HAVE_CONFIG_H
37 #include <config.h>
38 #endif
39
40 #include <errno.h>
41
42 #ifdef HAVE_SYS_SELECT_H
43 #include <sys/select.h>
44 #endif
45
46 #include "winsock.h"
47
48 #ifndef HAVE_SYS_POLL_H
49
50 #include <pulsecore/core-util.h>
51
52 #include "poll.h"
53
54 int poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
55     struct timeval tv;
56     fd_set rset, wset, xset;
57     struct pollfd *f;
58     int ready;
59     int maxfd = 0;
60     char data[64];
61
62     FD_ZERO (&rset);
63     FD_ZERO (&wset);
64     FD_ZERO (&xset);
65
66     if (nfds == 0) {
67         if (timeout >= 0) {
68             pa_msleep(timeout);
69             return 0;
70         }
71
72 #ifdef OS_IS_WIN32
73         /*
74          * Windows does not support signals properly so waiting for them would
75          * mean a deadlock.
76          */
77         pa_msleep(100);
78         return 0;
79 #else
80         return select(0, NULL, NULL, NULL, NULL);
81 #endif
82     }
83
84     for (f = fds; f < &fds[nfds]; ++f) {
85         if (f->fd != -1) {
86             if (f->events & POLLIN)
87                 FD_SET (f->fd, &rset);
88             if (f->events & POLLOUT)
89                 FD_SET (f->fd, &wset);
90             if (f->events & POLLPRI)
91                 FD_SET (f->fd, &xset);
92             if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
93                 maxfd = f->fd;
94         }
95     }
96
97     tv.tv_sec = timeout / 1000;
98     tv.tv_usec = (timeout % 1000) * 1000;
99
100     ready = select ((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 &rset,
101                     SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
102                     SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv));
103     if ((ready == -1) && (errno == EBADF)) {
104         ready = 0;
105
106         FD_ZERO (&rset);
107         FD_ZERO (&wset);
108         FD_ZERO (&xset);
109
110         maxfd = -1;
111
112         for (f = fds; f < &fds[nfds]; ++f) {
113             if (f->fd != -1) {
114                 fd_set sngl_rset, sngl_wset, sngl_xset;
115
116                 FD_ZERO (&sngl_rset);
117                 FD_ZERO (&sngl_wset);
118                 FD_ZERO (&sngl_xset);
119
120                 if (f->events & POLLIN)
121                     FD_SET (f->fd, &sngl_rset);
122                 if (f->events & POLLOUT)
123                     FD_SET (f->fd, &sngl_wset);
124                 if (f->events & POLLPRI)
125                     FD_SET (f->fd, &sngl_xset);
126                 if (f->events & (POLLIN|POLLOUT|POLLPRI)) {
127                     struct timeval singl_tv;
128
129                     singl_tv.tv_sec = 0;
130                     singl_tv.tv_usec = 0;
131
132                     if (select((SELECT_TYPE_ARG1) f->fd, SELECT_TYPE_ARG234 &rset,
133                                SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
134                                SELECT_TYPE_ARG5 &singl_tv) != -1) {
135                         if (f->events & POLLIN)
136                             FD_SET (f->fd, &rset);
137                         if (f->events & POLLOUT)
138                             FD_SET (f->fd, &wset);
139                         if (f->events & POLLPRI)
140                             FD_SET (f->fd, &xset);
141                         if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI)))
142                             maxfd = f->fd;
143                         ++ready;
144                     } else if (errno == EBADF)
145                         f->revents |= POLLNVAL;
146                 }
147             }
148         }
149
150         if (ready) {
151         /* Linux alters the tv struct... but it shouldn't matter here ...
152          * as we're going to be a little bit out anyway as we've just eaten
153          * more than a couple of cpu cycles above */
154             ready = select ((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 &rset,
155                             SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
156                             SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv));
157         }
158     }
159
160 #ifdef OS_IS_WIN32
161     errno = WSAGetLastError();
162 #endif
163
164     if (ready > 0) {
165         ready = 0;
166         for (f = fds; f < &fds[nfds]; ++f) {
167             f->revents = 0;
168             if (f->fd != -1) {
169                 if (FD_ISSET (f->fd, &rset)) {
170                     /* support for POLLHUP.  An hung up descriptor does not
171                        increase the return value! */
172                     if (recv (f->fd, data, 64, MSG_PEEK) == -1) {
173                         if (errno == ESHUTDOWN || errno == ECONNRESET ||
174                             errno == ECONNABORTED || errno == ENETRESET) {
175                             fprintf(stderr, "Hangup\n");
176                             f->revents |= POLLHUP;
177                         }
178                     }
179
180                     if (f->revents == 0)
181                         f->revents |= POLLIN;
182                 }
183                 if (FD_ISSET (f->fd, &wset))
184                     f->revents |= POLLOUT;
185                 if (FD_ISSET (f->fd, &xset))
186                     f->revents |= POLLPRI;
187             }
188             if (f->revents)
189                 ready++;
190         }
191     }
192
193     return ready;
194 }
195
196 #endif /* HAVE_SYS_POLL_H */