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