Merge pull request #631 from kebby/master
[mono.git] / mono / utils / mono-poll.c
1 #include "mono-poll.h"
2 #include <errno.h>
3
4 #ifdef DISABLE_SOCKETS
5 #include <glib.h>
6
7 int
8 mono_poll (mono_pollfd *ufds, unsigned int nfds, int timeout)
9 {
10         g_assert_not_reached ();
11         return -1;
12 }
13 #else
14
15 #if defined(HAVE_POLL) && !defined(__APPLE__)
16 int
17 mono_poll (mono_pollfd *ufds, unsigned int nfds, int timeout)
18 {
19         return poll (ufds, nfds, timeout);
20 }
21 #else
22
23 int
24 mono_poll (mono_pollfd *ufds, unsigned int nfds, int timeout)
25 {
26         struct timeval tv, *tvptr;
27         int i, fd, events, affected, count;
28         fd_set rfds, wfds, efds;
29         int nexc = 0;
30         int maxfd = 0;
31
32         if (timeout < 0) {
33                 tvptr = NULL;
34         } else {
35                 tv.tv_sec = timeout / 1000;
36                 tv.tv_usec = (timeout % 1000) * 1000;
37                 tvptr = &tv;
38         }
39
40         FD_ZERO (&rfds);
41         FD_ZERO (&wfds);
42         FD_ZERO (&efds);
43
44         for (i = 0; i < nfds; i++) {
45                 ufds [i].revents = 0;
46                 fd = ufds [i].fd;
47                 if (fd < 0)
48                         continue;
49
50 #ifdef HOST_WIN32
51                 if (nexc >= FD_SETSIZE) {
52                         ufds [i].revents = MONO_POLLNVAL;
53                         return 1;
54                 }
55 #else
56                 if (fd > FD_SETSIZE) {
57                         ufds [i].revents = MONO_POLLNVAL;
58                         return 1;
59                 }
60 #endif
61
62                 events = ufds [i].events;
63                 if ((events & MONO_POLLIN) != 0)
64                         FD_SET (fd, &rfds);
65
66                 if ((events & MONO_POLLOUT) != 0)
67                         FD_SET (fd, &wfds);
68
69                 FD_SET (fd, &efds);
70                 nexc++;
71                 if (fd > maxfd)
72                         maxfd = fd;
73                         
74         }
75
76         affected = select (maxfd + 1, &rfds, &wfds, &efds, tvptr);
77         if (affected == -1) {
78 #ifdef HOST_WIN32
79                 int error = WSAGetLastError ();
80                 switch (error) {
81                 case WSAEFAULT: errno = EFAULT; break;
82                 case WSAEINVAL: errno = EINVAL; break;
83                 case WSAEINTR: errno = EINTR; break;
84                 /* case WSAEINPROGRESS: errno = EINPROGRESS; break; */
85                 case WSAEINPROGRESS: errno = EINTR; break;
86                 case WSAENOTSOCK: errno = EBADF; break;
87 #ifdef ENOSR
88                 case WSAENETDOWN: errno = ENOSR; break;
89 #endif
90                 default: errno = 0;
91                 }
92 #endif
93
94                 return -1;
95         }
96
97         count = 0;
98         for (i = 0; i < nfds && affected > 0; i++) {
99                 fd = ufds [i].fd;
100                 if (fd < 0)
101                         continue;
102
103                 events = ufds [i].events;
104                 if ((events & MONO_POLLIN) != 0 && FD_ISSET (fd, &rfds)) {
105                         ufds [i].revents |= MONO_POLLIN;
106                         affected--;
107                 }
108
109                 if ((events & MONO_POLLOUT) != 0 && FD_ISSET (fd, &wfds)) {
110                         ufds [i].revents |= MONO_POLLOUT;
111                         affected--;
112                 }
113
114                 if (FD_ISSET (fd, &efds)) {
115                         ufds [i].revents |= MONO_POLLERR;
116                         affected--;
117                 }
118
119                 if (ufds [i].revents != 0)
120                         count++;
121         }
122
123         return count;
124 }
125
126 #endif
127
128 #endif /* #ifndef DISABLE_SOCKETS */