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