X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fthreadpool-ms-io-poll.c;h=3d32130d3b530cc14ad38ce04cffaf5258ac28cf;hb=e90eb269935e8974e24342289d4088a9b200a201;hp=a02ceea4c50411148fc47ec79dd5d38b7a449c9c;hpb=ffa76054a9c072500a28392006ecac6cb4228be5;p=mono.git diff --git a/mono/metadata/threadpool-ms-io-poll.c b/mono/metadata/threadpool-ms-io-poll.c index a02ceea4c50..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; @@ -35,76 +16,117 @@ POLL_INIT_FD (mono_pollfd *poll_fd, gint fd, gint events) static gboolean poll_init (gint wakeup_pipe_fd) { - gint i; + g_assert (wakeup_pipe_fd >= 0); - poll_fds_size = wakeup_pipe_fd + 1; + poll_fds_size = 1; poll_fds_capacity = 64; - while (wakeup_pipe_fd >= poll_fds_capacity) - poll_fds_capacity *= 4; - poll_fds = g_new0 (mono_pollfd, poll_fds_capacity); - for (i = 0; i < wakeup_pipe_fd; ++i) - POLL_INIT_FD (&poll_fds [i], -1, 0); - - POLL_INIT_FD (&poll_fds [wakeup_pipe_fd], 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) { gint i; - mono_pollfd *poll_fd; + gint poll_event; g_assert (fd >= 0); g_assert (poll_fds_size <= poll_fds_capacity); - if (fd >= poll_fds_capacity) { - do { - poll_fds_capacity *= 4; - } while (fd >= poll_fds_capacity); + g_assert ((events & ~(EVENT_IN | EVENT_OUT)) == 0); + + poll_event = 0; + if (events & EVENT_IN) + poll_event |= MONO_POLLIN; + if (events & EVENT_OUT) + poll_event |= MONO_POLLOUT; - poll_fds = g_renew (mono_pollfd, poll_fds, poll_fds_capacity); + for (i = 0; i < poll_fds_size; ++i) { + if (poll_fds [i].fd == fd) { + g_assert (!is_new); + POLL_INIT_FD (&poll_fds [i], fd, poll_event); + return; + } } - if (fd >= poll_fds_size) { - for (i = poll_fds_size; i <= fd; ++i) - POLL_INIT_FD (&poll_fds [i], -1, 0); + g_assert (is_new); - poll_fds_size = fd + 1; + for (i = 0; i < poll_fds_size; ++i) { + if (poll_fds [i].fd == -1) { + POLL_INIT_FD (&poll_fds [i], fd, poll_event); + return; + } } - poll_fd = &poll_fds [fd]; + poll_fds_size += 1; + + if (poll_fds_size > poll_fds_capacity) { + poll_fds_capacity *= 2; + g_assert (poll_fds_size <= poll_fds_capacity); - if (poll_fd->fd != -1) { - g_assert (poll_fd->fd == fd); - g_assert (!is_new); + poll_fds = (mono_pollfd *)g_renew (mono_pollfd, poll_fds, poll_fds_capacity); } - POLL_INIT_FD (poll_fd, fd, ((events & EVENT_IN) ? POLLIN : 0) | ((events & EVENT_OUT) ? POLLOUT : 0)); + POLL_INIT_FD (&poll_fds [poll_fds_size - 1], fd, poll_event); } static void poll_remove_fd (gint fd) { - mono_pollfd *poll_fd; + gint i; g_assert (fd >= 0); - g_assert (fd < poll_fds_size); - poll_fd = &poll_fds [fd]; + for (i = 0; i < poll_fds_size; ++i) { + if (poll_fds [i].fd == fd) { + POLL_INIT_FD (&poll_fds [i], -1, 0); + 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; - g_assert (poll_fd->fd == fd); - POLL_INIT_FD (poll_fd, -1, 0); + 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; + } + } + + return ready; } static gint @@ -117,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); @@ -141,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; @@ -179,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); @@ -195,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,