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