X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fthreadpool-ms-io-poll.c;h=3d32130d3b530cc14ad38ce04cffaf5258ac28cf;hb=94ecf49a0b60b0a312113af1dc1f4c5fabedeed2;hp=c7c0af2b5a64a51a1416ddc6879670b623abe7e6;hpb=385c7692be38f92f91151d0c998a551d42b081f7;p=mono.git diff --git a/mono/metadata/threadpool-ms-io-poll.c b/mono/metadata/threadpool-ms-io-poll.c index c7c0af2b5a6..3d32130d3b5 100644 --- a/mono/metadata/threadpool-ms-io-poll.c +++ b/mono/metadata/threadpool-ms-io-poll.c @@ -1,24 +1,5 @@ -#if defined(HAVE_POLL) - -#if defined(HAVE_POLL_H) -#include -#elif defined(HAVE_SYS_POLL_H) -#include -#endif - -typedef struct pollfd mono_pollfd; - -#elif defined(HOST_WIN32) - -#include "mswsock.h" - -typedef WSAPOLLFD mono_pollfd; - -#else -/* poll is not defined */ -#error -#endif +#include "utils/mono-poll.h" static mono_pollfd *poll_fds; static guint poll_fds_capacity; @@ -42,17 +23,11 @@ poll_init (gint wakeup_pipe_fd) poll_fds = g_new0 (mono_pollfd, poll_fds_capacity); - POLL_INIT_FD (&poll_fds [0], wakeup_pipe_fd, POLLIN); + POLL_INIT_FD (&poll_fds [0], wakeup_pipe_fd, MONO_POLLIN); return TRUE; } -static void -poll_cleanup (void) -{ - g_free (poll_fds); -} - static void poll_register_fd (gint fd, gint events, gboolean is_new) { @@ -66,9 +41,9 @@ poll_register_fd (gint fd, gint events, gboolean is_new) poll_event = 0; if (events & EVENT_IN) - poll_event |= POLLIN; + poll_event |= MONO_POLLIN; if (events & EVENT_OUT) - poll_event |= POLLOUT; + poll_event |= MONO_POLLOUT; for (i = 0; i < poll_fds_size; ++i) { if (poll_fds [i].fd == fd) { @@ -93,7 +68,7 @@ poll_register_fd (gint fd, gint events, gboolean is_new) poll_fds_capacity *= 2; g_assert (poll_fds_size <= poll_fds_capacity); - poll_fds = g_renew (mono_pollfd, poll_fds, poll_fds_capacity); + poll_fds = (mono_pollfd *)g_renew (mono_pollfd, poll_fds, poll_fds_capacity); } POLL_INIT_FD (&poll_fds [poll_fds_size - 1], fd, poll_event); @@ -109,11 +84,49 @@ poll_remove_fd (gint fd) for (i = 0; i < poll_fds_size; ++i) { if (poll_fds [i].fd == fd) { POLL_INIT_FD (&poll_fds [i], -1, 0); - return; + break; + } + } + + /* if we don't find the fd in poll_fds, + * it means we try to delete it twice */ + g_assert (i < poll_fds_size); + + /* if we find it again, it means we added + * it twice */ + for (; i < poll_fds_size; ++i) + g_assert (poll_fds [i].fd != fd); + + /* reduce the value of poll_fds_size so we + * do not keep it too big */ + while (poll_fds_size > 1 && poll_fds [poll_fds_size - 1].fd == -1) + poll_fds_size -= 1; +} + +static inline gint +poll_mark_bad_fds (mono_pollfd *poll_fds, gint poll_fds_size) +{ + gint i, ready = 0; + + for (i = 0; i < poll_fds_size; i++) { + if (poll_fds [i].fd == -1) + continue; + + switch (mono_poll (&poll_fds [i], 1, 0)) { + case 1: + ready++; + break; + case -1: + if (errno == EBADF) + { + poll_fds [i].revents |= MONO_POLLNVAL; + ready++; + } + break; } } - g_assert_not_reached (); + return ready; } static gint @@ -126,13 +139,9 @@ poll_event_wait (void (*callback) (gint fd, gint events, gpointer user_data), gp mono_gc_set_skip_thread (TRUE); -#if !defined(HOST_WIN32) - ready = poll (poll_fds, poll_fds_size, -1); -#else - ready = WSAPoll(poll_fds, poll_fds_size, -1); - if (ready == SOCKET_ERROR) - ready = -1; -#endif + MONO_ENTER_GC_SAFE; + ready = mono_poll (poll_fds, poll_fds_size, -1); + MONO_EXIT_GC_SAFE; mono_gc_set_skip_thread (FALSE); @@ -150,34 +159,31 @@ poll_event_wait (void (*callback) (gint fd, gint events, gpointer user_data), gp * ENOMEM: we're doomed anyway * */ -#if !defined(HOST_WIN32) switch (errno) -#else - switch (WSAGetLastError ()) -#endif { -#if !defined(HOST_WIN32) case EINTR: -#else - case WSAEINTR: -#endif { mono_thread_internal_check_for_interruption_critical (mono_thread_internal_current ()); ready = 0; break; } + case EBADF: + { + ready = poll_mark_bad_fds (poll_fds, poll_fds_size); + break; + } default: -#if !defined(HOST_WIN32) g_error ("poll_event_wait: mono_poll () failed, error (%d) %s", errno, g_strerror (errno)); -#else - g_error ("poll_event_wait: mono_poll () failed, error (%d)\n", WSAGetLastError ()); -#endif break; } } if (ready == -1) return -1; + if (ready == 0) + return 0; + + g_assert (ready > 0); for (i = 0; i < poll_fds_size; ++i) { gint fd, events = 0; @@ -188,10 +194,12 @@ poll_event_wait (void (*callback) (gint fd, gint events, gpointer user_data), gp continue; fd = poll_fds [i].fd; - if (poll_fds [i].revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL)) + if (poll_fds [i].revents & (MONO_POLLIN | MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)) events |= EVENT_IN; - if (poll_fds [i].revents & (POLLOUT | POLLERR | POLLHUP | POLLNVAL)) + if (poll_fds [i].revents & (MONO_POLLOUT | MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)) events |= EVENT_OUT; + if (poll_fds [i].revents & (MONO_POLLERR | MONO_POLLHUP | MONO_POLLNVAL)) + events |= EVENT_ERR; callback (fd, events, user_data); @@ -204,7 +212,6 @@ poll_event_wait (void (*callback) (gint fd, gint events, gpointer user_data), gp static ThreadPoolIOBackend backend_poll = { .init = poll_init, - .cleanup = poll_cleanup, .register_fd = poll_register_fd, .remove_fd = poll_remove_fd, .event_wait = poll_event_wait,