+/*
+ * tpool-epoll.c: epoll related stuff
+ *
+ * Authors:
+ * Dietmar Maurer (dietmar@ximian.com)
+ * Gonzalo Paniagua Javier (gonzalo@ximian.com)
+ *
+ * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
+ * Copyright 2004-2011 Novell, Inc (http://www.novell.com)
+ * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
+ */
+
struct _tp_epoll_data {
int epollfd;
};
typedef struct _tp_epoll_data tp_epoll_data;
-static void tp_epoll_modify (gpointer event_data, int fd, int operation, int events, gboolean is_new);
+static void tp_epoll_modify (gpointer p, int fd, int operation, int events, gboolean is_new);
static void tp_epoll_shutdown (gpointer event_data);
static void tp_epoll_wait (gpointer event_data);
result->epollfd = epoll_create (256); /* The number does not really matter */
fcntl (result->epollfd, F_SETFD, FD_CLOEXEC);
#endif
- if (result->epollfd == -1)
+ if (result->epollfd == -1) {
+ int err = errno;
+ if (g_getenv ("MONO_DEBUG")) {
+#ifdef EPOLL_CLOEXEC
+ g_message ("epoll_create1(EPOLL_CLOEXEC) failed: %d %s", err, g_strerror (err));
+#else
+ g_message ("epoll_create(256) failed: %d %s", err, g_strerror (err));
+#endif
+ }
+
return NULL;
+ }
data->shutdown = tp_epoll_shutdown;
data->modify = tp_epoll_modify;
}
static void
-tp_epoll_modify (gpointer event_data, int fd, int operation, int events, gboolean is_new)
+tp_epoll_modify (gpointer p, int fd, int operation, int events, gboolean is_new)
{
- tp_epoll_data *data = event_data;
+ SocketIOData *socket_io_data;
+ tp_epoll_data *data;
struct epoll_event evt;
int epoll_op;
+ socket_io_data = p;
+ data = socket_io_data->event_data;
+
+ memset (&evt, 0, sizeof (evt));
evt.data.fd = fd;
if ((events & MONO_POLLIN) != 0)
evt.events |= EPOLLIN;
}
}
}
+ mono_mutex_unlock (&socket_io_data->io_lock);
}
static void
tp_epoll_data *data = event_data;
close (data->epollfd);
- data->epollfd = -1;
+ g_free (data);
}
#define EPOLL_ERRORS (EPOLLERR | EPOLLHUP)
{
SocketIOData *socket_io_data;
int epollfd;
- MonoInternalThread *thread;
struct epoll_event *events, *evt;
int ready = 0, i;
gpointer async_results [EPOLL_NEVENTS * 2]; // * 2 because each loop can add up to 2 results here
socket_io_data = p;
data = socket_io_data->event_data;
epollfd = data->epollfd;
- thread = mono_thread_internal_current ();
events = g_new0 (struct epoll_event, EPOLL_NEVENTS);
- printf ("epoll_wait\n");
while (1) {
+ mono_gc_set_skip_thread (TRUE);
+
do {
if (ready == -1) {
- if (THREAD_WANTS_A_BREAK (thread))
- mono_thread_interruption_checkpoint ();
+ check_for_interruption_critical ();
}
ready = epoll_wait (epollfd, events, EPOLL_NEVENTS, -1);
} while (ready == -1 && errno == EINTR);
+ mono_gc_set_skip_thread (FALSE);
+
if (ready == -1) {
int err = errno;
g_free (events);
if (err != EBADF)
g_warning ("epoll_wait: %d %s", err, g_strerror (err));
- close (epollfd);
return;
}
- EnterCriticalSection (&socket_io_data->io_lock);
+ mono_mutex_lock (&socket_io_data->io_lock);
if (socket_io_data->inited == 3) {
g_free (events);
- close (epollfd);
- LeaveCriticalSection (&socket_io_data->io_lock);
+ mono_mutex_unlock (&socket_io_data->io_lock);
return; /* cleanup called */
}
}
if (list != NULL) {
+ int p;
+
mono_g_hash_table_replace (socket_io_data->sock_to_state, GINT_TO_POINTER (fd), list);
- evt->events = get_events_from_list (list);
- if (epoll_ctl (epollfd, EPOLL_CTL_MOD, fd, evt)) {
- epoll_ctl (epollfd, EPOLL_CTL_ADD, fd, evt); /* ignoring error here */
+ p = get_events_from_list (list);
+ evt->events = (p & MONO_POLLOUT) ? EPOLLOUT : 0;
+ evt->events |= (p & MONO_POLLIN) ? EPOLLIN : 0;
+ if (epoll_ctl (epollfd, EPOLL_CTL_MOD, fd, evt) == -1) {
+ if (epoll_ctl (epollfd, EPOLL_CTL_ADD, fd, evt) == -1) {
+ int err = errno;
+ g_message ("epoll(ADD): %d %s", err, g_strerror (err));
+ }
}
} else {
mono_g_hash_table_remove (socket_io_data->sock_to_state, GINT_TO_POINTER (fd));
epoll_ctl (epollfd, EPOLL_CTL_DEL, fd, evt);
}
}
- LeaveCriticalSection (&socket_io_data->io_lock);
+ mono_mutex_unlock (&socket_io_data->io_lock);
threadpool_append_jobs (&async_io_tp, (MonoObject **) async_results, nresults);
- memset (async_results, 0, sizeof (gpointer) * nresults);
+ mono_gc_bzero_aligned (async_results, sizeof (gpointer) * nresults);
}
}
#undef EPOLL_NEVENTS
+#undef EPOLL_ERRORS