X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fthreadpool-ms-io-kqueue.c;h=4422b668e8f61c7c2d2a630e1b1cb702dfb5fd56;hb=20c72671c19e43952c3713660f350642e1f392d1;hp=f6afe7f71a8d603f67acb767f870331a4ade7375;hpb=81a9fcc9c7c0f9adc6d22ea7720868efe009223e;p=mono.git diff --git a/mono/metadata/threadpool-ms-io-kqueue.c b/mono/metadata/threadpool-ms-io-kqueue.c index f6afe7f71a8..4422b668e8f 100644 --- a/mono/metadata/threadpool-ms-io-kqueue.c +++ b/mono/metadata/threadpool-ms-io-kqueue.c @@ -15,20 +15,25 @@ static gint kqueue_fd; static struct kevent *kqueue_events; -static gboolean -kqueue_init (gint wakeup_pipe_fd) +static gint +KQUEUE_INIT_FD (gint fd, gint events, gint flags) { struct kevent event; + EV_SET (&event, fd, events, flags, 0, 0, 0); + return kevent (kqueue_fd, &event, 1, NULL, 0, NULL); +} +static gboolean +kqueue_init (gint wakeup_pipe_fd) +{ kqueue_fd = kqueue (); if (kqueue_fd == -1) { - g_warning ("kqueue_init: kqueue () failed, error (%d) %s", errno, g_strerror (errno)); + g_error ("kqueue_init: kqueue () failed, error (%d) %s", errno, g_strerror (errno)); return FALSE; } - EV_SET (&event, wakeup_pipe_fd, EVFILT_READ, EV_ADD | EV_ENABLE, 0, 0, 0); - if (kevent (kqueue_fd, &event, 1, NULL, 0, NULL) == -1) { - g_warning ("kqueue_init: kevent () failed, error (%d) %s", errno, g_strerror (errno)); + if (KQUEUE_INIT_FD (wakeup_pipe_fd, EVFILT_READ, EV_ADD | EV_ENABLE) == -1) { + g_error ("kqueue_init: kevent () failed, error (%d) %s", errno, g_strerror (errno)); close (kqueue_fd); return FALSE; } @@ -39,107 +44,84 @@ kqueue_init (gint wakeup_pipe_fd) } static void -kqueue_cleanup (void) +kqueue_register_fd (gint fd, gint events, gboolean is_new) { - g_free (kqueue_events); - close (kqueue_fd); + if (events & EVENT_IN) { + if (KQUEUE_INIT_FD (fd, EVFILT_READ, EV_ADD | EV_ENABLE) == -1) + g_error ("kqueue_register_fd: kevent(read,enable) failed, error (%d) %s", errno, g_strerror (errno)); + } else { + if (KQUEUE_INIT_FD (fd, EVFILT_READ, EV_ADD | EV_DISABLE) == -1) + g_error ("kqueue_register_fd: kevent(read,disable) failed, error (%d) %s", errno, g_strerror (errno)); + } + if (events & EVENT_OUT) { + if (KQUEUE_INIT_FD (fd, EVFILT_WRITE, EV_ADD | EV_ENABLE) == -1) + g_error ("kqueue_register_fd: kevent(write,enable) failed, error (%d) %s", errno, g_strerror (errno)); + } else { + if (KQUEUE_INIT_FD (fd, EVFILT_WRITE, EV_ADD | EV_DISABLE) == -1) + g_error ("kqueue_register_fd: kevent(write,disable) failed, error (%d) %s", errno, g_strerror (errno)); + } } static void -kqueue_update_add (ThreadPoolIOUpdate *update) +kqueue_remove_fd (gint fd) { - struct kevent event; - - if ((update->events & MONO_POLLIN) != 0) - EV_SET (&event, update->fd, EVFILT_READ, EV_ADD | EV_ENABLE | EV_ONESHOT, 0, 0, 0); - if ((update->events & MONO_POLLOUT) != 0) - EV_SET (&event, update->fd, EVFILT_WRITE, EV_ADD | EV_ENABLE | EV_ONESHOT, 0, 0, 0); - - if (kevent (kqueue_fd, &event, 1, NULL, 0, NULL) == -1) - g_warning ("kqueue_update_add: kevent(update) failed, error (%d) %s", errno, g_strerror (errno)); + /* FIXME: a race between closing and adding operation in the Socket managed code trigger a ENOENT error */ + if (KQUEUE_INIT_FD (fd, EVFILT_READ, EV_DELETE) == -1) + g_error ("kqueue_register_fd: kevent(read,delete) failed, error (%d) %s", errno, g_strerror (errno)); + if (KQUEUE_INIT_FD (fd, EVFILT_WRITE, EV_DELETE) == -1) + g_error ("kqueue_register_fd: kevent(write,delete) failed, error (%d) %s", errno, g_strerror (errno)); } static gint -kqueue_event_wait (void) +kqueue_event_wait (void (*callback) (gint fd, gint events, gpointer user_data), gpointer user_data) { - gint ready; + gint i, ready; + + memset (kqueue_events, 0, sizeof (struct kevent) * KQUEUE_NEVENTS); + mono_gc_set_skip_thread (TRUE); + + MONO_ENTER_GC_SAFE; ready = kevent (kqueue_fd, NULL, 0, kqueue_events, KQUEUE_NEVENTS, NULL); + MONO_EXIT_GC_SAFE; + + mono_gc_set_skip_thread (FALSE); + if (ready == -1) { switch (errno) { case EINTR: - check_for_interruption_critical (); + mono_thread_internal_check_for_interruption_critical (mono_thread_internal_current ()); ready = 0; break; default: - g_warning ("kqueue_event_wait: kevent () failed, error (%d) %s", errno, g_strerror (errno)); + g_error ("kqueue_event_wait: kevent () failed, error (%d) %s", errno, g_strerror (errno)); break; } } - return ready; -} - -static inline gint -kqueue_event_fd_at (guint i) -{ - return kqueue_events [i].ident; -} + if (ready == -1) + return -1; -static gint -kqueue_event_max (void) -{ - return KQUEUE_NEVENTS; -} - -static gboolean -kqueue_event_create_sockares_at (guint i, gint fd, MonoMList **list) -{ - struct kevent *kqueue_event; + for (i = 0; i < ready; ++i) { + gint fd, events = 0; - g_assert (list); + fd = kqueue_events [i].ident; + if (kqueue_events [i].filter == EVFILT_READ || (kqueue_events [i].flags & EV_ERROR) != 0) + events |= EVENT_IN; + if (kqueue_events [i].filter == EVFILT_WRITE || (kqueue_events [i].flags & EV_ERROR) != 0) + events |= EVENT_OUT; - kqueue_event = &kqueue_events [i]; - g_assert (kqueue_event); - - g_assert (fd == kqueue_event->ident); - - if (*list && (kqueue_event->filter == EVFILT_READ || (kqueue_event->flags & EV_ERROR) != 0)) { - MonoSocketAsyncResult *io_event = get_sockares_for_event (list, MONO_POLLIN); - if (io_event) - mono_threadpool_ms_enqueue_work_item (((MonoObject*) io_event)->vtable->domain, (MonoObject*) io_event); - } - if (*list && (kqueue_event->filter == EVFILT_WRITE || (kqueue_event->flags & EV_ERROR) != 0)) { - MonoSocketAsyncResult *io_event = get_sockares_for_event (list, MONO_POLLOUT); - if (io_event) - mono_threadpool_ms_enqueue_work_item (((MonoObject*) io_event)->vtable->domain, (MonoObject*) io_event); - } - - if (*list) { - gint events = get_events (*list); - if (kqueue_event->filter == EVFILT_READ && (events & MONO_POLLIN) != 0) { - EV_SET (kqueue_event, fd, EVFILT_READ, EV_ADD | EV_ENABLE | EV_ONESHOT, 0, 0, 0); - if (kevent (kqueue_fd, kqueue_event, 1, NULL, 0, NULL) == -1) - g_warning ("kqueue_event_create_sockares_at: kevent (read) failed, error (%d) %s", errno, g_strerror (errno)); - } - if (kqueue_event->filter == EVFILT_WRITE && (events & MONO_POLLOUT) != 0) { - EV_SET (kqueue_event, fd, EVFILT_WRITE, EV_ADD | EV_ENABLE | EV_ONESHOT, 0, 0, 0); - if (kevent (kqueue_fd, kqueue_event, 1, NULL, 0, NULL) == -1) - g_warning ("kqueue_event_create_sockares_at: kevent (write) failed, error (%d) %s", errno, g_strerror (errno)); - } + callback (fd, events, user_data); } - return TRUE; + return 0; } static ThreadPoolIOBackend backend_kqueue = { .init = kqueue_init, - .cleanup = kqueue_cleanup, - .update_add = kqueue_update_add, + .register_fd = kqueue_register_fd, + .remove_fd = kqueue_remove_fd, .event_wait = kqueue_event_wait, - .event_max = kqueue_event_max, - .event_fd_at = kqueue_event_fd_at, - .event_create_sockares_at = kqueue_event_create_sockares_at, }; #endif