[dtrace] GC begin/end probes for SGen.
[mono.git] / mono / metadata / tpool-poll.c
index 5b1af65fb7583fc738f8d08798cce0edb21227a7..e03eca5248cc4c4a0f36bb374064bf2eebab1258 100644 (file)
@@ -1,3 +1,14 @@
+/*
+ * tpool-poll.c: poll 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)
+ */
+
 #define INIT_POLLFD(a, b, c) {(a)->fd = b; (a)->events = c; (a)->revents = 0;}
 struct _tp_poll_data {
        int pipe [2];
@@ -11,30 +22,13 @@ static void tp_poll_shutdown (gpointer event_data);
 static void tp_poll_modify (gpointer event_data, int fd, int operation, int events, gboolean is_new);
 static void tp_poll_wait (gpointer p);
 
-#ifdef HOST_WIN32
-static void
-connect_hack (gpointer x)
-{
-       struct sockaddr_in *addr = (struct sockaddr_in *) x;
-       int count = 0;
-
-       while (connect ((SOCKET) socket_io_data.pipe [1], (SOCKADDR *) addr, sizeof (struct sockaddr_in))) {
-               Sleep (500);
-               if (++count > 3) {
-                       g_warning ("Error initializing async. sockets %d.", WSAGetLastError ());
-                       g_assert (WSAGetLastError ());
-               }
-       }
-}
-#endif
-
 static gpointer
 tp_poll_init (SocketIOData *data)
 {
        tp_poll_data *result;
 #ifdef HOST_WIN32
-       struct sockaddr_in server;
        struct sockaddr_in client;
+       struct sockaddr_in server;
        SOCKET srv;
        int len;
 #endif
@@ -55,7 +49,7 @@ tp_poll_init (SocketIOData *data)
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = inet_addr ("127.0.0.1");
        server.sin_port = 0;
-       if (bind (srv, (SOCKADDR *) &server, sizeof (server))) {
+       if (bind (srv, (SOCKADDR *) &server, sizeof (struct sockaddr_in))) {
                g_print ("%d\n", WSAGetLastError ());
                g_assert (1 != 0);
        }
@@ -63,8 +57,11 @@ tp_poll_init (SocketIOData *data)
        len = sizeof (server);
        getsockname (srv, (SOCKADDR *) &server, &len);
        listen (srv, 1);
-       mono_thread_create (mono_get_root_domain (), connect_hack, &server);
-       len = sizeof (server);
+       if (connect ((SOCKET) result->pipe [1], (SOCKADDR *) &server, sizeof (server)) == SOCKET_ERROR) {
+               g_print ("%d\n", WSAGetLastError ());
+               g_assert (1 != 0);
+       }
+       len = sizeof (client);
        result->pipe [0] = accept (srv, (SOCKADDR *) &client, &len);
        g_assert (result->pipe [0] != INVALID_SOCKET);
        closesocket (srv);
@@ -81,15 +78,15 @@ tp_poll_modify (gpointer event_data, int fd, int operation, int events, gboolean
 {
        tp_poll_data *data = event_data;
        char msg [1];
-       int w;
+       int unused;
 
        MONO_SEM_WAIT (&data->new_sem);
        INIT_POLLFD (&data->newpfd, GPOINTER_TO_INT (fd), events);
        *msg = (char) operation;
 #ifndef HOST_WIN32
-       w = write (data->pipe [1], msg, 1);
+       unused = write (data->pipe [1], msg, 1);
 #else
-       send ((SOCKET) data->pipe [1], msg, 1, 0);
+       unused = send ((SOCKET) data->pipe [1], msg, 1, 0);
 #endif
 }
 
@@ -145,6 +142,10 @@ tp_poll_wait (gpointer p)
 #define INITIAL_POLLFD_SIZE    1024
 #endif
 #define POLL_ERRORS (MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)
+
+#ifdef DISABLE_SOCKETS
+#define socket_io_cleanup(x)
+#endif
        mono_pollfd *pfds;
        gint maxfd = 1;
        gint allocated;
@@ -152,7 +153,7 @@ tp_poll_wait (gpointer p)
        MonoInternalThread *thread;
        tp_poll_data *data;
        SocketIOData *socket_io_data = p;
-       gpointer *async_results;
+       MonoPtrArray async_results;
        gint nresults;
 
        thread = mono_thread_internal_current ();
@@ -160,12 +161,11 @@ tp_poll_wait (gpointer p)
        data = socket_io_data->event_data;
        allocated = INITIAL_POLLFD_SIZE;
        pfds = g_new0 (mono_pollfd, allocated);
-       async_results = g_new0 (gpointer, allocated * 2);
+       mono_ptr_array_init (async_results, allocated * 2);
        INIT_POLLFD (pfds, data->pipe [0], MONO_POLLIN);
        for (i = 1; i < allocated; i++)
                INIT_POLLFD (&pfds [i], -1, 0);
 
-       printf ("poll_wait\n");
        while (1) {
                int nsock = 0;
                mono_pollfd *pfd;
@@ -173,6 +173,8 @@ tp_poll_wait (gpointer p)
                MonoMList *list;
                MonoObject *ares;
 
+               mono_gc_set_skip_thread (TRUE);
+
                do {
                        if (nsock == -1) {
                                if (THREAD_WANTS_A_BREAK (thread))
@@ -182,6 +184,8 @@ tp_poll_wait (gpointer p)
                        nsock = mono_poll (pfds, maxfd, -1);
                } while (nsock == -1 && errno == EINTR);
 
+               mono_gc_set_skip_thread (FALSE);
+
                /* 
                 * Apart from EINTR, we only check EBADF, for the rest:
                 *  EINVAL: mono_poll() 'protects' us from descriptor
@@ -204,7 +208,7 @@ tp_poll_wait (gpointer p)
                if ((pfds->revents & POLL_ERRORS) != 0) {
                        /* We're supposed to die now, as the pipe has been closed */
                        g_free (pfds);
-                       g_free (async_results);
+                       mono_ptr_array_destroy (async_results);
                        socket_io_cleanup (socket_io_data);
                        return;
                }
@@ -212,11 +216,22 @@ tp_poll_wait (gpointer p)
                /* Got a new socket */
                if ((pfds->revents & MONO_POLLIN) != 0) {
                        int nread;
+                       gboolean found = FALSE;
 
                        for (i = 1; i < allocated; i++) {
                                pfd = &pfds [i];
-                               if (pfd->fd == -1 || pfd->fd == data->newpfd.fd)
+                               if (pfd->fd == data->newpfd.fd) {
+                                       found = TRUE;
                                        break;
+                               }
+                       }
+
+                       if (!found) {
+                               for (i = 1; i < allocated; i++) {
+                                       pfd = &pfds [i];
+                                       if (pfd->fd == -1)
+                                               break;
+                               }
                        }
 
                        if (i == allocated) {
@@ -229,7 +244,7 @@ tp_poll_wait (gpointer p)
                                g_free (oldfd);
                                for (; i < allocated; i++)
                                        INIT_POLLFD (&pfds [i], -1, 0);
-                               async_results = g_renew (gpointer, async_results, allocated * 2);
+                               //async_results = g_renew (gpointer, async_results, allocated * 2);
                        }
 #ifndef HOST_WIN32
                        nread = read (data->pipe [0], one, 1);
@@ -238,7 +253,7 @@ tp_poll_wait (gpointer p)
 #endif
                        if (nread <= 0) {
                                g_free (pfds);
-                               g_free (async_results);
+                               mono_ptr_array_destroy (async_results);
                                return; /* we're closed */
                        }
 
@@ -256,12 +271,14 @@ tp_poll_wait (gpointer p)
                EnterCriticalSection (&socket_io_data->io_lock);
                if (socket_io_data->inited == 3) {
                        g_free (pfds);
-                       g_free (async_results);
+                       mono_ptr_array_destroy (async_results);
                        LeaveCriticalSection (&socket_io_data->io_lock);
                        return; /* cleanup called */
                }
 
                nresults = 0;
+               mono_ptr_array_clear (async_results);
+
                for (i = 1; i < maxfd && nsock > 0; i++) {
                        pfd = &pfds [i];
                        if (pfd->fd == -1 || pfd->revents == 0)
@@ -271,14 +288,18 @@ tp_poll_wait (gpointer p)
                        list = mono_g_hash_table_lookup (socket_io_data->sock_to_state, GINT_TO_POINTER (pfd->fd));
                        if (list != NULL && (pfd->revents & (MONO_POLLIN | POLL_ERRORS)) != 0) {
                                ares = get_io_event (&list, MONO_POLLIN);
-                               if (ares != NULL)
-                                       async_results [nresults++] = ares;
+                               if (ares != NULL) {
+                                       mono_ptr_array_append (async_results, ares);
+                                       ++nresults;
+                               }
                        }
 
                        if (list != NULL && (pfd->revents & (MONO_POLLOUT | POLL_ERRORS)) != 0) {
                                ares = get_io_event (&list, MONO_POLLOUT);
-                               if (ares != NULL)
-                                       async_results [nresults++] = ares;
+                               if (ares != NULL) {
+                                       mono_ptr_array_append (async_results, ares);
+                                       ++nresults;
+                               }
                        }
 
                        if (list != NULL) {
@@ -292,8 +313,8 @@ tp_poll_wait (gpointer p)
                        }
                }
                LeaveCriticalSection (&socket_io_data->io_lock);
-               threadpool_append_jobs (&async_io_tp, (MonoObject **) async_results, nresults);
-               memset (async_results, 0, sizeof (gpointer) * nresults);
+               threadpool_append_jobs (&async_io_tp, (MonoObject **) async_results.data, nresults);
+               mono_ptr_array_clear (async_results);
        }
 }