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