[2019-12] [threads] Add back mono_threads_attach_tools_thread as a public API (#18074)
[mono-project.git] / mono / utils / mono-poll.c
blob022cabc24b4be369980a8ec78de5bde1580b7b7a
1 /**
2 * \file
3 */
5 #include <config.h>
7 #ifdef HOST_WIN32
8 /* For select */
9 #include <winsock2.h>
10 #endif
12 #include "mono-poll.h"
13 #include <errno.h>
14 #include <mono/utils/mono-errno.h>
16 #ifdef DISABLE_SOCKETS
17 #include <glib.h>
19 int
20 mono_poll_can_add (mono_pollfd *ufds, unsigned int nfds, int fd)
22 return 1;
25 int
26 mono_poll (mono_pollfd *ufds, unsigned int nfds, int timeout)
28 g_assert_not_reached ();
29 return -1;
32 #else
34 #if defined(HAVE_POLL) && !defined(__APPLE__)
36 int
37 mono_poll_can_add (mono_pollfd *ufds, unsigned int nfds, int fd)
39 return 1;
42 int
43 mono_poll (mono_pollfd *ufds, unsigned int nfds, int timeout)
45 return poll (ufds, nfds, timeout);
47 #else
49 int
50 mono_poll_can_add (mono_pollfd *ufds, unsigned int nfds, int fd)
52 if (fd < 0)
53 return 1;
54 #ifdef HOST_WIN32
55 return (nfds < FD_SETSIZE);
56 #else
57 return (fd < FD_SETSIZE);
58 #endif
61 int
62 mono_poll (mono_pollfd *ufds, unsigned int nfds, int timeout)
64 struct timeval tv, *tvptr;
65 int i, fd, events, affected, count;
66 fd_set rfds, wfds, efds;
67 int nexc = 0;
68 int maxfd = 0;
70 if (timeout < 0) {
71 tvptr = NULL;
72 } else {
73 tv.tv_sec = timeout / 1000;
74 tv.tv_usec = (timeout % 1000) * 1000;
75 tvptr = &tv;
78 FD_ZERO (&rfds);
79 FD_ZERO (&wfds);
80 FD_ZERO (&efds);
82 for (i = 0; i < nfds; i++) {
83 ufds [i].revents = 0;
84 fd = ufds [i].fd;
85 if (fd < 0)
86 continue;
88 #ifdef HOST_WIN32
89 if (nexc >= FD_SETSIZE) {
90 ufds [i].revents = MONO_POLLNVAL;
91 return 1;
93 #else
94 if (fd >= FD_SETSIZE) {
95 ufds [i].revents = MONO_POLLNVAL;
96 return 1;
98 #endif
100 events = ufds [i].events;
101 if ((events & MONO_POLLIN) != 0)
102 FD_SET (fd, &rfds);
104 if ((events & MONO_POLLOUT) != 0)
105 FD_SET (fd, &wfds);
107 FD_SET (fd, &efds);
108 nexc++;
109 if (fd > maxfd)
110 maxfd = fd;
114 affected = select (maxfd + 1, &rfds, &wfds, &efds, tvptr);
115 if (affected == -1) {
116 #ifdef HOST_WIN32
117 int error = WSAGetLastError ();
118 switch (error) {
119 case WSAEFAULT: mono_set_errno (EFAULT); break;
120 case WSAEINVAL: mono_set_errno (EINVAL); break;
121 case WSAEINTR: mono_set_errno (EINTR); break;
122 /* case WSAEINPROGRESS: mono_set_errno (EINPROGRESS); break; */
123 case WSAEINPROGRESS: mono_set_errno (EINTR); break;
124 case WSAENOTSOCK: mono_set_errno (EBADF); break;
125 #ifdef ENOSR
126 case WSAENETDOWN: mono_set_errno (ENOSR); break;
127 #endif
128 default: mono_set_errno (0);
130 #endif
132 return -1;
135 count = 0;
136 for (i = 0; i < nfds && affected > 0; i++) {
137 fd = ufds [i].fd;
138 if (fd < 0)
139 continue;
141 events = ufds [i].events;
142 if ((events & MONO_POLLIN) != 0 && FD_ISSET (fd, &rfds)) {
143 ufds [i].revents |= MONO_POLLIN;
144 affected--;
147 if ((events & MONO_POLLOUT) != 0 && FD_ISSET (fd, &wfds)) {
148 ufds [i].revents |= MONO_POLLOUT;
149 affected--;
152 if (FD_ISSET (fd, &efds)) {
153 ufds [i].revents |= MONO_POLLERR;
154 affected--;
157 if (ufds [i].revents != 0)
158 count++;
161 return count;
164 #endif
166 #endif /* #ifndef DISABLE_SOCKETS */