if (epoll_fd == -1) {
#ifdef EPOOL_CLOEXEC
- g_warning ("epoll_init: epoll (EPOLL_CLOEXEC) failed, error (%d) %s\n", errno, g_strerror (errno));
+ g_error ("epoll_init: epoll (EPOLL_CLOEXEC) failed, error (%d) %s\n", errno, g_strerror (errno));
#else
- g_warning ("epoll_init: epoll (256) failed, error (%d) %s\n", errno, g_strerror (errno));
+ g_error ("epoll_init: epoll (256) failed, error (%d) %s\n", errno, g_strerror (errno));
#endif
return FALSE;
}
event.events = EPOLLIN;
event.data.fd = wakeup_pipe_fd;
if (epoll_ctl (epoll_fd, EPOLL_CTL_ADD, event.data.fd, &event) == -1) {
- g_warning ("epoll_init: epoll_ctl () failed, error (%d) %s", errno, g_strerror (errno));
+ g_error ("epoll_init: epoll_ctl () failed, error (%d) %s", errno, g_strerror (errno));
close (epoll_fd);
return FALSE;
}
}
static void
-epoll_update_add (gint fd, gint events, gboolean is_new)
+epoll_register_fd (gint fd, gint events, gboolean is_new)
{
struct epoll_event event;
+#ifndef EPOLLONESHOT
+/* it was only defined on android in May 2013 */
+#define EPOLLONESHOT 0x40000000
+#endif
+
event.data.fd = fd;
- if ((events & MONO_POLLIN) != 0)
+ event.events = EPOLLONESHOT;
+ if ((events & EVENT_IN) != 0)
event.events |= EPOLLIN;
- if ((events & MONO_POLLOUT) != 0)
+ if ((events & EVENT_OUT) != 0)
event.events |= EPOLLOUT;
if (epoll_ctl (epoll_fd, is_new ? EPOLL_CTL_ADD : EPOLL_CTL_MOD, event.data.fd, &event) == -1)
- g_warning ("epoll_update_add: epoll_ctl(%s) failed, error (%d) %s", is_new ? "EPOLL_CTL_ADD" : "EPOLL_CTL_MOD", errno, g_strerror (errno));
+ g_error ("epoll_register_fd: epoll_ctl(%s) failed, error (%d) %s", is_new ? "EPOLL_CTL_ADD" : "EPOLL_CTL_MOD", errno, g_strerror (errno));
+}
+
+static void
+epoll_remove_fd (gint fd)
+{
+ if (epoll_ctl (epoll_fd, EPOLL_CTL_DEL, fd, NULL) == -1)
+ g_error ("epoll_remove_fd: epoll_ctl (EPOLL_CTL_DEL) failed, error (%d) %s", errno, g_strerror (errno));
}
static gint
-epoll_event_wait (void)
+epoll_event_wait (void (*callback) (gint fd, gint events, gpointer user_data), gpointer user_data)
{
- gint ready;
+ gint i, ready;
+
+ memset (epoll_events, 0, sizeof (struct epoll_event) * EPOLL_NEVENTS);
+
+ mono_gc_set_skip_thread (TRUE);
ready = epoll_wait (epoll_fd, epoll_events, EPOLL_NEVENTS, -1);
+
+ mono_gc_set_skip_thread (FALSE);
+
if (ready == -1) {
switch (errno) {
case EINTR:
- check_for_interruption_critical ();
+ mono_thread_internal_check_for_interruption_critical (mono_thread_internal_current ());
ready = 0;
break;
default:
- g_warning ("epoll_event_wait: epoll_wait () failed, error (%d) %s", errno, g_strerror (errno));
+ g_error ("epoll_event_wait: epoll_wait () failed, error (%d) %s", errno, g_strerror (errno));
break;
}
}
- return ready;
-}
-
-static gint
-epoll_event_get_fd_max (void)
-{
- return EPOLL_NEVENTS;
-}
+ if (ready == -1)
+ return -1;
-static gint
-epoll_event_get_fd_at (gint i, gint *events)
-{
- g_assert (events);
+ for (i = 0; i < ready; ++i) {
+ gint fd, events = 0;
- *events = ((epoll_events [i].events & (EPOLLIN | EPOLLERR | EPOLLHUP)) ? MONO_POLLIN : 0)
- | ((epoll_events [i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) ? MONO_POLLOUT : 0);
+ fd = epoll_events [i].data.fd;
+ if (epoll_events [i].events & (EPOLLIN | EPOLLERR | EPOLLHUP))
+ events |= EVENT_IN;
+ if (epoll_events [i].events & (EPOLLOUT | EPOLLERR | EPOLLHUP))
+ events |= EVENT_OUT;
- return epoll_events [i].data.fd;
-}
-
-static void
-epoll_event_reset_fd_at (gint i, gint events)
-{
- if (events == 0) {
- if (epoll_ctl (epoll_fd, EPOLL_CTL_DEL, epoll_events [i].data.fd, &epoll_events [i]) == -1)
- g_warning ("epoll_event_reset_fd_at: epoll_ctl (EPOLL_CTL_DEL) failed, error (%d) %s", errno, g_strerror (errno));
- } else {
- epoll_events [i].events = ((events & MONO_POLLOUT) ? EPOLLOUT : 0)
- | ((events & MONO_POLLIN) ? EPOLLIN : 0);
-
- if (epoll_ctl (epoll_fd, EPOLL_CTL_MOD, epoll_events [i].data.fd, &epoll_events [i]) == -1)
- g_warning ("epoll_event_get_ioares_at: epoll_ctl (EPOLL_CTL_MOD) failed, error (%d) %s", errno, g_strerror (errno));
+ callback (fd, events, user_data);
}
+
+ return 0;
}
static ThreadPoolIOBackend backend_epoll = {
.init = epoll_init,
.cleanup = epoll_cleanup,
- .update_add = epoll_update_add,
+ .register_fd = epoll_register_fd,
+ .remove_fd = epoll_remove_fd,
.event_wait = epoll_event_wait,
- .event_get_fd_max = epoll_event_get_fd_max,
- .event_get_fd_at = epoll_event_get_fd_at,
- .event_reset_fd_at = epoll_event_reset_fd_at,
};
#endif