Pass the --clr-memory-model flag on the command line instead of MONO_DEBUG so its...
[mono-project.git] / mono / metadata / threadpool-io-poll.c
blob2563e6d4f5c18dbdd1dca16881af9fb101cbbd27
1 /**
2 * \file
3 */
5 #include "utils/mono-poll.h"
7 static mono_pollfd *poll_fds;
8 static guint poll_fds_capacity;
9 static guint poll_fds_size;
11 static inline void
12 POLL_INIT_FD (mono_pollfd *poll_fd, gint fd, gint events)
14 poll_fd->fd = fd;
15 poll_fd->events = events;
16 poll_fd->revents = 0;
19 static gboolean
20 poll_init (gint wakeup_pipe_fd)
22 g_assert (wakeup_pipe_fd >= 0);
24 poll_fds_size = 1;
25 poll_fds_capacity = 64;
27 poll_fds = g_new0 (mono_pollfd, poll_fds_capacity);
29 POLL_INIT_FD (&poll_fds [0], wakeup_pipe_fd, MONO_POLLIN);
31 return TRUE;
34 static void
35 poll_register_fd (gint fd, gint events, gboolean is_new)
37 gint i;
38 gint poll_event;
40 g_assert (fd >= 0);
41 g_assert (poll_fds_size <= poll_fds_capacity);
43 g_assert ((events & ~(EVENT_IN | EVENT_OUT)) == 0);
45 poll_event = 0;
46 if (events & EVENT_IN)
47 poll_event |= MONO_POLLIN;
48 if (events & EVENT_OUT)
49 poll_event |= MONO_POLLOUT;
51 for (i = 0; i < poll_fds_size; ++i) {
52 if (poll_fds [i].fd == fd) {
53 g_assert (!is_new);
54 POLL_INIT_FD (&poll_fds [i], fd, poll_event);
55 return;
59 g_assert (is_new);
61 for (i = 0; i < poll_fds_size; ++i) {
62 if (poll_fds [i].fd == -1) {
63 POLL_INIT_FD (&poll_fds [i], fd, poll_event);
64 return;
68 poll_fds_size += 1;
70 if (poll_fds_size > poll_fds_capacity) {
71 poll_fds_capacity *= 2;
72 g_assert (poll_fds_size <= poll_fds_capacity);
74 poll_fds = (mono_pollfd *)g_renew (mono_pollfd, poll_fds, poll_fds_capacity);
77 POLL_INIT_FD (&poll_fds [poll_fds_size - 1], fd, poll_event);
80 static void
81 poll_remove_fd (gint fd)
83 gint i;
85 g_assert (fd >= 0);
87 for (i = 0; i < poll_fds_size; ++i) {
88 if (poll_fds [i].fd == fd) {
89 POLL_INIT_FD (&poll_fds [i], -1, 0);
90 break;
94 /* if we don't find the fd in poll_fds,
95 * it means we try to delete it twice */
96 g_assert (i < poll_fds_size);
98 /* if we find it again, it means we added
99 * it twice */
100 for (; i < poll_fds_size; ++i)
101 g_assert (poll_fds [i].fd != fd);
103 /* reduce the value of poll_fds_size so we
104 * do not keep it too big */
105 while (poll_fds_size > 1 && poll_fds [poll_fds_size - 1].fd == -1)
106 poll_fds_size -= 1;
109 static inline gint
110 poll_mark_bad_fds (mono_pollfd *fds, gint size)
112 gint i, ready = 0;
114 for (i = 0; i < size; i++) {
115 if (fds [i].fd == -1)
116 continue;
118 switch (mono_poll (&fds [i], 1, 0)) {
119 case 1:
120 ready++;
121 break;
122 case -1:
123 if (errno == EBADF)
125 fds [i].revents |= MONO_POLLNVAL;
126 ready++;
128 break;
132 return ready;
135 static gint
136 poll_event_wait (void (*callback) (gint fd, gint events, gpointer user_data), gpointer user_data)
138 gint i, ready;
140 for (i = 0; i < poll_fds_size; ++i)
141 poll_fds [i].revents = 0;
143 mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NO_GC);
145 MONO_ENTER_GC_SAFE;
146 ready = mono_poll (poll_fds, poll_fds_size, -1);
147 MONO_EXIT_GC_SAFE;
149 mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NONE);
151 if (ready == -1) {
153 * Apart from EINTR, we only check EBADF, for the rest:
154 * EINVAL: mono_poll() 'protects' us from descriptor
155 * numbers above the limit if using select() by marking
156 * then as POLLERR. If a system poll() is being
157 * used, the number of descriptor we're passing will not
158 * be over sysconf(_SC_OPEN_MAX), as the error would have
159 * happened when opening.
161 * EFAULT: we own the memory pointed by pfds.
162 * ENOMEM: we're doomed anyway
165 switch (errno)
167 case EINTR:
169 ready = 0;
170 break;
172 case EBADF:
174 ready = poll_mark_bad_fds (poll_fds, poll_fds_size);
175 break;
177 default:
178 g_error ("poll_event_wait: mono_poll () failed, error (%d) %s", errno, g_strerror (errno));
179 break;
183 if (ready == -1)
184 return -1;
185 if (ready == 0)
186 return 0;
188 g_assert (ready > 0);
190 for (i = 0; i < poll_fds_size; ++i) {
191 gint fd, events = 0;
193 if (poll_fds [i].fd == -1)
194 continue;
195 if (poll_fds [i].revents == 0)
196 continue;
198 fd = poll_fds [i].fd;
199 if (poll_fds [i].revents & (MONO_POLLIN | MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL))
200 events |= EVENT_IN;
201 if (poll_fds [i].revents & (MONO_POLLOUT | MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL))
202 events |= EVENT_OUT;
203 if (poll_fds [i].revents & (MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL))
204 events |= EVENT_ERR;
206 callback (fd, events, user_data);
208 if (--ready == 0)
209 break;
212 return 0;
215 static ThreadPoolIOBackend backend_poll = {
216 poll_init,
217 poll_register_fd,
218 poll_remove_fd,
219 poll_event_wait,