From 174a3a9a08ab964349d7f976f3c3025d21a2f2e8 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Thu, 21 Oct 2010 15:38:32 -0700 Subject: [PATCH] Upgrade libev to 4.00 --- deps/libev/Changes | 46 +++ deps/libev/Makefile.am | 2 +- deps/libev/configure.ac | 4 +- deps/libev/ev++.h | 29 +- deps/libev/ev.c | 517 +++++++++++++++---------- deps/libev/ev.h | 239 ++++++++---- deps/libev/ev.pod | 808 ++++++++++++++++++++++++++++------------ deps/libev/ev_epoll.c | 11 +- deps/libev/ev_kqueue.c | 22 +- deps/libev/ev_poll.c | 36 +- deps/libev/ev_port.c | 11 +- deps/libev/ev_select.c | 7 +- deps/libev/ev_vars.h | 8 +- deps/libev/event.c | 22 +- deps/libev/event.h | 12 +- deps/libev/libev.m4 | 9 +- 16 files changed, 1201 insertions(+), 582 deletions(-) diff --git a/deps/libev/Changes b/deps/libev/Changes index a9e0ac4a8d..06379c8ada 100644 --- a/deps/libev/Changes +++ b/deps/libev/Changes @@ -1,5 +1,51 @@ Revision history for libev, a high-performance and full-featured event loop. +TODO: include ev_xyz_start in each example? +TODO: section watcher states/lifetime +TODO: use enums //TODO: enum? + - "PORTING FROM LIBEV 3.X TO 4.X" (in ev.pod) is recommended reading. + - ev_embed_stop did not correctly stop the watcher (very good + testcase by Vladimir Timofeev). + - ev_run will now always update the current loop time - it errornously + didn't when idle watchers were active, causing timers not to fire. + - fix a bug where a timeout of zero caused the timer not to fire + in the libevent emulation (testcase by Péter Szabó). + - applied win32 fixes by Michael Lenaghan (also James Mansion). + - replace EV_MINIMAL by EV_FEATURES. + - prefer EPOLL_CTL_ADD over EPOLL_CTL_MOD in some more cases, as it + seems the former is *much* faster than the latter. + - reduce the number of spurious wake-ups with the ports backend. + - remove dependency on sys/queue.h on freebsd (patch by Vanilla Hsu). + - do async init within ev_async_start, not ev_async_set, which avoids + an API quirk where the set function must be called in the C++ API + even when there is nothing to set. + - add (undocumented) EV_ENABLE when adding events with kqueue, + this might help with OS X, which seems to need it despite documenting + not to need it (helpfully pointed out by Tilghman Lesher). + - do not use poll by default on freebsd, it's broken (what isn't + on freebsd...). + - configure now prepends -O3, not appends it, so one can still + override it. + - greatly expanded the portability section. + - disable poll backend on AIX, the poll header spams the namespace + and it's not worth working around dead platforms (reported + and analyzed by Aivars Kalvans). + - improve header file compatibility of the standalone eventfd code + in an obscure case. + - implement EV_AVOID_STDIO option. + - do not use sscanf to parse linux version number (smaller, faster, + no sscanf dependency). + - new EV_CHILD_ENABLE and EV_SIGNAL_ENABLE configurable settings. + - update libev.m4 HAVE_CLOCK_SYSCALL test for newer glibcs. + - add section on accept() problems to the manpage. + - rename EV_TIMEOUT to EV_TIMER. + - rename ev_loop_count/depth/verify. + - switch to two-digit minor version. + - work around an apparent gentoo compiler bug. + - define _DARWIN_UNLIMITED_SELECT. just so. + - use enum instead of #define for most constants. + - improve compatibility to older C++ compilers. + 3.9 Thu Dec 31 07:59:59 CET 2009 - signalfd is no longer used by default and has to be requested explicitly - this means that easy to catch bugs become hard to diff --git a/deps/libev/Makefile.am b/deps/libev/Makefile.am index 9a8239e42d..1b4f7e18d4 100644 --- a/deps/libev/Makefile.am +++ b/deps/libev/Makefile.am @@ -1,6 +1,6 @@ AUTOMAKE_OPTIONS = foreign no-dependencies -VERSION_INFO = 3:0 +VERSION_INFO = 4:0 EXTRA_DIST = LICENSE Changes libev.m4 autogen.sh \ ev_vars.h ev_wrap.h \ diff --git a/deps/libev/configure.ac b/deps/libev/configure.ac index 8bb910d726..5047de3f43 100644 --- a/deps/libev/configure.ac +++ b/deps/libev/configure.ac @@ -1,7 +1,7 @@ AC_INIT AC_CONFIG_SRCDIR([ev_epoll.c]) -AM_INIT_AUTOMAKE(libev,3.9) dnl also update ev.h! +AM_INIT_AUTOMAKE(libev,4.00) dnl also update ev.h! AC_CONFIG_HEADERS([config.h]) AM_MAINTAINER_MODE @@ -9,7 +9,7 @@ AC_PROG_INSTALL AC_PROG_LIBTOOL if test "x$GCC" = xyes ; then - CFLAGS="$CFLAGS -O3" + CFLAGS="-O3 $CFLAGS" fi m4_include([libev.m4]) diff --git a/deps/libev/ev++.h b/deps/libev/ev++.h index 73bcf32cc8..b764487fdf 100644 --- a/deps/libev/ev++.h +++ b/deps/libev/ev++.h @@ -1,7 +1,7 @@ /* * libev simple C++ wrapper classes * - * Copyright (c) 2007,2008 Marc Alexander Lehmann + * Copyright (c) 2007,2008,2010 Marc Alexander Lehmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- @@ -76,7 +76,7 @@ namespace ev { ASYNC = EV_ASYNC, EMBED = EV_EMBED, # undef ERROR // some systems stupidly #define ERROR - ERROR = EV_ERROR, + ERROR = EV_ERROR }; enum @@ -227,15 +227,15 @@ namespace ev { ev_unref (EV_AX); } -#if EV_MINIMAL < 2 - unsigned int count () const throw () +#if EV_FEATURE_API + unsigned int iteration () const throw () { - return ev_loop_count (EV_AX); + return ev_iteration (EV_AX); } unsigned int depth () const throw () { - return ev_loop_depth (EV_AX); + return ev_depth (EV_AX); } void set_io_collect_interval (tstamp interval) throw () @@ -415,6 +415,7 @@ namespace ev { #if EV_MULTIPLICITY EV_PX; + // loop set void set (EV_P) throw () { this->EV_A = EV_A; @@ -480,7 +481,7 @@ namespace ev { template static void method_noargs_thunk (EV_P_ ev_watcher *w, int revents) { - static_cast(w->data)->*method + (static_cast(w->data)->*method) (); } @@ -674,6 +675,7 @@ namespace ev { EV_END_WATCHER (periodic, periodic) #endif + #if EV_SIGNAL_ENABLE EV_BEGIN_WATCHER (sig, signal) void set (int signum) throw () { @@ -689,7 +691,9 @@ namespace ev { start (); } EV_END_WATCHER (sig, signal) + #endif + #if EV_CHILD_ENABLE EV_BEGIN_WATCHER (child, child) void set (int pid, int trace = 0) throw () { @@ -705,6 +709,7 @@ namespace ev { start (); } EV_END_WATCHER (child, child) + #endif #if EV_STAT_ENABLE EV_BEGIN_WATCHER (stat, stat) @@ -730,19 +735,23 @@ namespace ev { EV_END_WATCHER (stat, stat) #endif -#if EV_IDLE_ENABLE + #if EV_IDLE_ENABLE EV_BEGIN_WATCHER (idle, idle) void set () throw () { } EV_END_WATCHER (idle, idle) -#endif + #endif + #if EV_PREPARE_ENABLE EV_BEGIN_WATCHER (prepare, prepare) void set () throw () { } EV_END_WATCHER (prepare, prepare) + #endif + #if EV_CHECK_ENABLE EV_BEGIN_WATCHER (check, check) void set () throw () { } EV_END_WATCHER (check, check) + #endif #if EV_EMBED_ENABLE EV_BEGIN_WATCHER (embed, embed) @@ -775,8 +784,6 @@ namespace ev { #if EV_ASYNC_ENABLE EV_BEGIN_WATCHER (async, async) - void set () throw () { } - void send () throw () { ev_async_send (EV_A_ static_cast(this)); diff --git a/deps/libev/ev.c b/deps/libev/ev.c index ccd202b4ff..27274b46f9 100644 --- a/deps/libev/ev.c +++ b/deps/libev/ev.c @@ -1,7 +1,7 @@ /* * libev event processing core, watcher management * - * Copyright (c) 2007,2008,2009 Marc Alexander Lehmann + * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- @@ -79,76 +79,85 @@ extern "C" { # endif # endif -# ifndef EV_USE_NANOSLEEP -# if HAVE_NANOSLEEP -# define EV_USE_NANOSLEEP 1 -# else -# define EV_USE_NANOSLEEP 0 +# if HAVE_NANOSLEEP +# ifndef EV_USE_NANOSLEEP +# define EV_USE_NANOSLEEP EV_FEATURE_OS # endif +# else +# undef EV_USE_NANOSLEEP +# define EV_USE_NANOSLEEP 0 # endif -# ifndef EV_USE_SELECT -# if HAVE_SELECT && HAVE_SYS_SELECT_H -# define EV_USE_SELECT 1 -# else -# define EV_USE_SELECT 0 +# if HAVE_SELECT && HAVE_SYS_SELECT_H +# ifndef EV_USE_SELECT +# define EV_USE_SELECT EV_FEATURE_BACKENDS # endif +# else +# undef EV_USE_SELECT +# define EV_USE_SELECT 0 # endif -# ifndef EV_USE_POLL -# if HAVE_POLL && HAVE_POLL_H -# define EV_USE_POLL 1 -# else -# define EV_USE_POLL 0 +# if HAVE_POLL && HAVE_POLL_H +# ifndef EV_USE_POLL +# define EV_USE_POLL EV_FEATURE_BACKENDS # endif +# else +# undef EV_USE_POLL +# define EV_USE_POLL 0 # endif -# ifndef EV_USE_EPOLL -# if HAVE_EPOLL_CTL && HAVE_SYS_EPOLL_H -# define EV_USE_EPOLL 1 -# else -# define EV_USE_EPOLL 0 +# if HAVE_EPOLL_CTL && HAVE_SYS_EPOLL_H +# ifndef EV_USE_EPOLL +# define EV_USE_EPOLL EV_FEATURE_BACKENDS # endif +# else +# undef EV_USE_EPOLL +# define EV_USE_EPOLL 0 # endif -# ifndef EV_USE_KQUEUE -# if HAVE_KQUEUE && HAVE_SYS_EVENT_H && HAVE_SYS_QUEUE_H -# define EV_USE_KQUEUE 1 -# else -# define EV_USE_KQUEUE 0 +# if HAVE_KQUEUE && HAVE_SYS_EVENT_H +# ifndef EV_USE_KQUEUE +# define EV_USE_KQUEUE EV_FEATURE_BACKENDS # endif +# else +# undef EV_USE_KQUEUE +# define EV_USE_KQUEUE 0 # endif -# ifndef EV_USE_PORT -# if HAVE_PORT_H && HAVE_PORT_CREATE -# define EV_USE_PORT 1 -# else -# define EV_USE_PORT 0 +# if HAVE_PORT_H && HAVE_PORT_CREATE +# ifndef EV_USE_PORT +# define EV_USE_PORT EV_FEATURE_BACKENDS # endif +# else +# undef EV_USE_PORT +# define EV_USE_PORT 0 # endif -# ifndef EV_USE_INOTIFY -# if HAVE_INOTIFY_INIT && HAVE_SYS_INOTIFY_H -# define EV_USE_INOTIFY 1 -# else -# define EV_USE_INOTIFY 0 +# if HAVE_INOTIFY_INIT && HAVE_SYS_INOTIFY_H +# ifndef EV_USE_INOTIFY +# define EV_USE_INOTIFY EV_FEATURE_OS # endif +# else +# undef EV_USE_INOTIFY +# define EV_USE_INOTIFY 0 # endif -# ifndef EV_USE_SIGNALFD -# if HAVE_SIGNALFD && HAVE_SYS_SIGNALFD_H -# define EV_USE_SIGNALFD 1 -# else -# define EV_USE_SIGNALFD 0 +# if HAVE_SIGNALFD && HAVE_SYS_SIGNALFD_H +# ifndef EV_USE_SIGNALFD +# define EV_USE_SIGNALFD EV_FEATURE_OS # endif +# else +# undef EV_USE_SIGNALFD +# define EV_USE_SIGNALFD 0 # endif -# ifndef EV_USE_EVENTFD -# if HAVE_EVENTFD -# define EV_USE_EVENTFD 1 -# else -# define EV_USE_EVENTFD 0 +# if HAVE_EVENTFD +# ifndef EV_USE_EVENTFD +# define EV_USE_EVENTFD EV_FEATURE_OS # endif +# else +# undef EV_USE_EVENTFD +# define EV_USE_EVENTFD 0 # endif #endif @@ -165,6 +174,7 @@ extern "C" { #include #include #include +#include #include @@ -185,8 +195,17 @@ extern "C" { # ifndef EV_SELECT_IS_WINSOCKET # define EV_SELECT_IS_WINSOCKET 1 # endif +# undef EV_AVOID_STDIO #endif +/* OS X, in its infinite idiocy, actually HARDCODES + * a limit of 1024 into their select. Where people have brains, + * OS X engineers apparently have a vacuum. Or maybe they were + * ordered to have a vacuum, or they do anything for money. + * This might help. Or not. + */ +#define _DARWIN_UNLIMITED_SELECT 1 + /* this block tries to deduce configuration from header-defined symbols and defaults */ /* try to deduce the maximum number of signals on this platform */ @@ -207,18 +226,19 @@ extern "C" { #elif defined (MAX_SIG) # define EV_NSIG (MAX_SIG+1) #elif defined (SIGARRAYSIZE) -# define EV_NSIG SIGARRAYSIZE /* Assume ary[SIGARRAYSIZE] */ +# define EV_NSIG (SIGARRAYSIZE) /* Assume ary[SIGARRAYSIZE] */ #elif defined (_sys_nsig) # define EV_NSIG (_sys_nsig) /* Solaris 2.5 */ #else # error "unable to find value for NSIG, please report" -/* to make it compile regardless, just remove the above line */ +/* to make it compile regardless, just remove the above line, */ +/* but consider reporting it, too! :) */ # define EV_NSIG 65 #endif #ifndef EV_USE_CLOCK_SYSCALL # if __linux && __GLIBC__ >= 2 -# define EV_USE_CLOCK_SYSCALL 1 +# define EV_USE_CLOCK_SYSCALL EV_FEATURE_OS # else # define EV_USE_CLOCK_SYSCALL 0 # endif @@ -226,7 +246,7 @@ extern "C" { #ifndef EV_USE_MONOTONIC # if defined (_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 -# define EV_USE_MONOTONIC 1 +# define EV_USE_MONOTONIC EV_FEATURE_OS # else # define EV_USE_MONOTONIC 0 # endif @@ -238,27 +258,27 @@ extern "C" { #ifndef EV_USE_NANOSLEEP # if _POSIX_C_SOURCE >= 199309L -# define EV_USE_NANOSLEEP 1 +# define EV_USE_NANOSLEEP EV_FEATURE_OS # else # define EV_USE_NANOSLEEP 0 # endif #endif #ifndef EV_USE_SELECT -# define EV_USE_SELECT 1 +# define EV_USE_SELECT EV_FEATURE_BACKENDS #endif #ifndef EV_USE_POLL # ifdef _WIN32 # define EV_USE_POLL 0 # else -# define EV_USE_POLL 1 +# define EV_USE_POLL EV_FEATURE_BACKENDS # endif #endif #ifndef EV_USE_EPOLL # if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4)) -# define EV_USE_EPOLL 1 +# define EV_USE_EPOLL EV_FEATURE_BACKENDS # else # define EV_USE_EPOLL 0 # endif @@ -274,31 +294,23 @@ extern "C" { #ifndef EV_USE_INOTIFY # if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4)) -# define EV_USE_INOTIFY 1 +# define EV_USE_INOTIFY EV_FEATURE_OS # else # define EV_USE_INOTIFY 0 # endif #endif #ifndef EV_PID_HASHSIZE -# if EV_MINIMAL -# define EV_PID_HASHSIZE 1 -# else -# define EV_PID_HASHSIZE 16 -# endif +# define EV_PID_HASHSIZE EV_FEATURE_DATA ? 16 : 1 #endif #ifndef EV_INOTIFY_HASHSIZE -# if EV_MINIMAL -# define EV_INOTIFY_HASHSIZE 1 -# else -# define EV_INOTIFY_HASHSIZE 16 -# endif +# define EV_INOTIFY_HASHSIZE EV_FEATURE_DATA ? 16 : 1 #endif #ifndef EV_USE_EVENTFD # if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7)) -# define EV_USE_EVENTFD 1 +# define EV_USE_EVENTFD EV_FEATURE_OS # else # define EV_USE_EVENTFD 0 # endif @@ -306,7 +318,7 @@ extern "C" { #ifndef EV_USE_SIGNALFD # if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7)) -# define EV_USE_SIGNALFD 1 +# define EV_USE_SIGNALFD EV_FEATURE_OS # else # define EV_USE_SIGNALFD 0 # endif @@ -319,15 +331,15 @@ extern "C" { #endif #ifndef EV_VERIFY -# define EV_VERIFY !EV_MINIMAL +# define EV_VERIFY (EV_FEATURE_API ? 1 : 0) #endif #ifndef EV_USE_4HEAP -# define EV_USE_4HEAP !EV_MINIMAL +# define EV_USE_4HEAP EV_FEATURE_DATA #endif #ifndef EV_HEAP_CACHE_AT -# define EV_HEAP_CACHE_AT !EV_MINIMAL +# define EV_HEAP_CACHE_AT EV_FEATURE_DATA #endif /* on linux, we can use a (slow) syscall to avoid a dependency on pthread, */ @@ -346,6 +358,12 @@ extern "C" { /* this block fixes any misconfiguration where we know we run into trouble otherwise */ +#ifdef _AIX +/* AIX has a completely broken poll.h header */ +# undef EV_USE_POLL +# define EV_USE_POLL 0 +#endif + #ifndef CLOCK_MONOTONIC # undef EV_USE_MONOTONIC # define EV_USE_MONOTONIC 0 @@ -398,7 +416,7 @@ extern "C" { # ifdef __cplusplus extern "C" { # endif -int eventfd (unsigned int initval, int flags); +int (eventfd) (unsigned int initval, int flags); # ifdef __cplusplus } # endif @@ -432,11 +450,10 @@ struct signalfd_siginfo # endif #endif - /**/ #if EV_VERIFY >= 3 -# define EV_FREQUENT_CHECK ev_loop_verify (EV_A) +# define EV_FREQUENT_CHECK ev_verify (EV_A) #else # define EV_FREQUENT_CHECK do { } while (0) #endif @@ -454,6 +471,9 @@ struct signalfd_siginfo #define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */ #define MAX_BLOCKTIME 59.743 /* never wait longer than this time (to detect time jumps) */ +#define EV_TV_SET(tv,t) do { tv.tv_sec = (long)t; tv.tv_usec = (long)((t - tv.tv_sec) * 1e6); } while (0) +#define EV_TS_SET(ts,t) do { ts.tv_sec = (long)t; ts.tv_nsec = (long)((t - ts.tv_sec) * 1e9); } while (0) + #if __GNUC__ >= 4 # define expect(expr,value) __builtin_expect ((expr),(value)) # define noinline __attribute__ ((noinline)) @@ -469,10 +489,10 @@ struct signalfd_siginfo #define expect_true(expr) expect ((expr) != 0, 1) #define inline_size static inline -#if EV_MINIMAL -# define inline_speed static noinline -#else +#if EV_FEATURE_CODE # define inline_speed static inline +#else +# define inline_speed static noinline #endif #define NUMPRI (EV_MAXPRI - EV_MINPRI + 1) @@ -495,7 +515,7 @@ typedef ev_watcher_time *WT; #if EV_USE_REALTIME /* sig_atomic_t is used to avoid per-thread variables or locking but still */ -/* giving it a reasonably high chance of working on typical architetcures */ +/* giving it a reasonably high chance of working on typical architectures */ static EV_ATOMIC_T have_realtime; /* did clock_gettime (CLOCK_REALTIME) work? */ #endif @@ -507,7 +527,7 @@ static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? # define EV_FD_TO_WIN32_HANDLE(fd) _get_osfhandle (fd) #endif #ifndef EV_WIN32_HANDLE_TO_FD -# define EV_WIN32_HANDLE_TO_FD(handle) _open_osfhandle (fd, 0) +# define EV_WIN32_HANDLE_TO_FD(handle) _open_osfhandle (handle, 0) #endif #ifndef EV_WIN32_CLOSE_FD # define EV_WIN32_CLOSE_FD(fd) close (fd) @@ -519,6 +539,14 @@ static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? /*****************************************************************************/ +#if EV_AVOID_STDIO +static void noinline +ev_printerr (const char *msg) +{ + write (STDERR_FILENO, msg, strlen (msg)); +} +#endif + static void (*syserr_cb)(const char *msg); void @@ -537,7 +565,16 @@ ev_syserr (const char *msg) syserr_cb (msg); else { +#if EV_AVOID_STDIO + const char *err = strerror (errno); + + ev_printerr (msg); + ev_printerr (": "); + ev_printerr (err); + ev_printerr ("\n"); +#else perror (msg); +#endif abort (); } } @@ -545,8 +582,11 @@ ev_syserr (const char *msg) static void * ev_realloc_emul (void *ptr, long size) { +#if __GLIBC__ + return realloc (ptr, size); +#else /* some systems, notably openbsd and darwin, fail to properly - * implement realloc (x, 0) (as required by both ansi c-98 and + * implement realloc (x, 0) (as required by both ansi c-89 and * the single unix specification, so work around them here. */ @@ -555,6 +595,7 @@ ev_realloc_emul (void *ptr, long size) free (ptr); return 0; +#endif } static void *(*alloc)(void *ptr, long size) = ev_realloc_emul; @@ -572,7 +613,11 @@ ev_realloc (void *ptr, long size) if (!ptr && size) { +#if EV_AVOID_STDIO + ev_printerr ("libev: memory allocation failed, aborting.\n"); +#else fprintf (stderr, "libev: cannot allocate %ld bytes, aborting.", size); +#endif abort (); } @@ -664,7 +709,7 @@ typedef struct #endif -#if EV_MINIMAL < 2 +#if EV_FEATURE_API # define EV_RELEASE_CB if (expect_false (release_cb)) release_cb (EV_A) # define EV_ACQUIRE_CB if (expect_false (acquire_cb)) acquire_cb (EV_A) # define EV_INVOKE_PENDING invoke_cb (EV_A) @@ -674,7 +719,7 @@ typedef struct # define EV_INVOKE_PENDING ev_invoke_pending (EV_A) #endif -#define EVUNLOOP_RECURSE 0x80 +#define EVBREAK_RECURSE 0x80 /*****************************************************************************/ @@ -728,21 +773,17 @@ ev_sleep (ev_tstamp delay) #if EV_USE_NANOSLEEP struct timespec ts; - ts.tv_sec = (time_t)delay; - ts.tv_nsec = (long)((delay - (ev_tstamp)(ts.tv_sec)) * 1e9); - + EV_TS_SET (ts, delay); nanosleep (&ts, 0); #elif defined(_WIN32) Sleep ((unsigned long)(delay * 1e3)); #else struct timeval tv; - tv.tv_sec = (time_t)delay; - tv.tv_usec = (long)((delay - (ev_tstamp)(tv.tv_sec)) * 1e6); - /* here we rely on sys/time.h + sys/types.h + unistd.h providing select */ /* something not guaranteed by newer posix versions, but guaranteed */ /* by older ones */ + EV_TV_SET (tv, delay); select (0, 0, 0, 0, &tv); #endif } @@ -753,7 +794,7 @@ ev_sleep (ev_tstamp delay) #define MALLOC_ROUND 4096 /* prefer to allocate in chunks of this size, must be 2**n and >> 4 longs */ /* find a suitable new size for the given array, */ -/* hopefully by rounding to a ncie-to-malloc size */ +/* hopefully by rounding to a nice-to-malloc size */ inline_size int array_nextsize (int elem, int cur, int cnt) { @@ -859,7 +900,7 @@ queue_events (EV_P_ W *events, int eventcnt, int type) /*****************************************************************************/ inline_speed void -fd_event_nc (EV_P_ int fd, int revents) +fd_event_nocheck (EV_P_ int fd, int revents) { ANFD *anfd = anfds + fd; ev_io *w; @@ -881,14 +922,14 @@ fd_event (EV_P_ int fd, int revents) ANFD *anfd = anfds + fd; if (expect_true (!anfd->reify)) - fd_event_nc (EV_A_ fd, revents); + fd_event_nocheck (EV_A_ fd, revents); } void ev_feed_fd_event (EV_P_ int fd, int revents) { if (fd >= 0 && fd < anfdmax) - fd_event_nc (EV_A_ fd, revents); + fd_event_nocheck (EV_A_ fd, revents); } /* make sure the external fd watch events are in-sync */ @@ -904,13 +945,13 @@ fd_reify (EV_P) ANFD *anfd = anfds + fd; ev_io *w; - unsigned char events = 0; + unsigned char o_events = anfd->events; + unsigned char o_reify = anfd->reify; - for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next) - events |= (unsigned char)w->events; + anfd->reify = 0; #if EV_SELECT_IS_WINSOCKET - if (events) + if (o_reify & EV__IOFDSET) { unsigned long arg; anfd->handle = EV_FD_TO_WIN32_HANDLE (fd); @@ -918,16 +959,19 @@ fd_reify (EV_P) } #endif - { - unsigned char o_events = anfd->events; - unsigned char o_reify = anfd->reify; + /*if (expect_true (o_reify & EV_ANFD_REIFY)) probably a deoptimisation */ + { + anfd->events = 0; - anfd->reify = 0; - anfd->events = events; + for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next) + anfd->events |= (unsigned char)w->events; - if (o_events != events || o_reify & EV__IOFDSET) - backend_modify (EV_A_ fd, o_events, events); - } + if (o_events != anfd->events) + o_reify = EV__IOFDSET; /* actually |= */ + } + + if (o_reify & EV__IOFDSET) + backend_modify (EV_A_ fd, o_events, anfd->events); } fdchangecnt = 0; @@ -961,12 +1005,12 @@ fd_kill (EV_P_ int fd) } } -/* check whether the given fd is atcually valid, for error recovery */ +/* check whether the given fd is actually valid, for error recovery */ inline_size int fd_valid (int fd) { #ifdef _WIN32 - return _get_osfhandle (fd) != -1; + return EV_FD_TO_WIN32_HANDLE (fd) != -1; #else return fcntl (fd, F_GETFD) != -1; #endif @@ -1013,10 +1057,24 @@ fd_rearm_all (EV_P) } } +/* used to prepare libev internal fd's */ +/* this is not fork-safe */ +inline_speed void +fd_intern (int fd) +{ +#ifdef _WIN32 + unsigned long arg = 1; + ioctlsocket (EV_FD_TO_WIN32_HANDLE (fd), FIONBIO, &arg); +#else + fcntl (fd, F_SETFD, FD_CLOEXEC); + fcntl (fd, F_SETFL, O_NONBLOCK); +#endif +} + /*****************************************************************************/ /* - * the heap functions want a real array index. array index 0 uis guaranteed to not + * the heap functions want a real array index. array index 0 is guaranteed to not * be in-use at any time. the first heap entry is at array [HEAP0]. DHEAP gives * the branching factor of the d-tree. */ @@ -1174,26 +1232,14 @@ static ANSIG signals [EV_NSIG - 1]; /*****************************************************************************/ -/* used to prepare libev internal fd's */ -/* this is not fork-safe */ -inline_speed void -fd_intern (int fd) -{ -#ifdef _WIN32 - unsigned long arg = 1; - ioctlsocket (_get_osfhandle (fd), FIONBIO, &arg); -#else - fcntl (fd, F_SETFD, FD_CLOEXEC); - fcntl (fd, F_SETFL, O_NONBLOCK); -#endif -} +#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE static void noinline evpipe_init (EV_P) { if (!ev_is_active (&pipe_w)) { -#if EV_USE_EVENTFD +# if EV_USE_EVENTFD evfd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC); if (evfd < 0 && errno == EINVAL) evfd = eventfd (0, 0); @@ -1205,7 +1251,7 @@ evpipe_init (EV_P) ev_io_set (&pipe_w, evfd, EV_READ); } else -#endif +# endif { while (pipe (evpipe)) ev_syserr ("(libev) error creating signal/async pipe"); @@ -1226,6 +1272,7 @@ evpipe_write (EV_P_ EV_ATOMIC_T *flag) if (!*flag) { int old_errno = errno; /* save errno because write might clobber it */ + char dummy; *flag = 1; @@ -1237,7 +1284,12 @@ evpipe_write (EV_P_ EV_ATOMIC_T *flag) } else #endif - write (evpipe [1], &old_errno, 1); + /* win32 people keep sending patches that change this write() to send() */ + /* and then run away. but send() is wrong, it wants a socket handle on win32 */ + /* so when you think this write should be a send instead, please find out */ + /* where your send() is from - it's definitely not the microsoft send, and */ + /* tell me. thank you. */ + write (evpipe [1], &dummy, 1); errno = old_errno; } @@ -1260,6 +1312,7 @@ pipecb (EV_P_ ev_io *iow, int revents) #endif { char dummy; + /* see discussion in evpipe_write when you think this read should be recv in win32 */ read (evpipe [0], &dummy, 1); } @@ -1296,7 +1349,7 @@ ev_sighandler (int signum) EV_P = signals [signum - 1].loop; #endif -#if _WIN32 +#ifdef _WIN32 signal (signum, ev_sighandler); #endif @@ -1348,12 +1401,13 @@ sigfdcb (EV_P_ ev_io *iow, int revents) } #endif +#endif + /*****************************************************************************/ +#if EV_CHILD_ENABLE static WL childs [EV_PID_HASHSIZE]; -#ifndef _WIN32 - static ev_signal childev; #ifndef WIFCONTINUED @@ -1367,7 +1421,7 @@ child_reap (EV_P_ int chain, int pid, int status) ev_child *w; int traced = WIFSTOPPED (status) || WIFCONTINUED (status); - for (w = (ev_child *)childs [chain & (EV_PID_HASHSIZE - 1)]; w; w = (ev_child *)((WL)w)->next) + for (w = (ev_child *)childs [chain & ((EV_PID_HASHSIZE) - 1)]; w; w = (ev_child *)((WL)w)->next) { if ((w->pid == pid || !w->pid) && (!traced || (w->flags & 1))) @@ -1402,7 +1456,7 @@ childcb (EV_P_ ev_signal *sw, int revents) ev_feed_event (EV_A_ (W)sw, EV_SIGNAL); child_reap (EV_A_ pid, pid, status); - if (EV_PID_HASHSIZE > 1) + if ((EV_PID_HASHSIZE) > 1) child_reap (EV_A_ 0, pid, status); /* this might trigger a watcher twice, but feed_event catches that */ } @@ -1479,6 +1533,9 @@ ev_recommended_backends (void) flags &= ~EVBACKEND_KQUEUE; /* horribly broken, even for sockets */ flags &= ~EVBACKEND_POLL; /* poll is based on kqueue from 10.5 onwards */ #endif +#ifdef __FreeBSD__ + flags &= ~EVBACKEND_POLL; /* poll return value is unusable (http://forums.freebsd.org/archive/index.php/t-10270.html) */ +#endif return flags; } @@ -1501,15 +1558,15 @@ ev_backend (EV_P) return backend; } -#if EV_MINIMAL < 2 +#if EV_FEATURE_API unsigned int -ev_loop_count (EV_P) +ev_iteration (EV_P) { return loop_count; } unsigned int -ev_loop_depth (EV_P) +ev_depth (EV_P) { return loop_depth; } @@ -1591,7 +1648,7 @@ loop_init (EV_P_ unsigned int flags) mn_now = get_clock (); now_floor = mn_now; rtmn_diff = ev_rt_now - mn_now; -#if EV_MINIMAL < 2 +#if EV_FEATURE_API invoke_cb = ev_invoke_pending; #endif @@ -1631,8 +1688,10 @@ loop_init (EV_P_ unsigned int flags) ev_prepare_init (&pending_w, pendingcb); +#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE ev_init (&pipe_w, pipecb); ev_set_priority (&pipe_w, EV_MAXPRI); +#endif } } @@ -1760,9 +1819,11 @@ loop_fork (EV_P) EV_WIN32_CLOSE_FD (evpipe [1]); } +#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE evpipe_init (EV_A); /* now iterate over everything, in case we missed something */ pipecb (EV_A_ &pipe_w, EV_READ); +#endif } postfork = 0; @@ -1834,9 +1895,9 @@ array_verify (EV_P_ W *ws, int cnt) } #endif -#if EV_MINIMAL < 2 +#if EV_FEATURE_API void -ev_loop_verify (EV_P) +ev_verify (EV_P) { #if EV_VERIFY int i; @@ -1885,15 +1946,21 @@ ev_loop_verify (EV_P) array_verify (EV_A_ (W *)asyncs, asynccnt); #endif +#if EV_PREPARE_ENABLE assert (preparemax >= preparecnt); array_verify (EV_A_ (W *)prepares, preparecnt); +#endif +#if EV_CHECK_ENABLE assert (checkmax >= checkcnt); array_verify (EV_A_ (W *)checks, checkcnt); +#endif # if 0 - for (w = (ev_child *)childs [chain & (EV_PID_HASHSIZE - 1)]; w; w = (ev_child *)((WL)w)->next) +#if EV_CHILD_ENABLE + for (w = (ev_child *)childs [chain & ((EV_PID_HASHSIZE) - 1)]; w; w = (ev_child *)((WL)w)->next) for (signum = EV_NSIG; signum--; ) if (signals [signum].pending) +#endif # endif #endif } @@ -1919,7 +1986,7 @@ ev_default_loop (unsigned int flags) if (ev_backend (EV_A)) { -#ifndef _WIN32 +#if EV_CHILD_ENABLE ev_signal_init (&childev, childcb, SIGCHLD); ev_set_priority (&childev, EV_MAXPRI); ev_signal_start (EV_A_ &childev); @@ -1942,7 +2009,7 @@ ev_default_destroy (void) ev_default_loop_ptr = 0; -#ifndef _WIN32 +#if EV_CHILD_ENABLE ev_ref (EV_A); /* child watcher */ ev_signal_stop (EV_A_ &childev); #endif @@ -2058,7 +2125,7 @@ timers_reify (EV_P) } while (timercnt && ANHE_at (timers [HEAP0]) < mn_now); - feed_reverse_done (EV_A_ EV_TIMEOUT); + feed_reverse_done (EV_A_ EV_TIMER); } } @@ -2121,7 +2188,7 @@ periodics_reify (EV_P) } /* simply recalculate all periodics */ -/* TODO: maybe ensure that at leats one event happens when jumping forward? */ +/* TODO: maybe ensure that at least one event happens when jumping forward? */ static void noinline periodics_reschedule (EV_P) { @@ -2159,7 +2226,7 @@ timers_reschedule (EV_P_ ev_tstamp adjust) } /* fetch new monotonic and realtime times from the kernel */ -/* also detetc if there was a timejump, and act accordingly */ +/* also detect if there was a timejump, and act accordingly */ inline_speed void time_update (EV_P_ ev_tstamp max_block) { @@ -2227,22 +2294,22 @@ time_update (EV_P_ ev_tstamp max_block) } void -ev_loop (EV_P_ int flags) +ev_run (EV_P_ int flags) { -#if EV_MINIMAL < 2 +#if EV_FEATURE_API ++loop_depth; #endif - assert (("libev: ev_loop recursion during release detected", loop_done != EVUNLOOP_RECURSE)); + assert (("libev: ev_loop recursion during release detected", loop_done != EVBREAK_RECURSE)); - loop_done = EVUNLOOP_CANCEL; + loop_done = EVBREAK_CANCEL; EV_INVOKE_PENDING; /* in case we recurse, ensure ordering stays nice and clean */ do { #if EV_VERIFY >= 2 - ev_loop_verify (EV_A); + ev_verify (EV_A); #endif #ifndef _WIN32 @@ -2264,12 +2331,14 @@ ev_loop (EV_P_ int flags) } #endif +#if EV_PREPARE_ENABLE /* queue prepare watchers (and execute them) */ if (expect_false (preparecnt)) { queue_events (EV_A_ (W *)prepares, preparecnt, EV_PREPARE); EV_INVOKE_PENDING; } +#endif if (expect_false (loop_done)) break; @@ -2286,14 +2355,14 @@ ev_loop (EV_P_ int flags) ev_tstamp waittime = 0.; ev_tstamp sleeptime = 0.; - if (expect_true (!(flags & EVLOOP_NONBLOCK || idleall || !activecnt))) - { - /* remember old timestamp for io_blocktime calculation */ - ev_tstamp prev_mn_now = mn_now; + /* remember old timestamp for io_blocktime calculation */ + ev_tstamp prev_mn_now = mn_now; - /* update time to cancel out callback processing overhead */ - time_update (EV_A_ 1e100); + /* update time to cancel out callback processing overhead */ + time_update (EV_A_ 1e100); + if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt))) + { waittime = MAX_BLOCKTIME; if (timercnt) @@ -2330,12 +2399,12 @@ ev_loop (EV_P_ int flags) } } -#if EV_MINIMAL < 2 +#if EV_FEATURE_API ++loop_count; #endif - assert ((loop_done = EVUNLOOP_RECURSE, 1)); /* assert for side effect */ + assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */ backend_poll (EV_A_ waittime); - assert ((loop_done = EVUNLOOP_CANCEL, 1)); /* assert for side effect */ + assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */ /* update ev_rt_now, do magic */ time_update (EV_A_ waittime + sleeptime); @@ -2352,28 +2421,30 @@ ev_loop (EV_P_ int flags) idle_reify (EV_A); #endif +#if EV_CHECK_ENABLE /* queue check watchers, to be executed first */ if (expect_false (checkcnt)) queue_events (EV_A_ (W *)checks, checkcnt, EV_CHECK); +#endif EV_INVOKE_PENDING; } while (expect_true ( activecnt && !loop_done - && !(flags & (EVLOOP_ONESHOT | EVLOOP_NONBLOCK)) + && !(flags & (EVRUN_ONCE | EVRUN_NOWAIT)) )); - if (loop_done == EVUNLOOP_ONE) - loop_done = EVUNLOOP_CANCEL; + if (loop_done == EVBREAK_ONE) + loop_done = EVBREAK_CANCEL; -#if EV_MINIMAL < 2 +#if EV_FEATURE_API --loop_depth; #endif } void -ev_unloop (EV_P_ int how) +ev_break (EV_P_ int how) { loop_done = how; } @@ -2503,7 +2574,7 @@ ev_io_start (EV_P_ ev_io *w) return; assert (("libev: ev_io_start called with negative fd", fd >= 0)); - assert (("libev: ev_io start called with illegal event mask", !(w->events & ~(EV__IOFDSET | EV_READ | EV_WRITE)))); + assert (("libev: ev_io_start called with illegal event mask", !(w->events & ~(EV__IOFDSET | EV_READ | EV_WRITE)))); EV_FREQUENT_CHECK; @@ -2531,7 +2602,7 @@ ev_io_stop (EV_P_ ev_io *w) wlist_del (&anfds[w->fd].head, (WL)w); ev_stop (EV_A_ (W)w); - fd_change (EV_A_ w->fd, 1); + fd_change (EV_A_ w->fd, EV_ANFD_REIFY); EV_FREQUENT_CHECK; } @@ -2583,11 +2654,11 @@ ev_timer_stop (EV_P_ ev_timer *w) } } - EV_FREQUENT_CHECK; - ev_at (w) -= mn_now; ev_stop (EV_A_ (W)w); + + EV_FREQUENT_CHECK; } void noinline @@ -2676,9 +2747,9 @@ ev_periodic_stop (EV_P_ ev_periodic *w) } } - EV_FREQUENT_CHECK; - ev_stop (EV_A_ (W)w); + + EV_FREQUENT_CHECK; } void noinline @@ -2694,6 +2765,8 @@ ev_periodic_again (EV_P_ ev_periodic *w) # define SA_RESTART 0 #endif +#if EV_SIGNAL_ENABLE + void noinline ev_signal_start (EV_P_ ev_signal *w) { @@ -2749,7 +2822,7 @@ ev_signal_start (EV_P_ ev_signal *w) if (sigfd < 0) /*TODO*/ # endif { -# if _WIN32 +# ifdef _WIN32 evpipe_init (EV_A); signal (w->signum, ev_sighandler); @@ -2809,6 +2882,10 @@ ev_signal_stop (EV_P_ ev_signal *w) EV_FREQUENT_CHECK; } +#endif + +#if EV_CHILD_ENABLE + void ev_child_start (EV_P_ ev_child *w) { @@ -2821,7 +2898,7 @@ ev_child_start (EV_P_ ev_child *w) EV_FREQUENT_CHECK; ev_start (EV_A_ (W)w, 1); - wlist_add (&childs [w->pid & (EV_PID_HASHSIZE - 1)], (WL)w); + wlist_add (&childs [w->pid & ((EV_PID_HASHSIZE) - 1)], (WL)w); EV_FREQUENT_CHECK; } @@ -2835,12 +2912,14 @@ ev_child_stop (EV_P_ ev_child *w) EV_FREQUENT_CHECK; - wlist_del (&childs [w->pid & (EV_PID_HASHSIZE - 1)], (WL)w); + wlist_del (&childs [w->pid & ((EV_PID_HASHSIZE) - 1)], (WL)w); ev_stop (EV_A_ (W)w); EV_FREQUENT_CHECK; } +#endif + #if EV_STAT_ENABLE # ifdef _WIN32 @@ -2855,7 +2934,9 @@ ev_child_stop (EV_P_ ev_child *w) static void noinline stat_timer_cb (EV_P_ ev_timer *w_, int revents); #if EV_USE_INOTIFY -# define EV_INOTIFY_BUFSIZE 8192 + +/* the * 2 is to allow for alignment padding, which for some reason is >> 8 */ +# define EV_INOTIFY_BUFSIZE (sizeof (struct inotify_event) * 2 + NAME_MAX) static void noinline infy_add (EV_P_ ev_stat *w) @@ -2914,7 +2995,7 @@ infy_add (EV_P_ ev_stat *w) } if (w->wd >= 0) - wlist_add (&fs_hash [w->wd & (EV_INOTIFY_HASHSIZE - 1)].head, (WL)w); + wlist_add (&fs_hash [w->wd & ((EV_INOTIFY_HASHSIZE) - 1)].head, (WL)w); /* now re-arm timer, if required */ if (ev_is_active (&w->timer)) ev_ref (EV_A); @@ -2932,7 +3013,7 @@ infy_del (EV_P_ ev_stat *w) return; w->wd = -2; - slot = wd & (EV_INOTIFY_HASHSIZE - 1); + slot = wd & ((EV_INOTIFY_HASHSIZE) - 1); wlist_del (&fs_hash [slot].head, (WL)w); /* remove this watcher, if others are watching it, they will rearm */ @@ -2944,13 +3025,13 @@ infy_wd (EV_P_ int slot, int wd, struct inotify_event *ev) { if (slot < 0) /* overflow, need to check for all hash slots */ - for (slot = 0; slot < EV_INOTIFY_HASHSIZE; ++slot) + for (slot = 0; slot < (EV_INOTIFY_HASHSIZE); ++slot) infy_wd (EV_A_ slot, wd, ev); else { WL w_; - for (w_ = fs_hash [slot & (EV_INOTIFY_HASHSIZE - 1)].head; w_; ) + for (w_ = fs_hash [slot & ((EV_INOTIFY_HASHSIZE) - 1)].head; w_; ) { ev_stat *w = (ev_stat *)w_; w_ = w_->next; /* lets us remove this watcher and all before it */ @@ -2959,7 +3040,7 @@ infy_wd (EV_P_ int slot, int wd, struct inotify_event *ev) { if (ev->mask & (IN_IGNORED | IN_UNMOUNT | IN_DELETE_SELF)) { - wlist_del (&fs_hash [slot & (EV_INOTIFY_HASHSIZE - 1)].head, (WL)w); + wlist_del (&fs_hash [slot & ((EV_INOTIFY_HASHSIZE) - 1)].head, (WL)w); w->wd = -1; infy_add (EV_A_ w); /* re-add, no matter what */ } @@ -2974,32 +3055,56 @@ static void infy_cb (EV_P_ ev_io *w, int revents) { char buf [EV_INOTIFY_BUFSIZE]; - struct inotify_event *ev = (struct inotify_event *)buf; int ofs; int len = read (fs_fd, buf, sizeof (buf)); - for (ofs = 0; ofs < len; ofs += sizeof (struct inotify_event) + ev->len) - infy_wd (EV_A_ ev->wd, ev->wd, ev); + for (ofs = 0; ofs < len; ) + { + struct inotify_event *ev = (struct inotify_event *)(buf + ofs); + infy_wd (EV_A_ ev->wd, ev->wd, ev); + ofs += sizeof (struct inotify_event) + ev->len; + } } -inline_size void -check_2625 (EV_P) +inline_size unsigned int +ev_linux_version (void) { - /* kernels < 2.6.25 are borked - * http://www.ussg.indiana.edu/hypermail/linux/kernel/0711.3/1208.html - */ struct utsname buf; - int major, minor, micro; + unsigned int v; + int i; + char *p = buf.release; if (uname (&buf)) - return; + return 0; - if (sscanf (buf.release, "%d.%d.%d", &major, &minor, µ) != 3) - return; + for (i = 3+1; --i; ) + { + unsigned int c = 0; + + for (;;) + { + if (*p >= '0' && *p <= '9') + c = c * 10 + *p++ - '0'; + else + { + p += *p == '.'; + break; + } + } + + v = (v << 8) | c; + } + + return v; +} - if (major < 2 - || (major == 2 && minor < 6) - || (major == 2 && minor == 6 && micro < 25)) +inline_size void +ev_check_2625 (EV_P) +{ + /* kernels < 2.6.25 are borked + * http://www.ussg.indiana.edu/hypermail/linux/kernel/0711.3/1208.html + */ + if (ev_linux_version () < 0x020619) return; fs_2625 = 1; @@ -3024,7 +3129,7 @@ infy_init (EV_P) fs_fd = -1; - check_2625 (EV_A); + ev_check_2625 (EV_A); fs_fd = infy_newfd (); @@ -3059,7 +3164,7 @@ infy_fork (EV_P) ev_unref (EV_A); } - for (slot = 0; slot < EV_INOTIFY_HASHSIZE; ++slot) + for (slot = 0; slot < (EV_INOTIFY_HASHSIZE); ++slot) { WL w_ = fs_hash [slot].head; fs_hash [slot].head = 0; @@ -3244,6 +3349,7 @@ ev_idle_stop (EV_P_ ev_idle *w) } #endif +#if EV_PREPARE_ENABLE void ev_prepare_start (EV_P_ ev_prepare *w) { @@ -3279,7 +3385,9 @@ ev_prepare_stop (EV_P_ ev_prepare *w) EV_FREQUENT_CHECK; } +#endif +#if EV_CHECK_ENABLE void ev_check_start (EV_P_ ev_check *w) { @@ -3315,12 +3423,13 @@ ev_check_stop (EV_P_ ev_check *w) EV_FREQUENT_CHECK; } +#endif #if EV_EMBED_ENABLE void noinline ev_embed_sweep (EV_P_ ev_embed *w) { - ev_loop (w->other, EVLOOP_NONBLOCK); + ev_run (w->other, EVRUN_NOWAIT); } static void @@ -3331,7 +3440,7 @@ embed_io_cb (EV_P_ ev_io *io, int revents) if (ev_cb (w)) ev_feed_event (EV_A_ (W)w, EV_EMBED); else - ev_loop (w->other, EVLOOP_NONBLOCK); + ev_run (w->other, EVRUN_NOWAIT); } static void @@ -3345,7 +3454,7 @@ embed_prepare_cb (EV_P_ ev_prepare *prepare, int revents) while (fdchangecnt) { fd_reify (EV_A); - ev_loop (EV_A_ EVLOOP_NONBLOCK); + ev_run (EV_A_ EVRUN_NOWAIT); } } } @@ -3361,7 +3470,7 @@ embed_fork_cb (EV_P_ ev_fork *fork_w, int revents) EV_P = w->other; ev_loop_fork (EV_A); - ev_loop (EV_A_ EVLOOP_NONBLOCK); + ev_run (EV_A_ EVRUN_NOWAIT); } ev_embed_start (EV_A_ w); @@ -3419,6 +3528,8 @@ ev_embed_stop (EV_P_ ev_embed *w) ev_prepare_stop (EV_A_ &w->prepare); ev_fork_stop (EV_A_ &w->fork); + ev_stop (EV_A_ (W)w); + EV_FREQUENT_CHECK; } #endif @@ -3468,6 +3579,8 @@ ev_async_start (EV_P_ ev_async *w) if (expect_false (ev_is_active (w))) return; + w->sent = 0; + evpipe_init (EV_A); EV_FREQUENT_CHECK; @@ -3554,7 +3667,7 @@ ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, vo if (expect_false (!once)) { - cb (EV_ERROR | EV_READ | EV_WRITE | EV_TIMEOUT, arg); + cb (EV_ERROR | EV_READ | EV_WRITE | EV_TIMER, arg); return; } @@ -3651,17 +3764,22 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) cb (EV_A_ EV_ASYNC, asyncs [i]); #endif +#if EV_PREPARE_ENABLE if (types & EV_PREPARE) for (i = preparecnt; i--; ) -#if EV_EMBED_ENABLE +# if EV_EMBED_ENABLE if (ev_cb (prepares [i]) != embed_prepare_cb) -#endif +# endif cb (EV_A_ EV_PREPARE, prepares [i]); +#endif +#if EV_CHECK_ENABLE if (types & EV_CHECK) for (i = checkcnt; i--; ) cb (EV_A_ EV_CHECK, checks [i]); +#endif +#if EV_SIGNAL_ENABLE if (types & EV_SIGNAL) for (i = 0; i < EV_NSIG - 1; ++i) for (wl = signals [i].head; wl; ) @@ -3670,15 +3788,18 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) cb (EV_A_ EV_SIGNAL, wl); wl = wn; } +#endif +#if EV_CHILD_ENABLE if (types & EV_CHILD) - for (i = EV_PID_HASHSIZE; i--; ) + for (i = (EV_PID_HASHSIZE); i--; ) for (wl = childs [i]; wl; ) { wn = wl->next; cb (EV_A_ EV_CHILD, wl); wl = wn; } +#endif /* EV_STAT 0x00001000 /* stat data changed */ /* EV_EMBED 0x00010000 /* embedded event loop needs sweep */ } diff --git a/deps/libev/ev.h b/deps/libev/ev.h index c7c44ff70e..96e735871a 100644 --- a/deps/libev/ev.h +++ b/deps/libev/ev.h @@ -1,7 +1,7 @@ /* * libev native API header * - * Copyright (c) 2007,2008,2009 Marc Alexander Lehmann + * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- @@ -44,55 +44,101 @@ extern "C" { #endif -typedef double ev_tstamp; +/*****************************************************************************/ + +/* pre-4.0 compatibility */ +#ifndef EV_COMPAT3 +# define EV_COMPAT3 1 +#endif + +#ifndef EV_FEATURES +# define EV_FEATURES 0x7f +#endif + +#define EV_FEATURE_CODE ((EV_FEATURES) & 1) +#define EV_FEATURE_DATA ((EV_FEATURES) & 2) +#define EV_FEATURE_CONFIG ((EV_FEATURES) & 4) +#define EV_FEATURE_API ((EV_FEATURES) & 8) +#define EV_FEATURE_WATCHERS ((EV_FEATURES) & 16) +#define EV_FEATURE_BACKENDS ((EV_FEATURES) & 32) +#define EV_FEATURE_OS ((EV_FEATURES) & 64) -/* these priorities are inclusive, higher priorities will be called earlier */ +/* these priorities are inclusive, higher priorities will be invoked earlier */ #ifndef EV_MINPRI -# define EV_MINPRI -2 +# define EV_MINPRI (EV_FEATURE_CONFIG ? -2 : 0) #endif #ifndef EV_MAXPRI -# define EV_MAXPRI +2 +# define EV_MAXPRI (EV_FEATURE_CONFIG ? +2 : 0) #endif #ifndef EV_MULTIPLICITY -# define EV_MULTIPLICITY 1 +# define EV_MULTIPLICITY EV_FEATURE_CONFIG #endif #ifndef EV_PERIODIC_ENABLE -# define EV_PERIODIC_ENABLE 1 +# define EV_PERIODIC_ENABLE EV_FEATURE_WATCHERS #endif #ifndef EV_STAT_ENABLE -# define EV_STAT_ENABLE 1 +# define EV_STAT_ENABLE EV_FEATURE_WATCHERS +#endif + +#ifndef EV_PREPARE_ENABLE +# define EV_PREPARE_ENABLE EV_FEATURE_WATCHERS +#endif + +#ifndef EV_CHECK_ENABLE +# define EV_CHECK_ENABLE EV_FEATURE_WATCHERS #endif #ifndef EV_IDLE_ENABLE -# define EV_IDLE_ENABLE 1 +# define EV_IDLE_ENABLE EV_FEATURE_WATCHERS #endif #ifndef EV_FORK_ENABLE -# define EV_FORK_ENABLE 1 +# define EV_FORK_ENABLE EV_FEATURE_WATCHERS #endif -#ifndef EV_EMBED_ENABLE -# define EV_EMBED_ENABLE 1 +#ifndef EV_SIGNAL_ENABLE +# define EV_SIGNAL_ENABLE EV_FEATURE_WATCHERS +#endif + +#ifndef EV_CHILD_ENABLE +# ifdef _WIN32 +# define EV_CHILD_ENABLE 0 +# else +# define EV_CHILD_ENABLE EV_FEATURE_WATCHERS +#endif #endif #ifndef EV_ASYNC_ENABLE -# define EV_ASYNC_ENABLE 1 +# define EV_ASYNC_ENABLE EV_FEATURE_WATCHERS +#endif + +#ifndef EV_EMBED_ENABLE +# define EV_EMBED_ENABLE EV_FEATURE_WATCHERS #endif #ifndef EV_WALK_ENABLE # define EV_WALK_ENABLE 0 /* not yet */ #endif +/*****************************************************************************/ + +#if EV_CHILD_ENABLE && !EV_SIGNAL_ENABLE +# undef EV_SIGNAL_ENABLE +# define EV_SIGNAL_ENABLE 1 +#endif + +/*****************************************************************************/ + +typedef double ev_tstamp; + #ifndef EV_ATOMIC_T # include # define EV_ATOMIC_T sig_atomic_t volatile #endif -/*****************************************************************************/ - #if EV_STAT_ENABLE # ifdef _WIN32 # include @@ -130,40 +176,43 @@ struct ev_loop; # define EV_INLINE static #endif +#ifndef EV_PROTOTYPES +# define EV_PROTOTYPES 1 +#endif + /*****************************************************************************/ +#define EV_VERSION_MAJOR 4 +#define EV_VERSION_MINOR 0 + /* eventmask, revents, events... */ -#define EV_UNDEF -1 /* guaranteed to be invalid */ -#define EV_NONE 0x00 /* no events */ -#define EV_READ 0x01 /* ev_io detected read will not block */ -#define EV_WRITE 0x02 /* ev_io detected write will not block */ -#define EV__IOFDSET 0x80 /* internal use only */ -#define EV_IO EV_READ /* alias for type-detection */ -#define EV_TIMEOUT 0x00000100 /* timer timed out */ -#define EV_TIMER EV_TIMEOUT /* alias for type-detection */ -#define EV_PERIODIC 0x00000200 /* periodic timer timed out */ -#define EV_SIGNAL 0x00000400 /* signal was received */ -#define EV_CHILD 0x00000800 /* child/pid had status change */ -#define EV_STAT 0x00001000 /* stat data changed */ -#define EV_IDLE 0x00002000 /* event loop is idling */ -#define EV_PREPARE 0x00004000 /* event loop about to poll */ -#define EV_CHECK 0x00008000 /* event loop finished poll */ -#define EV_EMBED 0x00010000 /* embedded event loop needs sweep */ -#define EV_FORK 0x00020000 /* event loop resumed in child */ -#define EV_ASYNC 0x00040000 /* async intra-loop signal */ -#define EV_CUSTOM 0x01000000 /* for use by user code */ -#define EV_ERROR 0x80000000 /* sent when an error occurs */ +enum { + EV_UNDEF = -1, /* guaranteed to be invalid */ + EV_NONE = 0x00, /* no events */ + EV_READ = 0x01, /* ev_io detected read will not block */ + EV_WRITE = 0x02, /* ev_io detected write will not block */ + EV__IOFDSET = 0x80, /* internal use only */ + EV_IO = EV_READ, /* alias for type-detection */ + EV_TIMER = 0x00000100, /* timer timed out */ + EV_TIMEOUT = EV_TIMER, /* pre 4.0 API compatibility */ + EV_PERIODIC = 0x00000200, /* periodic timer timed out */ + EV_SIGNAL = 0x00000400, /* signal was received */ + EV_CHILD = 0x00000800, /* child/pid had status change */ + EV_STAT = 0x00001000, /* stat data changed */ + EV_IDLE = 0x00002000, /* event loop is idling */ + EV_PREPARE = 0x00004000, /* event loop about to poll */ + EV_CHECK = 0x00008000, /* event loop finished poll */ + EV_EMBED = 0x00010000, /* embedded event loop needs sweep */ + EV_FORK = 0x00020000, /* event loop resumed in child */ + EV_ASYNC = 0x00040000, /* async intra-loop signal */ + EV_CUSTOM = 0x01000000, /* for use by user code */ + EV_ERROR = 0x80000000 /* sent when an error occurs */ +}; /* can be used to add custom fields to all watchers, while losing binary compatibility */ #ifndef EV_COMMON # define EV_COMMON void *data; #endif -#ifndef EV_PROTOTYPES -# define EV_PROTOTYPES 1 -#endif - -#define EV_VERSION_MAJOR 3 -#define EV_VERSION_MINOR 9 #ifndef EV_CB_DECLARE # define EV_CB_DECLARE(type) void (*cb)(EV_P_ struct type *w, int revents); @@ -172,6 +221,9 @@ struct ev_loop; # define EV_CB_INVOKE(watcher,revents) (watcher)->cb (EV_A_ (watcher), (revents)) #endif +/* not official, do not use */ +#define EV_CB(type,name) void name (EV_P_ struct ev_ ## type *w, int revents) + /* * struct member types: * private: you may look at them, but not change them, @@ -191,7 +243,7 @@ struct ev_loop; #if EV_MINPRI == EV_MAXPRI # define EV_DECL_PRIORITY -#else +#elif !defined (EV_DECL_PRIORITY) # define EV_DECL_PRIORITY int priority; #endif @@ -398,24 +450,31 @@ union ev_any_watcher #endif }; -/* bits for ev_default_loop and ev_loop_new */ -/* the default */ -#define EVFLAG_AUTO 0x00000000U /* not quite a mask */ -/* flag bits */ -#define EVFLAG_NOENV 0x01000000U /* do NOT consult environment */ -#define EVFLAG_FORKCHECK 0x02000000U /* check for a fork in each iteration */ -/* debugging/feature disable */ -#define EVFLAG_NOINOTIFY 0x00100000U /* do not attempt to use inotify */ -#define EVFLAG_NOSIGFD 0 /* compatibility to pre-3.9 */ -#define EVFLAG_SIGNALFD 0x00200000U /* attempt to use signalfd */ +/* flag bits for ev_default_loop and ev_loop_new */ +enum { + /* the default */ + EVFLAG_AUTO = 0x00000000U, /* not quite a mask */ + /* flag bits */ + EVFLAG_NOENV = 0x01000000U, /* do NOT consult environment */ + EVFLAG_FORKCHECK = 0x02000000U, /* check for a fork in each iteration */ + /* debugging/feature disable */ + EVFLAG_NOINOTIFY = 0x00100000U, /* do not attempt to use inotify */ +#if EV_COMPAT3 + EVFLAG_NOSIGFD = 0, /* compatibility to pre-3.9 */ +#endif + EVFLAG_SIGNALFD = 0x00200000U /* attempt to use signalfd */ +}; + /* method bits to be ored together */ -#define EVBACKEND_SELECT 0x00000001U /* about anywhere */ -#define EVBACKEND_POLL 0x00000002U /* !win */ -#define EVBACKEND_EPOLL 0x00000004U /* linux */ -#define EVBACKEND_KQUEUE 0x00000008U /* bsd */ -#define EVBACKEND_DEVPOLL 0x00000010U /* solaris 8 */ /* NYI */ -#define EVBACKEND_PORT 0x00000020U /* solaris 10 */ -#define EVBACKEND_ALL 0x0000003FU +enum { + EVBACKEND_SELECT = 0x00000001U, /* about anywhere */ + EVBACKEND_POLL = 0x00000002U, /* !win */ + EVBACKEND_EPOLL = 0x00000004U, /* linux */ + EVBACKEND_KQUEUE = 0x00000008U, /* bsd */ + EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /* NYI */ + EVBACKEND_PORT = 0x00000020U, /* solaris 10 */ + EVBACKEND_ALL = 0x0000003FU +}; #if EV_PROTOTYPES int ev_version_major (void); @@ -520,15 +579,22 @@ void ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)); #endif /* prototypes */ -#define EVLOOP_NONBLOCK 1 /* do not block/wait */ -#define EVLOOP_ONESHOT 2 /* block *once* only */ -#define EVUNLOOP_CANCEL 0 /* undo unloop */ -#define EVUNLOOP_ONE 1 /* unloop once */ -#define EVUNLOOP_ALL 2 /* unloop all loops */ +/* ev_run flags values */ +enum { + EVRUN_NOWAIT = 1, /* do not block/wait */ + EVRUN_ONCE = 2 /* block *once* only */ +}; + +/* ev_break how values */ +enum { + EVBREAK_CANCEL = 0, /* undo unloop */ + EVBREAK_ONE = 1, /* unloop once */ + EVBREAK_ALL = 2 /* unloop all loops */ +}; #if EV_PROTOTYPES -void ev_loop (EV_P_ int flags); -void ev_unloop (EV_P_ int how); /* set to 1 to break out of event loop, set to 2 to break out of all event loops */ +void ev_run (EV_P_ int flags); +void ev_break (EV_P_ int how); /* set to 1 to break out of event loop, set to 2 to break out of all event loops */ /* * ref/unref can be used to add or remove a refcount on the mainloop. every watcher @@ -544,10 +610,10 @@ void ev_unref (EV_P); */ void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg); -# if EV_MINIMAL < 2 -unsigned int ev_loop_count (EV_P); /* number of loop iterations */ -unsigned int ev_loop_depth (EV_P); /* #ev_loop enters - #ev_loop leaves */ -void ev_loop_verify (EV_P); /* abort if loop data corrupted */ +# if EV_FEATURE_API +unsigned int ev_iteration (EV_P); /* number of loop iterations */ +unsigned int ev_depth (EV_P); /* #ev_loop enters - #ev_loop leaves */ +void ev_verify (EV_P); /* abort if loop data corrupted */ void ev_set_io_collect_interval (EV_P_ ev_tstamp interval); /* sleep at least this time, default 0 */ void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval); /* sleep at least this time, default 0 */ @@ -590,7 +656,7 @@ void ev_resume (EV_P); #define ev_check_set(ev) /* nop, yes, this is a serious in-joke */ #define ev_embed_set(ev,other_) do { (ev)->other = (other_); } while (0) #define ev_fork_set(ev) /* nop, yes, this is a serious in-joke */ -#define ev_async_set(ev) do { (ev)->sent = 0; } while (0) +#define ev_async_set(ev) /* nop, yes, this is a serious in-joke */ #define ev_io_init(ev,cb,fd,events) do { ev_init ((ev), (cb)); ev_io_set ((ev),(fd),(events)); } while (0) #define ev_timer_init(ev,cb,after,repeat) do { ev_init ((ev), (cb)); ev_timer_set ((ev),(after),(repeat)); } while (0) @@ -615,7 +681,7 @@ void ev_resume (EV_P); # define ev_set_priority(ev,pri) ((ev), (pri)) #else # define ev_priority(ev) (+(((ev_watcher *)(void *)(ev))->priority)) -# define ev_set_priority(ev,pri) ( (ev_watcher *)(void *)(ev))->priority = (pri) +# define ev_set_priority(ev,pri) ( (ev_watcher *)(void *)(ev))->priority = (pri) #endif #define ev_periodic_at(ev) (+((ev_watcher_time *)(ev))->at) @@ -632,7 +698,9 @@ void ev_resume (EV_P); /* accepts any ev_watcher type */ void ev_feed_event (EV_P_ void *w, int revents); void ev_feed_fd_event (EV_P_ int fd, int revents); +#if EV_SIGNAL_ENABLE void ev_feed_signal_event (EV_P_ int signum); +#endif void ev_invoke (EV_P_ void *w, int revents); int ev_clear_pending (EV_P_ void *w); @@ -653,12 +721,16 @@ void ev_periodic_again (EV_P_ ev_periodic *w); #endif /* only supported in the default loop */ +#if EV_SIGNAL_ENABLE void ev_signal_start (EV_P_ ev_signal *w); void ev_signal_stop (EV_P_ ev_signal *w); +#endif /* only supported in the default loop */ +# if EV_CHILD_ENABLE void ev_child_start (EV_P_ ev_child *w); void ev_child_stop (EV_P_ ev_child *w); +# endif # if EV_STAT_ENABLE void ev_stat_start (EV_P_ ev_stat *w); @@ -671,11 +743,15 @@ void ev_idle_start (EV_P_ ev_idle *w); void ev_idle_stop (EV_P_ ev_idle *w); # endif +#if EV_PREPARE_ENABLE void ev_prepare_start (EV_P_ ev_prepare *w); void ev_prepare_stop (EV_P_ ev_prepare *w); +#endif +#if EV_CHECK_ENABLE void ev_check_start (EV_P_ ev_check *w); void ev_check_stop (EV_P_ ev_check *w); +#endif # if EV_FORK_ENABLE void ev_fork_start (EV_P_ ev_fork *w); @@ -695,6 +771,25 @@ void ev_async_stop (EV_P_ ev_async *w); void ev_async_send (EV_P_ ev_async *w); # endif +#if EV_COMPAT3 + #define EVLOOP_NONBLOCK EVRUN_NOWAIT + #define EVLOOP_ONESHOT EVRUN_ONCE + #define EVUNLOOP_CANCEL EVBREAK_CANCEL + #define EVUNLOOP_ONE EVBREAK_ONE + #define EVUNLOOP_ALL EVBREAK_ALL + #if EV_PROTOTYPES + EV_INLINE void ev_loop (EV_P_ int flags) { ev_run (EV_A_ flags); } + EV_INLINE void ev_unloop (EV_P_ int how ) { ev_break (EV_A_ how ); } + #if EV_FEATURE_API + EV_INLINE void ev_loop_count (EV_P) { ev_iteration (EV_A); } + EV_INLINE void ev_loop_depth (EV_P) { ev_depth (EV_A); } + EV_INLINE void ev_loop_verify (EV_P) { ev_verify (EV_A); } + #endif + #endif +#else + typedef struct ev_loop ev_loop; +#endif + #endif #ifdef __cplusplus diff --git a/deps/libev/ev.pod b/deps/libev/ev.pod index 0fe88810bd..ba192deaca 100644 --- a/deps/libev/ev.pod +++ b/deps/libev/ev.pod @@ -28,8 +28,8 @@ libev - a high performance full-featured event loop written in C // with its corresponding stop function. ev_io_stop (EV_A_ w); - // this causes all nested ev_loop's to stop iterating - ev_unloop (EV_A_ EVUNLOOP_ALL); + // this causes all nested ev_run's to stop iterating + ev_break (EV_A_ EVBREAK_ALL); } // another callback, this time for a time-out @@ -37,8 +37,8 @@ libev - a high performance full-featured event loop written in C timeout_cb (EV_P_ ev_timer *w, int revents) { puts ("timeout"); - // this causes the innermost ev_loop to stop iterating - ev_unloop (EV_A_ EVUNLOOP_ONE); + // this causes the innermost ev_run to stop iterating + ev_break (EV_A_ EVBREAK_ONE); } int @@ -58,7 +58,7 @@ libev - a high performance full-featured event loop written in C ev_timer_start (loop, &timeout_watcher); // now wait for events to arrive - ev_loop (loop, 0); + ev_run (loop, 0); // unloop was called, so exit return 0; @@ -77,7 +77,7 @@ libev, its usage and the rationale behind its design, it is not a tutorial on event-based programming, nor will it introduce event-based programming with libev. -Familarity with event based programming techniques in general is assumed +Familiarity with event based programming techniques in general is assumed throughout this document. =head1 ABOUT LIBEV @@ -126,13 +126,14 @@ this argument. =head2 TIME REPRESENTATION Libev represents time as a single floating point number, representing -the (fractional) number of seconds since the (POSIX) epoch (somewhere -near the beginning of 1970, details are complicated, don't ask). This -type is called C, which is what you should use too. It usually -aliases to the C type in C. When you need to do any calculations -on it, you should treat it as some floating point value. Unlike the name -component C might indicate, it is also used for time differences -throughout libev. +the (fractional) number of seconds since the (POSIX) epoch (in practise +somewhere near the beginning of 1970, details are complicated, don't +ask). This type is called C, which is what you should use +too. It usually aliases to the C type in C. When you need to do +any calculations on it, you should treat it as some floating point value. + +Unlike the name component C might indicate, it is also used for +time differences (e.g. delays) throughout libev. =head1 ERROR HANDLING @@ -193,7 +194,7 @@ compatible to older versions, so a larger minor version alone is usually not a problem. Example: Make sure we haven't accidentally been linked against the wrong -version. +version (note, however, that this will not detect ABI mismatches :). assert (("libev version mismatch", ev_version_major () == EV_VERSION_MAJOR @@ -293,13 +294,13 @@ Example: This is basically the same thing that libev does internally, too. =head1 FUNCTIONS CONTROLLING THE EVENT LOOP -An event loop is described by a C (the C -is I optional in this case, as there is also an C -I). +An event loop is described by a C (the C is +I optional in this case unless libev 3 compatibility is disabled, as +libev 3 had an C function colliding with the struct name). The library knows two types of such loops, the I loop, which -supports signals and child events, and dynamically created loops which do -not. +supports signals and child events, and dynamically created event loops +which do not. =over 4 @@ -347,9 +348,8 @@ around bugs. =item C -Instead of calling C or C manually after -a fork, you can also make libev check for a fork in each iteration by -enabling this flag. +Instead of calling C manually after a fork, you can also +make libev check for a fork in each iteration by enabling this flag. This works by calling C on every iteration of the loop, and thus this might slow down your event loop if you do a lot of loop @@ -441,7 +441,9 @@ I file descriptors (even already closed ones, so one cannot even remove them from the set) than registered in the set (especially on SMP systems). Libev tries to counter these spurious notifications by employing an additional generation counter and comparing that against the -events to filter out spurious ones, recreating the set when required. +events to filter out spurious ones, recreating the set when required. Last +not least, it also refuses to work with some file descriptors which work +perfectly fine with C is buggy + +All that's left is C actively limits the number of file +descriptors you can pass in to 1024 - your program suddenly crashes when +you use more. + +There is an undocumented "workaround" for this - defining +C<_DARWIN_UNLIMITED_SELECT>, which libev tries to use, so select I +work on OS/X. + +=head2 SOLARIS PROBLEMS AND WORKAROUNDS + +=head3 C reentrancy + +The default compile environment on Solaris is unfortunately so +thread-unsafe that you can't even use components/libraries compiled +without C<-D_REENTRANT> (as long as they use C), which, of course, +isn't defined by default. + +If you want to use libev in threaded environments you have to make sure +it's compiled with C<_REENTRANT> defined. + +=head3 Event port backend + +The scalable event interface for Solaris is called "event ports". Unfortunately, +this mechanism is very buggy. If you run into high CPU usage, your program +freezes or you get a large number of spurious wakeups, make sure you have +all the relevant and latest kernel patches applied. No, I don't know which +ones, but there are multiple ones. + +If you can't get it to work, you can try running the program by setting +the environment variable C to only allow C and +C works fine +with large bitsets, and AIX is dead anyway. + =head2 WIN32 PLATFORM LIMITATIONS AND WORKAROUNDS +=head3 General issues + Win32 doesn't support any of the standards (e.g. POSIX) that libev requires, and its I/O model is fundamentally incompatible with the POSIX model. Libev still offers limited functionality on this platform in the form of the C backend, and only supports socket descriptors. This only applies when using Win32 natively, not when using -e.g. cygwin. +e.g. cygwin. Actually, it only applies to the microsofts own compilers, +as every compielr comes with a slightly differently broken/incompatible +environment. Lifting these limitations would basically require the full -re-implementation of the I/O system. If you are into these kinds of -things, then note that glib does exactly that for you in a very portable -way (note also that glib is the slowest event library known to man). +re-implementation of the I/O system. If you are into this kind of thing, +then note that glib does exactly that for you in a very portable way (note +also that glib is the slowest event library known to man). There is no supported compilation method available on windows except embedding it into other applications. @@ -4351,9 +4639,7 @@ you do I compile the F or any other embedded source files!): #include "evwrap.h" #include "ev.c" -=over 4 - -=item The winsocket select function +=head3 The winsocket C function doesn't follow POSIX in that it requires socket I and not socket I (it is @@ -4372,7 +4658,7 @@ libraries and raw winsocket select is: Note that winsockets handling of fd sets is O(n), so you can easily get a complexity in the O(n²) range when using win32. -=item Limited number of file descriptors +=head3 Limited number of file descriptors Windows has numerous arbitrary (and low) limits on things. @@ -4397,8 +4683,6 @@ runtime libraries. This might get you to about C<512> or C<2048> sockets you need to wrap all I/O functions and provide your own fd management, but the cost of calling select (O(n²)) will likely make this unworkable. -=back - =head2 PORTABILITY REQUIREMENTS In addition to a working ISO-C implementation and of course the @@ -4446,11 +4730,11 @@ watchers. =item C must hold a time value in seconds with enough accuracy The type C is used to represent timestamps. It is required to -have at least 51 bits of mantissa (and 9 bits of exponent), which is good -enough for at least into the year 4000. This requirement is fulfilled by -implementations implementing IEEE 754, which is basically all existing -ones. With IEEE 754 doubles, you get microsecond accuracy until at least -2200. +have at least 51 bits of mantissa (and 9 bits of exponent), which is +good enough for at least into the year 4000 with millisecond accuracy +(the design goal for libev). This requirement is overfulfilled by +implementations using IEEE 754, which is basically all existing ones. With +IEEE 754 doubles, you get microsecond accuracy until at least 2200. =back @@ -4528,6 +4812,58 @@ involves iterating over all running async watchers or all signal numbers. =back +=head1 PORTING FROM LIBEV 3.X TO 4.X + +The major version 4 introduced some minor incompatible changes to the API. + +At the moment, the C header file tries to implement superficial +compatibility, so most programs should still compile. Those might be +removed in later versions of libev, so better update early than late. + +=over 4 + +=item function/symbol renames + +A number of functions and symbols have been renamed: + + ev_loop => ev_run + EVLOOP_NONBLOCK => EVRUN_NOWAIT + EVLOOP_ONESHOT => EVRUN_ONCE + + ev_unloop => ev_break + EVUNLOOP_CANCEL => EVBREAK_CANCEL + EVUNLOOP_ONE => EVBREAK_ONE + EVUNLOOP_ALL => EVBREAK_ALL + + EV_TIMEOUT => EV_TIMER + + ev_loop_count => ev_iteration + ev_loop_depth => ev_depth + ev_loop_verify => ev_verify + +Most functions working on C objects don't have an +C prefix, so it was removed; C, C and +associated constants have been renamed to not collide with the C anymore and C now follows the same naming scheme +as all other watcher types. Note that C is still called +C because it would otherwise clash with the C +typedef. + +=item C backwards compatibility mechanism + +The backward compatibility mechanism can be controlled by +C. See L in the L +section. + +=item C mechanism replaced by C + +The preprocessor symbol C has been replaced by a different +mechanism, C. Programs using C usually compile +and work, but the library code will of course be larger. + +=back + + =head1 GLOSSARY =over 4 @@ -4558,7 +4894,7 @@ for reading on a file descriptor, time having passed or simply not having any other events happening anymore. In libev, events are represented as single bits (such as C or -C). +C). =item event library diff --git a/deps/libev/ev_epoll.c b/deps/libev/ev_epoll.c index f7e3d60e3c..67a488bddc 100644 --- a/deps/libev/ev_epoll.c +++ b/deps/libev/ev_epoll.c @@ -1,7 +1,7 @@ /* * libev epoll fd activity backend * - * Copyright (c) 2007,2008,2009 Marc Alexander Lehmann + * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- @@ -49,6 +49,11 @@ * c) the inability to handle fork or file descriptors (think dup) * limits the applicability over poll, so this is not a generic * poll replacement. + * d) epoll doesn't work the same as select with many file descriptors + * (such as files). while not critical, no other advanced interface + * seems to share this (rather non-unixy) limitation. + * e) epoll claims to be embeddable, but in practise you never get + * a ready event for the epoll fd. * * lots of "weird code" and complication handling in this file is due * to these design problems with epoll, as we try very hard to avoid @@ -85,7 +90,7 @@ epoll_modify (EV_P_ int fd, int oev, int nev) ev.events = (nev & EV_READ ? EPOLLIN : 0) | (nev & EV_WRITE ? EPOLLOUT : 0); - if (expect_true (!epoll_ctl (backend_fd, oev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &ev))) + if (expect_true (!epoll_ctl (backend_fd, oev && oldmask != nev ? EPOLL_CTL_MOD : EPOLL_CTL_ADD, fd, &ev))) return; if (expect_true (errno == ENOENT)) @@ -165,7 +170,7 @@ epoll_poll (EV_P_ ev_tstamp timeout) /* which is fortunately easy to do for us. */ if (epoll_ctl (backend_fd, want ? EPOLL_CTL_MOD : EPOLL_CTL_DEL, fd, ev)) { - postfork = 1; /* an error occured, recreate kernel state */ + postfork = 1; /* an error occurred, recreate kernel state */ continue; } } diff --git a/deps/libev/ev_kqueue.c b/deps/libev/ev_kqueue.c index 0fe340b6a0..0d809f5ee8 100644 --- a/deps/libev/ev_kqueue.c +++ b/deps/libev/ev_kqueue.c @@ -1,7 +1,7 @@ /* * libev kqueue backend * - * Copyright (c) 2007,2008,2009 Marc Alexander Lehmann + * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- @@ -39,7 +39,6 @@ #include #include -#include #include #include #include @@ -53,6 +52,10 @@ kqueue_change (EV_P_ int fd, int filter, int flags, int fflags) EV_SET (&kqueue_changes [kqueue_changecnt - 1], fd, filter, flags, fflags, 0, 0); } +/* OS X at least needs this */ +#ifndef EV_ENABLE +# define EV_ENABLE 0 +#endif #ifndef NOTE_EOF # define NOTE_EOF 0 #endif @@ -73,10 +76,10 @@ kqueue_modify (EV_P_ int fd, int oev, int nev) /* event requests even when oev == nev */ if (nev & EV_READ) - kqueue_change (EV_A_ fd, EVFILT_READ , EV_ADD, NOTE_EOF); + kqueue_change (EV_A_ fd, EVFILT_READ , EV_ADD | EV_ENABLE, NOTE_EOF); if (nev & EV_WRITE) - kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_ADD, NOTE_EOF); + kqueue_change (EV_A_ fd, EVFILT_WRITE, EV_ADD | EV_ENABLE, NOTE_EOF); } static void @@ -94,8 +97,7 @@ kqueue_poll (EV_P_ ev_tstamp timeout) } EV_RELEASE_CB; - ts.tv_sec = (time_t)timeout; - ts.tv_nsec = (long)((timeout - (ev_tstamp)ts.tv_sec) * 1e9); + EV_TS_SET (ts, timeout); res = kevent (backend_fd, kqueue_changes, kqueue_changecnt, kqueue_events, kqueue_eventmax, &ts); EV_ACQUIRE_CB; kqueue_changecnt = 0; @@ -114,11 +116,11 @@ kqueue_poll (EV_P_ ev_tstamp timeout) if (expect_false (kqueue_events [i].flags & EV_ERROR)) { - int err = kqueue_events [i].data; + int err = kqueue_events [i].data; /* we are only interested in errors for fds that we are interested in :) */ if (anfds [fd].events) - { + { if (err == ENOENT) /* resubmit changes on ENOENT */ kqueue_modify (EV_A_ fd, 0, anfds [fd].events); else if (err == EBADF) /* on EBADF, we re-check the fd */ @@ -130,7 +132,7 @@ kqueue_poll (EV_P_ ev_tstamp timeout) } else /* on all other errors, we error out on the fd */ fd_kill (EV_A_ fd); - } + } } else fd_event ( @@ -153,7 +155,7 @@ kqueue_poll (EV_P_ ev_tstamp timeout) int inline_size kqueue_init (EV_P_ int flags) { - /* Initalize the kernel queue */ + /* Initialize the kernel queue */ if ((backend_fd = kqueue ()) < 0) return 0; diff --git a/deps/libev/ev_poll.c b/deps/libev/ev_poll.c index 178e458466..81e4b53ba9 100644 --- a/deps/libev/ev_poll.c +++ b/deps/libev/ev_poll.c @@ -1,7 +1,7 @@ /* * libev poll fd activity backend * - * Copyright (c) 2007,2008,2009 Marc Alexander Lehmann + * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- @@ -42,7 +42,7 @@ void inline_size pollidx_init (int *base, int count) { - /* consider using memset (.., -1, ...), which is pratically guarenteed + /* consider using memset (.., -1, ...), which is practically guaranteed * to work on all systems implementing poll */ while (count--) *base++ = -1; @@ -106,20 +106,24 @@ poll_poll (EV_P_ ev_tstamp timeout) } else for (p = polls; res; ++p) - if (expect_false (p->revents)) /* this expect is debatable */ - { - --res; - - if (expect_false (p->revents & POLLNVAL)) - fd_kill (EV_A_ p->fd); - else - fd_event ( - EV_A_ - p->fd, - (p->revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0) - | (p->revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0) - ); - } + { + assert (("libev: poll() returned illegal result, broken BSD kernel?", p < polls + pollcnt)); + + if (expect_false (p->revents)) /* this expect is debatable */ + { + --res; + + if (expect_false (p->revents & POLLNVAL)) + fd_kill (EV_A_ p->fd); + else + fd_event ( + EV_A_ + p->fd, + (p->revents & (POLLOUT | POLLERR | POLLHUP) ? EV_WRITE : 0) + | (p->revents & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0) + ); + } + } } int inline_size diff --git a/deps/libev/ev_port.c b/deps/libev/ev_port.c index 47da929ceb..801de15cbc 100644 --- a/deps/libev/ev_port.c +++ b/deps/libev/ev_port.c @@ -1,7 +1,7 @@ /* * libev solaris event port backend * - * Copyright (c) 2007,2008,2009 Marc Alexander Lehmann + * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- @@ -86,8 +86,7 @@ port_poll (EV_P_ ev_tstamp timeout) uint_t nget = 1; EV_RELEASE_CB; - ts.tv_sec = (time_t)timeout; - ts.tv_nsec = (long)(timeout - (ev_tstamp)ts.tv_sec) * 1e9; + EV_TS_SET (ts, timeout); res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts); EV_ACQUIRE_CB; @@ -112,7 +111,7 @@ port_poll (EV_P_ ev_tstamp timeout) | (port_events [i].portev_events & (POLLIN | POLLERR | POLLHUP) ? EV_READ : 0) ); - port_associate_and_check (EV_A_ fd, anfds [fd].events); + fd_change (EV_A_ fd, EV__IOFDSET); } } @@ -127,7 +126,7 @@ port_poll (EV_P_ ev_tstamp timeout) int inline_size port_init (EV_P_ int flags) { - /* Initalize the kernel queue */ + /* Initialize the kernel queue */ if ((backend_fd = port_create ()) < 0) return 0; @@ -137,7 +136,7 @@ port_init (EV_P_ int flags) backend_modify = port_modify; backend_poll = port_poll; - port_eventmax = 64; /* intiial number of events receivable per poll */ + port_eventmax = 64; /* initial number of events receivable per poll */ port_events = (port_event_t *)ev_malloc (sizeof (port_event_t) * port_eventmax); return EVBACKEND_PORT; diff --git a/deps/libev/ev_select.c b/deps/libev/ev_select.c index 818a63e2eb..76ffa86b3b 100644 --- a/deps/libev/ev_select.c +++ b/deps/libev/ev_select.c @@ -1,7 +1,7 @@ /* * libev select fd activity backend * - * Copyright (c) 2007,2008,2009 Marc Alexander Lehmann + * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- @@ -141,8 +141,7 @@ select_poll (EV_P_ ev_tstamp timeout) int fd_setsize; EV_RELEASE_CB; - tv.tv_sec = (long)timeout; - tv.tv_usec = (long)((timeout - (ev_tstamp)tv.tv_sec) * 1e6); + EV_TV_SET (tv, timeout); #if EV_SELECT_USE_FD_SET fd_setsize = sizeof (fd_set); @@ -184,7 +183,7 @@ select_poll (EV_P_ ev_tstamp timeout) #endif #ifdef _WIN32 - /* select on windows errornously returns EINVAL when no fd sets have been + /* select on windows erroneously returns EINVAL when no fd sets have been * provided (this is documented). what microsoft doesn't tell you that this bug * exists even when the fd sets _are_ provided, so we have to check for this bug * here and emulate by sleeping manually. diff --git a/deps/libev/ev_vars.h b/deps/libev/ev_vars.h index da53ee818c..808f3c6d6e 100644 --- a/deps/libev/ev_vars.h +++ b/deps/libev/ev_vars.h @@ -1,7 +1,7 @@ /* * loop member variable declarations * - * Copyright (c) 2007,2008,2009 Marc Alexander Lehmann + * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- @@ -48,7 +48,7 @@ VARx(ev_tstamp, timeout_blocktime) VARx(int, backend) VARx(int, activecnt) /* total number of active events ("refcount") */ -VARx(unsigned char, loop_done) /* signal by ev_unloop */ +VARx(EV_ATOMIC_T, loop_done) /* signal by ev_break */ VARx(int, backend_fd) VARx(ev_tstamp, backend_fudge) /* assumed typical timer resolution */ @@ -173,9 +173,9 @@ VARx(ev_io, sigfd_w) VARx(sigset_t, sigfd_set) #endif -#if EV_MINIMAL < 2 || EV_GENWRAP +#if EV_FEATURE_API || EV_GENWRAP VARx(unsigned int, loop_count) /* total number of loop iterations/blocks */ -VARx(unsigned int, loop_depth) /* #ev_loop enters - #ev_loop leaves */ +VARx(unsigned int, loop_depth) /* #ev_run enters - #ev_run leaves */ VARx(void *, userdata) VAR (release_cb, void (*release_cb)(EV_P)) diff --git a/deps/libev/event.c b/deps/libev/event.c index fae26bb045..b0eb47588e 100644 --- a/deps/libev/event.c +++ b/deps/libev/event.c @@ -1,7 +1,7 @@ /* * libevent compatibility layer * - * Copyright (c) 2007,2008,2009 Marc Alexander Lehmann + * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- @@ -63,18 +63,14 @@ struct event_base static struct event_base *ev_x_cur; -static void -ev_tv_set (struct timeval *tv, ev_tstamp at) -{ - tv->tv_sec = (long)at; - tv->tv_usec = (long)((at - (ev_tstamp)tv->tv_sec) * 1e6); -} - static ev_tstamp ev_tv_get (struct timeval *tv) { if (tv) - return tv->tv_sec + tv->tv_usec * 1e-6; + { + ev_tstamp after = tv->tv_sec + tv->tv_usec * 1e-6; + return after ? after : 1e-6; + } else return -1.; } @@ -144,7 +140,7 @@ int event_loopexit (struct timeval *tv) static void ev_x_cb (struct event *ev, int revents) { - revents &= EV_READ | EV_WRITE | EV_TIMEOUT | EV_SIGNAL; + revents &= EV_READ | EV_WRITE | EV_TIMER | EV_SIGNAL; ev->ev_res = revents; ev->ev_callback (ev->ev_fd, (short)revents, ev->ev_arg); @@ -302,7 +298,7 @@ int event_pending (struct event *ev, short events, struct timeval *tv) revents |= EV_TIMEOUT; if (tv) - ev_tv_set (tv, ev_now (EV_A)); /* not sure if this is right :) */ + EV_TV_SET (tv, ev_now (EV_A)); /* not sure if this is right :) */ } return events & revents; @@ -331,7 +327,7 @@ int event_base_loop (struct event_base *base, int flags) { dLOOPbase; - ev_loop (EV_A_ flags); + ev_run (EV_A_ flags); return 0; } @@ -346,7 +342,7 @@ ev_x_loopexit_cb (int revents, void *base) { dLOOPbase; - ev_unloop (EV_A_ EVUNLOOP_ONE); + ev_break (EV_A_ EVBREAK_ONE); } int event_base_loopexit (struct event_base *base, struct timeval *tv) diff --git a/deps/libev/event.h b/deps/libev/event.h index 65415773e4..358344a0de 100644 --- a/deps/libev/event.h +++ b/deps/libev/event.h @@ -1,7 +1,7 @@ /* * libevent compatibility header, only core events supported * - * Copyright (c) 2007,2008 Marc Alexander Lehmann + * Copyright (c) 2007,2008,2010 Marc Alexander Lehmann * All rights reserved. * * Redistribution and use in source and binary forms, with or without modifica- @@ -46,6 +46,16 @@ # include "ev.h" #endif +#ifndef EVLOOP_NONBLOCK +# define EVLOOP_NONBLOCK EVRUN_NOWAIT +#endif +#ifndef EVLOOP_ONESHOT +# define EVLOOP_ONESHOT EVRUN_ONCE +#endif +#ifndef EV_TIMEOUT +# define EV_TIMEOUT EV_TIMER +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/deps/libev/libev.m4 b/deps/libev/libev.m4 index 2ba20eb37d..0930c0c001 100644 --- a/deps/libev/libev.m4 +++ b/deps/libev/libev.m4 @@ -2,16 +2,17 @@ dnl this file is part of libev, do not make local modifications dnl http://software.schmorp.de/pkg/libev dnl libev support -AC_CHECK_HEADERS(sys/inotify.h sys/epoll.h sys/event.h sys/queue.h port.h poll.h sys/select.h sys/eventfd.h) +AC_CHECK_HEADERS(sys/inotify.h sys/epoll.h sys/event.h port.h poll.h sys/select.h sys/eventfd.h sys/signalfd.h) -AC_CHECK_FUNCS(inotify_init epoll_ctl kqueue port_create poll select eventfd) +AC_CHECK_FUNCS(inotify_init epoll_ctl kqueue port_create poll select eventfd signalfd) AC_CHECK_FUNC(clock_gettime, [], [ dnl on linux, try syscall wrapper first if test $(uname) = Linux; then AC_MSG_CHECKING(for clock_gettime syscall) AC_LINK_IFELSE([AC_LANG_PROGRAM( - [#include + [#include + #include #include ], [struct timespec ts; int status = syscall (SYS_clock_gettime, CLOCK_REALTIME, &ts)])], [ac_have_clock_syscall=1 @@ -36,5 +37,3 @@ AC_CHECK_FUNC(nanosleep, [], [ AC_CHECK_LIB(m, ceil) - -