[arm64] Allow v8..v15 in unwind info on arm64. Fixes part of #21615.
[mono.git] / mono / metadata / tpool-epoll.c
index 12431f0ca0b9aa08b63ef0e442699696b24e19ce..bab57abf876b973ceb9ded37fb05289e927be4fe 100644 (file)
@@ -1,9 +1,21 @@
+/*
+ * 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);
 
@@ -19,8 +31,18 @@ tp_epoll_init (SocketIOData *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;
@@ -29,12 +51,17 @@ tp_epoll_init (SocketIOData *data)
 }
 
 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;
@@ -51,6 +78,7 @@ tp_epoll_modify (gpointer event_data, int fd, int operation, int events, gboolea
                        }
                }
        }
+       mono_mutex_unlock (&socket_io_data->io_lock);
 }
 
 static void
@@ -59,7 +87,7 @@ tp_epoll_shutdown (gpointer event_data)
        tp_epoll_data *data = event_data;
 
        close (data->epollfd);
-       data->epollfd = -1;
+       g_free (data);
 }
 
 #define EPOLL_ERRORS (EPOLLERR | EPOLLHUP)
@@ -69,7 +97,6 @@ tp_epoll_wait (gpointer p)
 {
        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
@@ -79,34 +106,33 @@ tp_epoll_wait (gpointer p)
        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 */
                }
 
@@ -132,19 +158,27 @@ tp_epoll_wait (gpointer p)
                        }
 
                        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