Browse Source

Upgrade libev to 4.3

v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
b7419dfaad
  1. 53
      deps/libev/Changes
  2. 4
      deps/libev/Makefile.am
  3. 2
      deps/libev/autogen.sh
  4. 28
      deps/libev/config.h.in
  5. 2
      deps/libev/configure.ac
  6. 41
      deps/libev/ev++.h
  7. 2026
      deps/libev/ev.3
  8. 299
      deps/libev/ev.c
  9. 137
      deps/libev/ev.h
  10. 1170
      deps/libev/ev.pod
  11. 41
      deps/libev/ev_epoll.c
  12. 29
      deps/libev/ev_port.c
  13. 18
      deps/libev/ev_vars.h
  14. 18
      deps/libev/ev_wrap.h
  15. 9
      deps/libev/event.c
  16. 2
      deps/libev/event.h

53
deps/libev/Changes

@ -1,12 +1,33 @@
Revision history for libev, a high-performance and full-featured event loop. Revision history for libev, a high-performance and full-featured event loop.
TODO: include ev_xyz_start in each example? 4.03 Tue Jan 11 14:37:25 CET 2011
TODO: section watcher states/lifetime - officially support polling files with all backends.
TODO: use enums //TODO: enum? - support files, /dev/zero etc. the same way as select in the epoll
backend, by generating events on our own.
- ports backend: work around solaris bug 6874410 and many related ones
(EINTR, maybe more), with no performance loss (note that the solaris
bug report is actually wrong, reality is far more bizarre and broken
than that).
- define EV_READ/EV_WRITE as macros in event.h, as some programs use
#ifdef to test for them.
- new (experimental) function: ev_feed_signal.
- new (to become default) EVFLAG_NOSIGMASK flag.
- new EVBACKEND_MASK symbol.
- updated COMMON IDIOMS SECTION.
4.01 Fri Nov 5 21:51:29 CET 2010
- automake fucked it up, apparently, --add-missing -f is not quite enough
to make it update its files, so 4.00 didn't install ev++.h and
event.h on make install. grrr.
- ev_loop(count|depth) didn't return anything (Robin Haberkorn).
- change EV_UNDEF to 0xffffffff to silence some overzealous compilers.
- use "(libev) " prefix for all libev error messages now.
4.00 Mon Oct 25 12:32:12 CEST 2010
- "PORTING FROM LIBEV 3.X TO 4.X" (in ev.pod) is recommended reading. - "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 - ev_embed_stop did not correctly stop the watcher (very good
testcase by Vladimir Timofeev). testcase by Vladimir Timofeev).
- ev_run will now always update the current loop time - it errornously - ev_run will now always update the current loop time - it erroneously
didn't when idle watchers were active, causing timers not to fire. 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 - fix a bug where a timeout of zero caused the timer not to fire
in the libevent emulation (testcase by Péter Szabó). in the libevent emulation (testcase by Péter Szabó).
@ -14,6 +35,8 @@ TODO: use enums //TODO: enum?
- replace EV_MINIMAL by EV_FEATURES. - replace EV_MINIMAL by EV_FEATURES.
- prefer EPOLL_CTL_ADD over EPOLL_CTL_MOD in some more cases, as it - prefer EPOLL_CTL_ADD over EPOLL_CTL_MOD in some more cases, as it
seems the former is *much* faster than the latter. seems the former is *much* faster than the latter.
- linux kernel version detection (for inotify bug workarounds)
did not work properly.
- reduce the number of spurious wake-ups with the ports backend. - reduce the number of spurious wake-ups with the ports backend.
- remove dependency on sys/queue.h on freebsd (patch by Vanilla Hsu). - 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 - do async init within ev_async_start, not ev_async_set, which avoids
@ -24,9 +47,11 @@ TODO: use enums //TODO: enum?
not to need it (helpfully pointed out by Tilghman Lesher). not to need it (helpfully pointed out by Tilghman Lesher).
- do not use poll by default on freebsd, it's broken (what isn't - do not use poll by default on freebsd, it's broken (what isn't
on freebsd...). on freebsd...).
- allow to embed epoll on kernels >= 2.6.32.
- configure now prepends -O3, not appends it, so one can still - configure now prepends -O3, not appends it, so one can still
override it. override it.
- greatly expanded the portability section. - ev.pod: greatly expanded the portability section, added a porting
section, a description of watcher states and made lots of minor fixes.
- disable poll backend on AIX, the poll header spams the namespace - disable poll backend on AIX, the poll header spams the namespace
and it's not worth working around dead platforms (reported and it's not worth working around dead platforms (reported
and analyzed by Aivars Kalvans). and analyzed by Aivars Kalvans).
@ -39,12 +64,18 @@ TODO: use enums //TODO: enum?
- update libev.m4 HAVE_CLOCK_SYSCALL test for newer glibcs. - update libev.m4 HAVE_CLOCK_SYSCALL test for newer glibcs.
- add section on accept() problems to the manpage. - add section on accept() problems to the manpage.
- rename EV_TIMEOUT to EV_TIMER. - rename EV_TIMEOUT to EV_TIMER.
- rename ev_loop_count/depth/verify. - rename ev_loop_count/depth/verify/loop/unloop.
- remove ev_default_destroy and ev_default_fork.
- switch to two-digit minor version. - switch to two-digit minor version.
- work around an apparent gentoo compiler bug. - work around an apparent gentoo compiler bug.
- define _DARWIN_UNLIMITED_SELECT. just so. - define _DARWIN_UNLIMITED_SELECT. just so.
- use enum instead of #define for most constants. - use enum instead of #define for most constants.
- improve compatibility to older C++ compilers. - improve compatibility to older C++ compilers.
- (experimental) ev_run/ev_default_loop/ev_break/ev_loop_new have now
default arguments when compiled as C++.
- enable automake dependency tracking.
- ev_loop_new no longer leaks memory when loop creation failed.
- new ev_cleanup watcher type.
3.9 Thu Dec 31 07:59:59 CET 2009 3.9 Thu Dec 31 07:59:59 CET 2009
- signalfd is no longer used by default and has to be requested - signalfd is no longer used by default and has to be requested
@ -70,14 +101,14 @@ TODO: use enums //TODO: enum?
- add missing string.h include (Denis F. Latypoff). - add missing string.h include (Denis F. Latypoff).
- only replace ev_stat.prev when we detect an actual difference, - only replace ev_stat.prev when we detect an actual difference,
so prev is (almost) always different to attr. this might so prev is (almost) always different to attr. this might
have caused the probems with 04_stat.t. have caused the problems with 04_stat.t.
- add ev::timer->remaining () method to C++ API. - add ev::timer->remaining () method to C++ API.
3.8 Sun Aug 9 14:30:45 CEST 2009 3.8 Sun Aug 9 14:30:45 CEST 2009
- incompatible change: do not necessarily reset signal handler - incompatible change: do not necessarily reset signal handler
to SIG_DFL when a sighandler is stopped. to SIG_DFL when a sighandler is stopped.
- ev_default_destroy did not properly free or zero some members, - ev_default_destroy did not properly free or zero some members,
potentially causing crashes and memory corruption on repated potentially causing crashes and memory corruption on repeated
ev_default_destroy/ev_default_loop calls. ev_default_destroy/ev_default_loop calls.
- take advantage of signalfd on GNU/Linux systems. - take advantage of signalfd on GNU/Linux systems.
- document that the signal mask might be in an unspecified - document that the signal mask might be in an unspecified
@ -209,7 +240,7 @@ TODO: use enums //TODO: enum?
3.45 Tue Oct 21 21:59:26 CEST 2008 3.45 Tue Oct 21 21:59:26 CEST 2008
- disable inotify usage on linux <2.6.25, as it is broken - disable inotify usage on linux <2.6.25, as it is broken
(reported by Yoann Vandoorselaere). (reported by Yoann Vandoorselaere).
- ev_stat errornously would try to add inotify watchers - ev_stat erroneously would try to add inotify watchers
even when inotify wasn't available (this should only even when inotify wasn't available (this should only
have a performance impact). have a performance impact).
- ev_once now passes both timeout and io to the callback if both - ev_once now passes both timeout and io to the callback if both
@ -287,10 +318,10 @@ TODO: use enums //TODO: enum?
not clearing revents field in ev_poll (Brandon Black) not clearing revents field in ev_poll (Brandon Black)
(no such systems are known at this time). (no such systems are known at this time).
- work around a bug in realloc on openbsd and darwin, - work around a bug in realloc on openbsd and darwin,
also makes the errornous valgrind complaints also makes the erroneous valgrind complaints
go away (noted by various people). go away (noted by various people).
- fix ev_async_pending, add c++ wrapper for ev_async - fix ev_async_pending, add c++ wrapper for ev_async
(based on patch sent by Johannes Deisenhofer. (based on patch sent by Johannes Deisenhofer).
- add sensible set method to ev::embed. - add sensible set method to ev::embed.
- made integer constants type int in ev.h. - made integer constants type int in ev.h.

4
deps/libev/Makefile.am

@ -1,6 +1,6 @@
AUTOMAKE_OPTIONS = foreign no-dependencies AUTOMAKE_OPTIONS = foreign
VERSION_INFO = 4:0 VERSION_INFO = 4:0:0
EXTRA_DIST = LICENSE Changes libev.m4 autogen.sh \ EXTRA_DIST = LICENSE Changes libev.m4 autogen.sh \
ev_vars.h ev_wrap.h \ ev_vars.h ev_wrap.h \

2
deps/libev/autogen.sh

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
libtoolize --force libtoolize --force
automake --add-missing automake --add-missing --force-missing
autoreconf autoreconf

28
deps/libev/config.h.in

@ -93,5 +93,33 @@
/* Define to 1 if you have the <unistd.h> header file. */ /* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H #undef HAVE_UNISTD_H
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Name of package */
#undef PACKAGE
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to 1 if you have the ANSI C header files. */ /* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS #undef STDC_HEADERS
/* Version number of package */
#undef VERSION

2
deps/libev/configure.ac

@ -1,7 +1,7 @@
AC_INIT AC_INIT
AC_CONFIG_SRCDIR([ev_epoll.c]) AC_CONFIG_SRCDIR([ev_epoll.c])
AM_INIT_AUTOMAKE(libev,4.00) dnl also update ev.h! AM_INIT_AUTOMAKE(libev,4.03) dnl also update ev.h!
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
AM_MAINTAINER_MODE AM_MAINTAINER_MODE

41
deps/libev/ev++.h

@ -58,13 +58,15 @@ namespace ev {
typedef ev_tstamp tstamp; typedef ev_tstamp tstamp;
enum enum {
{
UNDEF = EV_UNDEF, UNDEF = EV_UNDEF,
NONE = EV_NONE, NONE = EV_NONE,
READ = EV_READ, READ = EV_READ,
WRITE = EV_WRITE, WRITE = EV_WRITE,
#if EV_COMPAT3
TIMEOUT = EV_TIMEOUT, TIMEOUT = EV_TIMEOUT,
#endif
TIMER = EV_TIMER,
PERIODIC = EV_PERIODIC, PERIODIC = EV_PERIODIC,
SIGNAL = EV_SIGNAL, SIGNAL = EV_SIGNAL,
CHILD = EV_CHILD, CHILD = EV_CHILD,
@ -95,14 +97,18 @@ namespace ev {
enum enum
{ {
#if EV_COMPAT3
NONBLOCK = EVLOOP_NONBLOCK, NONBLOCK = EVLOOP_NONBLOCK,
ONESHOT = EVLOOP_ONESHOT ONESHOT = EVLOOP_ONESHOT,
#endif
NOWAIT = EVRUN_NOWAIT,
ONCE = EVRUN_ONCE
}; };
enum how_t enum how_t
{ {
ONE = EVUNLOOP_ONE, ONE = EVBREAK_ONE,
ALL = EVUNLOOP_ALL ALL = EVBREAK_ALL
}; };
struct bad_loop struct bad_loop
@ -188,23 +194,31 @@ namespace ev {
} }
#endif #endif
#if EV_COMPAT3
void loop (int flags = 0) void loop (int flags = 0)
{ {
ev_loop (EV_AX_ flags); ev_run (EV_AX_ flags);
} }
void unloop (how_t how = ONE) throw () void unloop (how_t how = ONE) throw ()
{ {
ev_unloop (EV_AX_ how); ev_break (EV_AX_ how);
}
#endif
void run (int flags = 0)
{
ev_run (EV_AX_ flags);
}
void break_loop (how_t how = ONE) throw ()
{
ev_break (EV_AX_ how);
} }
void post_fork () throw () void post_fork () throw ()
{ {
#if EV_MULTIPLICITY
ev_loop_fork (EV_AX); ev_loop_fork (EV_AX);
#else
ev_default_fork ();
#endif
} }
unsigned int backend () const throw () unsigned int backend () const throw ()
@ -377,11 +391,6 @@ namespace ev {
throw bad_loop (); throw bad_loop ();
} }
~default_loop () throw ()
{
ev_default_destroy ();
}
private: private:
default_loop (const default_loop &); default_loop (const default_loop &);
default_loop &operator = (const default_loop &); default_loop &operator = (const default_loop &);

2026
deps/libev/ev.3

File diff suppressed because it is too large

299
deps/libev/ev.c

@ -1,7 +1,7 @@
/* /*
* libev event processing core, watcher management * libev event processing core, watcher management
* *
* Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de> * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modifica- * Redistribution and use in source and binary forms, with or without modifica-
@ -37,10 +37,6 @@
* either the BSD or the GPL. * either the BSD or the GPL.
*/ */
#ifdef __cplusplus
extern "C" {
#endif
/* this big block deduces configuration from config.h */ /* this big block deduces configuration from config.h */
#ifndef EV_STANDALONE #ifndef EV_STANDALONE
# ifdef EV_CONFIG_H # ifdef EV_CONFIG_H
@ -184,6 +180,8 @@ extern "C" {
# include "ev.h" # include "ev.h"
#endif #endif
EV_CPP(extern "C" {)
#ifndef _WIN32 #ifndef _WIN32
# include <sys/time.h> # include <sys/time.h>
# include <sys/wait.h> # include <sys/wait.h>
@ -386,7 +384,6 @@ extern "C" {
#endif #endif
#if EV_USE_INOTIFY #if EV_USE_INOTIFY
# include <sys/utsname.h>
# include <sys/statfs.h> # include <sys/statfs.h>
# include <sys/inotify.h> # include <sys/inotify.h>
/* some very old inotify.h headers don't have IN_DONT_FOLLOW */ /* some very old inotify.h headers don't have IN_DONT_FOLLOW */
@ -413,13 +410,7 @@ extern "C" {
# define EFD_CLOEXEC 02000000 # define EFD_CLOEXEC 02000000
# endif # endif
# endif # endif
# ifdef __cplusplus EV_CPP(extern "C") int (eventfd) (unsigned int initval, int flags);
extern "C" {
# endif
int (eventfd) (unsigned int initval, int flags);
# ifdef __cplusplus
}
# endif
#endif #endif
#if EV_USE_SIGNALFD #if EV_USE_SIGNALFD
@ -435,19 +426,13 @@ int (eventfd) (unsigned int initval, int flags);
# define SFD_CLOEXEC 02000000 # define SFD_CLOEXEC 02000000
# endif # endif
# endif # endif
# ifdef __cplusplus EV_CPP (extern "C") int signalfd (int fd, const sigset_t *mask, int flags);
extern "C" {
# endif
int signalfd (int fd, const sigset_t *mask, int flags);
struct signalfd_siginfo struct signalfd_siginfo
{ {
uint32_t ssi_signo; uint32_t ssi_signo;
char pad[128 - sizeof (uint32_t)]; char pad[128 - sizeof (uint32_t)];
}; };
# ifdef __cplusplus
}
# endif
#endif #endif
/**/ /**/
@ -539,6 +524,48 @@ static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work?
/*****************************************************************************/ /*****************************************************************************/
#ifdef __linux
# include <sys/utsname.h>
#endif
static unsigned int noinline
ev_linux_version (void)
{
#ifdef __linux
unsigned int v = 0;
struct utsname buf;
int i;
char *p = buf.release;
if (uname (&buf))
return 0;
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;
#else
return 0;
#endif
}
/*****************************************************************************/
#if EV_AVOID_STDIO #if EV_AVOID_STDIO
static void noinline static void noinline
ev_printerr (const char *msg) ev_printerr (const char *msg)
@ -566,11 +593,9 @@ ev_syserr (const char *msg)
else else
{ {
#if EV_AVOID_STDIO #if EV_AVOID_STDIO
const char *err = strerror (errno);
ev_printerr (msg); ev_printerr (msg);
ev_printerr (": "); ev_printerr (": ");
ev_printerr (err); ev_printerr (strerror (errno));
ev_printerr ("\n"); ev_printerr ("\n");
#else #else
perror (msg); perror (msg);
@ -614,9 +639,9 @@ ev_realloc (void *ptr, long size)
if (!ptr && size) if (!ptr && size)
{ {
#if EV_AVOID_STDIO #if EV_AVOID_STDIO
ev_printerr ("libev: memory allocation failed, aborting.\n"); ev_printerr ("(libev) memory allocation failed, aborting.\n");
#else #else
fprintf (stderr, "libev: cannot allocate %ld bytes, aborting.", size); fprintf (stderr, "(libev) cannot allocate %ld bytes, aborting.", size);
#endif #endif
abort (); abort ();
} }
@ -643,9 +668,12 @@ typedef struct
#if EV_USE_EPOLL #if EV_USE_EPOLL
unsigned int egen; /* generation counter to counter epoll bugs */ unsigned int egen; /* generation counter to counter epoll bugs */
#endif #endif
#if EV_SELECT_IS_WINSOCKET #if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP
SOCKET handle; SOCKET handle;
#endif #endif
#if EV_USE_IOCP
OVERLAPPED or, ow;
#endif
} ANFD; } ANFD;
/* stores the pending event set for a given watcher */ /* stores the pending event set for a given watcher */
@ -950,12 +978,13 @@ fd_reify (EV_P)
anfd->reify = 0; anfd->reify = 0;
#if EV_SELECT_IS_WINSOCKET #if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP
if (o_reify & EV__IOFDSET) if (o_reify & EV__IOFDSET)
{ {
unsigned long arg; unsigned long arg;
anfd->handle = EV_FD_TO_WIN32_HANDLE (fd); anfd->handle = EV_FD_TO_WIN32_HANDLE (fd);
assert (("libev: only socket fds supported in this configuration", ioctlsocket (anfd->handle, FIONREAD, &arg) == 0)); assert (("libev: only socket fds supported in this configuration", ioctlsocket (anfd->handle, FIONREAD, &arg) == 0));
printf ("oi %d %x\n", fd, anfd->handle);//D
} }
#endif #endif
@ -1289,11 +1318,7 @@ evpipe_write (EV_P_ EV_ATOMIC_T *flag)
/* so when you think this write should be a send instead, please find out */ /* 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 */ /* where your send() is from - it's definitely not the microsoft send, and */
/* tell me. thank you. */ /* tell me. thank you. */
#ifdef __MINGW32__
send(EV_FD_TO_WIN32_HANDLE(evpipe [1]), &dummy, 1, 0);
#else
write (evpipe [1], &dummy, 1); write (evpipe [1], &dummy, 1);
#endif
errno = old_errno; errno = old_errno;
} }
@ -1317,11 +1342,7 @@ pipecb (EV_P_ ev_io *iow, int revents)
{ {
char dummy; char dummy;
/* see discussion in evpipe_write when you think this read should be recv in win32 */ /* see discussion in evpipe_write when you think this read should be recv in win32 */
#ifdef __MINGW32__
recv(EV_FD_TO_WIN32_HANDLE(evpipe [0]), &dummy, 1, 0);
#else
read (evpipe [0], &dummy, 1); read (evpipe [0], &dummy, 1);
#endif
} }
if (sig_pending) if (sig_pending)
@ -1350,19 +1371,28 @@ pipecb (EV_P_ ev_io *iow, int revents)
/*****************************************************************************/ /*****************************************************************************/
static void void
ev_sighandler (int signum) ev_feed_signal (int signum)
{ {
#if EV_MULTIPLICITY #if EV_MULTIPLICITY
EV_P = signals [signum - 1].loop; EV_P = signals [signum - 1].loop;
if (!EV_A)
return;
#endif #endif
signals [signum - 1].pending = 1;
evpipe_write (EV_A_ &sig_pending);
}
static void
ev_sighandler (int signum)
{
#ifdef _WIN32 #ifdef _WIN32
signal (signum, ev_sighandler); signal (signum, ev_sighandler);
#endif #endif
signals [signum - 1].pending = 1; ev_feed_signal (signum);
evpipe_write (EV_A_ &sig_pending);
} }
void noinline void noinline
@ -1472,6 +1502,9 @@ childcb (EV_P_ ev_signal *sw, int revents)
/*****************************************************************************/ /*****************************************************************************/
#if EV_USE_IOCP
# include "ev_iocp.c"
#endif
#if EV_USE_PORT #if EV_USE_PORT
# include "ev_port.c" # include "ev_port.c"
#endif #endif
@ -1554,8 +1587,8 @@ ev_embeddable_backends (void)
int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT; int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT;
/* epoll embeddability broken on all linux versions up to at least 2.6.23 */ /* epoll embeddability broken on all linux versions up to at least 2.6.23 */
/* please fix it and tell me how to detect the fix */ if (ev_linux_version () < 0x020620) /* disable it on linux < 2.6.32 */
flags &= ~EVBACKEND_EPOLL; flags &= ~EVBACKEND_EPOLL;
return flags; return flags;
} }
@ -1621,6 +1654,8 @@ loop_init (EV_P_ unsigned int flags)
{ {
if (!backend) if (!backend)
{ {
origflags = flags;
#if EV_USE_REALTIME #if EV_USE_REALTIME
if (!have_realtime) if (!have_realtime)
{ {
@ -1675,9 +1710,12 @@ loop_init (EV_P_ unsigned int flags)
sigfd = flags & EVFLAG_SIGNALFD ? -2 : -1; sigfd = flags & EVFLAG_SIGNALFD ? -2 : -1;
#endif #endif
if (!(flags & 0x0000ffffU)) if (!(flags & EVBACKEND_MASK))
flags |= ev_recommended_backends (); flags |= ev_recommended_backends ();
#if EV_USE_IOCP
if (!backend && (flags & EVBACKEND_IOCP )) backend = iocp_init (EV_A_ flags);
#endif
#if EV_USE_PORT #if EV_USE_PORT
if (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags); if (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags);
#endif #endif
@ -1704,11 +1742,34 @@ loop_init (EV_P_ unsigned int flags)
} }
/* free up a loop structure */ /* free up a loop structure */
static void noinline void
loop_destroy (EV_P) ev_loop_destroy (EV_P)
{ {
int i; int i;
#if EV_MULTIPLICITY
/* mimic free (0) */
if (!EV_A)
return;
#endif
#if EV_CLEANUP_ENABLE
/* queue cleanup watchers (and execute them) */
if (expect_false (cleanupcnt))
{
queue_events (EV_A_ (W *)cleanups, cleanupcnt, EV_CLEANUP);
EV_INVOKE_PENDING;
}
#endif
#if EV_CHILD_ENABLE
if (ev_is_active (&childev))
{
ev_ref (EV_A); /* child watcher */
ev_signal_stop (EV_A_ &childev);
}
#endif
if (ev_is_active (&pipe_w)) if (ev_is_active (&pipe_w))
{ {
/*ev_ref (EV_A);*/ /*ev_ref (EV_A);*/
@ -1739,6 +1800,9 @@ loop_destroy (EV_P)
if (backend_fd >= 0) if (backend_fd >= 0)
close (backend_fd); close (backend_fd);
#if EV_USE_IOCP
if (backend == EVBACKEND_IOCP ) iocp_destroy (EV_A);
#endif
#if EV_USE_PORT #if EV_USE_PORT
if (backend == EVBACKEND_PORT ) port_destroy (EV_A); if (backend == EVBACKEND_PORT ) port_destroy (EV_A);
#endif #endif
@ -1774,6 +1838,9 @@ loop_destroy (EV_P)
#endif #endif
#if EV_FORK_ENABLE #if EV_FORK_ENABLE
array_free (fork, EMPTY); array_free (fork, EMPTY);
#endif
#if EV_CLEANUP_ENABLE
array_free (cleanup, EMPTY);
#endif #endif
array_free (prepare, EMPTY); array_free (prepare, EMPTY);
array_free (check, EMPTY); array_free (check, EMPTY);
@ -1782,6 +1849,15 @@ loop_destroy (EV_P)
#endif #endif
backend = 0; backend = 0;
#if EV_MULTIPLICITY
if (ev_is_default_loop (EV_A))
#endif
ev_default_loop_ptr = 0;
#if EV_MULTIPLICITY
else
ev_free (EV_A);
#endif
} }
#if EV_USE_INOTIFY #if EV_USE_INOTIFY
@ -1850,21 +1926,10 @@ ev_loop_new (unsigned int flags)
if (ev_backend (EV_A)) if (ev_backend (EV_A))
return EV_A; return EV_A;
ev_free (EV_A);
return 0; return 0;
} }
void
ev_loop_destroy (EV_P)
{
loop_destroy (EV_A);
ev_free (loop);
}
void
ev_loop_fork (EV_P)
{
postfork = 1; /* must be in line with ev_default_fork */
}
#endif /* multiplicity */ #endif /* multiplicity */
#if EV_VERIFY #if EV_VERIFY
@ -1949,6 +2014,11 @@ ev_verify (EV_P)
array_verify (EV_A_ (W *)forks, forkcnt); array_verify (EV_A_ (W *)forks, forkcnt);
#endif #endif
#if EV_CLEANUP_ENABLE
assert (cleanupmax >= cleanupcnt);
array_verify (EV_A_ (W *)cleanups, cleanupcnt);
#endif
#if EV_ASYNC_ENABLE #if EV_ASYNC_ENABLE
assert (asyncmax >= asynccnt); assert (asyncmax >= asynccnt);
array_verify (EV_A_ (W *)asyncs, asynccnt); array_verify (EV_A_ (W *)asyncs, asynccnt);
@ -1976,11 +2046,10 @@ ev_verify (EV_P)
#if EV_MULTIPLICITY #if EV_MULTIPLICITY
struct ev_loop * struct ev_loop *
ev_default_loop_init (unsigned int flags)
#else #else
int int
ev_default_loop (unsigned int flags)
#endif #endif
ev_default_loop (unsigned int flags)
{ {
if (!ev_default_loop_ptr) if (!ev_default_loop_ptr)
{ {
@ -2009,30 +2078,9 @@ ev_default_loop (unsigned int flags)
} }
void void
ev_default_destroy (void) ev_loop_fork (EV_P)
{
#if EV_MULTIPLICITY
EV_P = ev_default_loop_ptr;
#endif
ev_default_loop_ptr = 0;
#if EV_CHILD_ENABLE
ev_ref (EV_A); /* child watcher */
ev_signal_stop (EV_A_ &childev);
#endif
loop_destroy (EV_A);
}
void
ev_default_fork (void)
{ {
#if EV_MULTIPLICITY postfork = 1; /* must be in line with ev_default_fork */
EV_P = ev_default_loop_ptr;
#endif
postfork = 1; /* must be in line with ev_loop_fork */
} }
/*****************************************************************************/ /*****************************************************************************/
@ -2065,9 +2113,6 @@ ev_invoke_pending (EV_P)
{ {
ANPENDING *p = pendings [pri] + --pendingcnt [pri]; ANPENDING *p = pendings [pri] + --pendingcnt [pri];
/*assert (("libev: non-pending watcher on pending list", p->w->pending));*/
/* ^ this is no longer true, as pending_w could be here */
p->w->pending = 0; p->w->pending = 0;
EV_CB_INVOKE (p->w, p->events); EV_CB_INVOKE (p->w, p->events);
EV_FREQUENT_CHECK; EV_FREQUENT_CHECK;
@ -2844,9 +2889,12 @@ ev_signal_start (EV_P_ ev_signal *w)
sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */ sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */
sigaction (w->signum, &sa, 0); sigaction (w->signum, &sa, 0);
sigemptyset (&sa.sa_mask); if (origflags & EVFLAG_NOSIGMASK)
sigaddset (&sa.sa_mask, w->signum); {
sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0); sigemptyset (&sa.sa_mask);
sigaddset (&sa.sa_mask, w->signum);
sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0);
}
#endif #endif
} }
@ -3074,38 +3122,6 @@ infy_cb (EV_P_ ev_io *w, int revents)
} }
} }
inline_size unsigned int
ev_linux_version (void)
{
struct utsname buf;
unsigned int v;
int i;
char *p = buf.release;
if (uname (&buf))
return 0;
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;
}
inline_size void inline_size void
ev_check_2625 (EV_P) ev_check_2625 (EV_P)
{ {
@ -3580,6 +3596,47 @@ ev_fork_stop (EV_P_ ev_fork *w)
} }
#endif #endif
#if EV_CLEANUP_ENABLE
void
ev_cleanup_start (EV_P_ ev_cleanup *w)
{
if (expect_false (ev_is_active (w)))
return;
EV_FREQUENT_CHECK;
ev_start (EV_A_ (W)w, ++cleanupcnt);
array_needsize (ev_cleanup *, cleanups, cleanupmax, cleanupcnt, EMPTY2);
cleanups [cleanupcnt - 1] = w;
/* cleanup watchers should never keep a refcount on the loop */
ev_unref (EV_A);
EV_FREQUENT_CHECK;
}
void
ev_cleanup_stop (EV_P_ ev_cleanup *w)
{
clear_pending (EV_A_ (W)w);
if (expect_false (!ev_is_active (w)))
return;
EV_FREQUENT_CHECK;
ev_ref (EV_A);
{
int active = ev_active (w);
cleanups [active - 1] = cleanups [--cleanupcnt];
ev_active (cleanups [active - 1]) = active;
}
ev_stop (EV_A_ (W)w);
EV_FREQUENT_CHECK;
}
#endif
#if EV_ASYNC_ENABLE #if EV_ASYNC_ENABLE
void void
ev_async_start (EV_P_ ev_async *w) ev_async_start (EV_P_ ev_async *w)
@ -3817,7 +3874,5 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
#include "ev_wrap.h" #include "ev_wrap.h"
#endif #endif
#ifdef __cplusplus EV_CPP(})
}
#endif

137
deps/libev/ev.h

@ -1,7 +1,7 @@
/* /*
* libev native API header * libev native API header
* *
* Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de> * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modifica- * Redistribution and use in source and binary forms, with or without modifica-
@ -41,9 +41,13 @@
#define EV_H_ #define EV_H_
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { # define EV_CPP(x) x
#else
# define EV_CPP(x)
#endif #endif
EV_CPP(extern "C" {)
/*****************************************************************************/ /*****************************************************************************/
/* pre-4.0 compatibility */ /* pre-4.0 compatibility */
@ -99,6 +103,10 @@ extern "C" {
# define EV_FORK_ENABLE EV_FEATURE_WATCHERS # define EV_FORK_ENABLE EV_FEATURE_WATCHERS
#endif #endif
#ifndef EV_CLEANUP_ENABLE
# define EV_CLEANUP_ENABLE EV_FEATURE_WATCHERS
#endif
#ifndef EV_SIGNAL_ENABLE #ifndef EV_SIGNAL_ENABLE
# define EV_SIGNAL_ENABLE EV_FEATURE_WATCHERS # define EV_SIGNAL_ENABLE EV_FEATURE_WATCHERS
#endif #endif
@ -150,14 +158,14 @@ typedef double ev_tstamp;
/* support multiple event loops? */ /* support multiple event loops? */
#if EV_MULTIPLICITY #if EV_MULTIPLICITY
struct ev_loop; struct ev_loop;
# define EV_P struct ev_loop *loop # define EV_P struct ev_loop *loop /* a loop as sole parameter in a declaration */
# define EV_P_ EV_P, # define EV_P_ EV_P, /* a loop as first of multiple parameters */
# define EV_A loop # define EV_A loop /* a loop as sole argument to a function call */
# define EV_A_ EV_A, # define EV_A_ EV_A, /* a loop as first of multiple arguments */
# define EV_DEFAULT_UC ev_default_loop_uc () # define EV_DEFAULT_UC ev_default_loop_uc_ () /* the default loop, if initialised, as sole arg */
# define EV_DEFAULT_UC_ EV_DEFAULT_UC, # define EV_DEFAULT_UC_ EV_DEFAULT_UC, /* the default loop as first of multiple arguments */
# define EV_DEFAULT ev_default_loop (0) # define EV_DEFAULT ev_default_loop (0) /* the default loop as sole arg */
# define EV_DEFAULT_ EV_DEFAULT, # define EV_DEFAULT_ EV_DEFAULT, /* the default loop as first of multiple arguments */
#else #else
# define EV_P void # define EV_P void
# define EV_P_ # define EV_P_
@ -170,12 +178,14 @@ struct ev_loop;
# undef EV_EMBED_ENABLE # undef EV_EMBED_ENABLE
#endif #endif
/* EV_INLINE is used for functions in header files */
#if __STDC_VERSION__ >= 199901L || __GNUC__ >= 3 #if __STDC_VERSION__ >= 199901L || __GNUC__ >= 3
# define EV_INLINE static inline # define EV_INLINE static inline
#else #else
# define EV_INLINE static # define EV_INLINE static
#endif #endif
/* EV_PROTOTYPES can be sued to switch of prototype declarations */
#ifndef EV_PROTOTYPES #ifndef EV_PROTOTYPES
# define EV_PROTOTYPES 1 # define EV_PROTOTYPES 1
#endif #endif
@ -183,18 +193,20 @@ struct ev_loop;
/*****************************************************************************/ /*****************************************************************************/
#define EV_VERSION_MAJOR 4 #define EV_VERSION_MAJOR 4
#define EV_VERSION_MINOR 0 #define EV_VERSION_MINOR 3
/* eventmask, revents, events... */ /* eventmask, revents, events... */
enum { enum {
EV_UNDEF = -1, /* guaranteed to be invalid */ EV_UNDEF = 0xFFFFFFFF, /* guaranteed to be invalid */
EV_NONE = 0x00, /* no events */ EV_NONE = 0x00, /* no events */
EV_READ = 0x01, /* ev_io detected read will not block */ EV_READ = 0x01, /* ev_io detected read will not block */
EV_WRITE = 0x02, /* ev_io detected write will not block */ EV_WRITE = 0x02, /* ev_io detected write will not block */
EV__IOFDSET = 0x80, /* internal use only */ EV__IOFDSET = 0x80, /* internal use only */
EV_IO = EV_READ, /* alias for type-detection */ EV_IO = EV_READ, /* alias for type-detection */
EV_TIMER = 0x00000100, /* timer timed out */ EV_TIMER = 0x00000100, /* timer timed out */
#if EV_COMPAT3
EV_TIMEOUT = EV_TIMER, /* pre 4.0 API compatibility */ EV_TIMEOUT = EV_TIMER, /* pre 4.0 API compatibility */
#endif
EV_PERIODIC = 0x00000200, /* periodic timer timed out */ EV_PERIODIC = 0x00000200, /* periodic timer timed out */
EV_SIGNAL = 0x00000400, /* signal was received */ EV_SIGNAL = 0x00000400, /* signal was received */
EV_CHILD = 0x00000800, /* child/pid had status change */ EV_CHILD = 0x00000800, /* child/pid had status change */
@ -204,7 +216,8 @@ enum {
EV_CHECK = 0x00008000, /* event loop finished poll */ EV_CHECK = 0x00008000, /* event loop finished poll */
EV_EMBED = 0x00010000, /* embedded event loop needs sweep */ EV_EMBED = 0x00010000, /* embedded event loop needs sweep */
EV_FORK = 0x00020000, /* event loop resumed in child */ EV_FORK = 0x00020000, /* event loop resumed in child */
EV_ASYNC = 0x00040000, /* async intra-loop signal */ EV_CLEANUP = 0x00040000, /* event loop resumed in child */
EV_ASYNC = 0x00080000, /* async intra-loop signal */
EV_CUSTOM = 0x01000000, /* for use by user code */ EV_CUSTOM = 0x01000000, /* for use by user code */
EV_ERROR = 0x80000000 /* sent when an error occurs */ EV_ERROR = 0x80000000 /* sent when an error occurs */
}; };
@ -383,12 +396,22 @@ typedef struct ev_check
#if EV_FORK_ENABLE #if EV_FORK_ENABLE
/* the callback gets invoked before check in the child process when a fork was detected */ /* the callback gets invoked before check in the child process when a fork was detected */
/* revent EV_FORK */
typedef struct ev_fork typedef struct ev_fork
{ {
EV_WATCHER (ev_fork) EV_WATCHER (ev_fork)
} ev_fork; } ev_fork;
#endif #endif
#if EV_CLEANUP_ENABLE
/* is invoked just before the loop gets destroyed */
/* revent EV_CLEANUP */
typedef struct ev_cleanup
{
EV_WATCHER (ev_cleanup)
} ev_cleanup;
#endif
#if EV_EMBED_ENABLE #if EV_EMBED_ENABLE
/* used to embed an event loop inside another */ /* used to embed an event loop inside another */
/* the callback gets invoked when the event loop has handled events, and can be 0 */ /* the callback gets invoked when the event loop has handled events, and can be 0 */
@ -404,6 +427,9 @@ typedef struct ev_embed
ev_periodic periodic; /* unused */ ev_periodic periodic; /* unused */
ev_idle idle; /* unused */ ev_idle idle; /* unused */
ev_fork fork; /* private */ ev_fork fork; /* private */
#if EV_CLEANUP_ENABLE
ev_cleanup cleanup; /* unused */
#endif
} ev_embed; } ev_embed;
#endif #endif
@ -442,6 +468,9 @@ union ev_any_watcher
#if EV_FORK_ENABLE #if EV_FORK_ENABLE
struct ev_fork fork; struct ev_fork fork;
#endif #endif
#if EV_CLEANUP_ENABLE
struct ev_cleanup cleanup;
#endif
#if EV_EMBED_ENABLE #if EV_EMBED_ENABLE
struct ev_embed embed; struct ev_embed embed;
#endif #endif
@ -462,7 +491,8 @@ enum {
#if EV_COMPAT3 #if EV_COMPAT3
EVFLAG_NOSIGFD = 0, /* compatibility to pre-3.9 */ EVFLAG_NOSIGFD = 0, /* compatibility to pre-3.9 */
#endif #endif
EVFLAG_SIGNALFD = 0x00200000U /* attempt to use signalfd */ EVFLAG_SIGNALFD = 0x00200000U, /* attempt to use signalfd */
EVFLAG_NOSIGMASK = 0x00400000U /* avoid modifying the signal mask */
}; };
/* method bits to be ored together */ /* method bits to be ored together */
@ -473,7 +503,8 @@ enum {
EVBACKEND_KQUEUE = 0x00000008U, /* bsd */ EVBACKEND_KQUEUE = 0x00000008U, /* bsd */
EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /* NYI */ EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /* NYI */
EVBACKEND_PORT = 0x00000020U, /* solaris 10 */ EVBACKEND_PORT = 0x00000020U, /* solaris 10 */
EVBACKEND_ALL = 0x0000003FU EVBACKEND_ALL = 0x0000003FU, /* all known backends */
EVBACKEND_MASK = 0x0000FFFFU /* all future backends */
}; };
#if EV_PROTOTYPES #if EV_PROTOTYPES
@ -502,41 +533,33 @@ void ev_set_allocator (void *(*cb)(void *ptr, long size));
void ev_set_syserr_cb (void (*cb)(const char *msg)); void ev_set_syserr_cb (void (*cb)(const char *msg));
#if EV_MULTIPLICITY #if EV_MULTIPLICITY
/* the default loop is the only one that handles signals and child watchers */
/* you can call this as often as you like */
struct ev_loop *ev_default_loop (unsigned int flags EV_CPP (= 0));
EV_INLINE struct ev_loop * EV_INLINE struct ev_loop *
ev_default_loop_uc (void) ev_default_loop_uc_ (void)
{ {
extern struct ev_loop *ev_default_loop_ptr; extern struct ev_loop *ev_default_loop_ptr;
return ev_default_loop_ptr; return ev_default_loop_ptr;
} }
/* the default loop is the only one that handles signals and child watchers */ EV_INLINE int
/* you can call this as often as you like */ ev_is_default_loop (EV_P)
EV_INLINE struct ev_loop *
ev_default_loop (unsigned int flags)
{ {
struct ev_loop *loop = ev_default_loop_uc (); return EV_A == EV_DEFAULT_UC;
if (!loop)
{
extern struct ev_loop *ev_default_loop_init (unsigned int flags);
loop = ev_default_loop_init (flags);
}
return loop;
} }
/* create and destroy alternative loops that don't handle signals */ /* create and destroy alternative loops that don't handle signals */
struct ev_loop *ev_loop_new (unsigned int flags); struct ev_loop *ev_loop_new (unsigned int flags EV_CPP (= 0));
void ev_loop_destroy (EV_P);
void ev_loop_fork (EV_P);
ev_tstamp ev_now (EV_P); /* time w.r.t. timers and the eventloop, updated after each poll */ ev_tstamp ev_now (EV_P); /* time w.r.t. timers and the eventloop, updated after each poll */
#else #else
int ev_default_loop (unsigned int flags); /* returns true when successful */ int ev_default_loop (unsigned int flags EV_CPP (= 0)); /* returns true when successful */
EV_INLINE ev_tstamp EV_INLINE ev_tstamp
ev_now (void) ev_now (void)
@ -545,26 +568,24 @@ ev_now (void)
return ev_rt_now; return ev_rt_now;
} }
#endif /* multiplicity */
/* looks weird, but ev_is_default_loop (EV_A) still works if this exists */
EV_INLINE int EV_INLINE int
ev_is_default_loop (EV_P) ev_is_default_loop (void)
{ {
#if EV_MULTIPLICITY
extern struct ev_loop *ev_default_loop_ptr;
return !!(EV_A == ev_default_loop_ptr);
#else
return 1; return 1;
#endif
} }
void ev_default_destroy (void); /* destroy the default loop */ #endif /* multiplicity */
/* this needs to be called after fork, to duplicate the default loop */
/* if you create alternative loops you have to call ev_loop_fork on them */ /* destroy event loops, also works for the default loop */
void ev_loop_destroy (EV_P);
/* this needs to be called after fork, to duplicate the loop */
/* when you want to re-use it in the child */
/* you can call it in either the parent or the child */ /* you can call it in either the parent or the child */
/* you can actually call it at any time, anywhere :) */ /* you can actually call it at any time, anywhere :) */
void ev_default_fork (void); void ev_loop_fork (EV_P);
unsigned int ev_backend (EV_P); /* backend in use by loop */ unsigned int ev_backend (EV_P); /* backend in use by loop */
@ -593,8 +614,8 @@ enum {
}; };
#if EV_PROTOTYPES #if EV_PROTOTYPES
void ev_run (EV_P_ int flags); void ev_run (EV_P_ int flags EV_CPP (= 0));
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 */ void ev_break (EV_P_ int how EV_CPP (= EVBREAK_ONE)); /* break out of the loop */
/* /*
* ref/unref can be used to add or remove a refcount on the mainloop. every watcher * ref/unref can be used to add or remove a refcount on the mainloop. every watcher
@ -656,6 +677,7 @@ void ev_resume (EV_P);
#define ev_check_set(ev) /* nop, yes, this is a serious in-joke */ #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_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_fork_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_cleanup_set(ev) /* nop, yes, this is a serious in-joke */
#define ev_async_set(ev) /* nop, yes, this is a serious in-joke */ #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_io_init(ev,cb,fd,events) do { ev_init ((ev), (cb)); ev_io_set ((ev),(fd),(events)); } while (0)
@ -669,6 +691,7 @@ void ev_resume (EV_P);
#define ev_check_init(ev,cb) do { ev_init ((ev), (cb)); ev_check_set ((ev)); } while (0) #define ev_check_init(ev,cb) do { ev_init ((ev), (cb)); ev_check_set ((ev)); } while (0)
#define ev_embed_init(ev,cb,other) do { ev_init ((ev), (cb)); ev_embed_set ((ev),(other)); } while (0) #define ev_embed_init(ev,cb,other) do { ev_init ((ev), (cb)); ev_embed_set ((ev),(other)); } while (0)
#define ev_fork_init(ev,cb) do { ev_init ((ev), (cb)); ev_fork_set ((ev)); } while (0) #define ev_fork_init(ev,cb) do { ev_init ((ev), (cb)); ev_fork_set ((ev)); } while (0)
#define ev_cleanup_init(ev,cb) do { ev_init ((ev), (cb)); ev_cleanup_set ((ev)); } while (0)
#define ev_async_init(ev,cb) do { ev_init ((ev), (cb)); ev_async_set ((ev)); } while (0) #define ev_async_init(ev,cb) do { ev_init ((ev), (cb)); ev_async_set ((ev)); } while (0)
#define ev_is_pending(ev) (0 + ((ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */ #define ev_is_pending(ev) (0 + ((ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */
@ -699,6 +722,7 @@ void ev_resume (EV_P);
void ev_feed_event (EV_P_ void *w, int revents); void ev_feed_event (EV_P_ void *w, int revents);
void ev_feed_fd_event (EV_P_ int fd, int revents); void ev_feed_fd_event (EV_P_ int fd, int revents);
#if EV_SIGNAL_ENABLE #if EV_SIGNAL_ENABLE
void ev_feed_signal (int signum);
void ev_feed_signal_event (EV_P_ int signum); void ev_feed_signal_event (EV_P_ int signum);
#endif #endif
void ev_invoke (EV_P_ void *w, int revents); void ev_invoke (EV_P_ void *w, int revents);
@ -758,6 +782,11 @@ void ev_fork_start (EV_P_ ev_fork *w);
void ev_fork_stop (EV_P_ ev_fork *w); void ev_fork_stop (EV_P_ ev_fork *w);
# endif # endif
# if EV_CLEANUP_ENABLE
void ev_cleanup_start (EV_P_ ev_cleanup *w);
void ev_cleanup_stop (EV_P_ ev_cleanup *w);
# endif
# if EV_EMBED_ENABLE # if EV_EMBED_ENABLE
/* only supported when loop to be embedded is in fact embeddable */ /* only supported when loop to be embedded is in fact embeddable */
void ev_embed_start (EV_P_ ev_embed *w); void ev_embed_start (EV_P_ ev_embed *w);
@ -780,10 +809,12 @@ void ev_async_send (EV_P_ ev_async *w);
#if EV_PROTOTYPES #if EV_PROTOTYPES
EV_INLINE void ev_loop (EV_P_ int flags) { ev_run (EV_A_ flags); } 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 ); } EV_INLINE void ev_unloop (EV_P_ int how ) { ev_break (EV_A_ how ); }
EV_INLINE void ev_default_destroy (void) { ev_loop_destroy (EV_DEFAULT); }
EV_INLINE void ev_default_fork (void) { ev_loop_fork (EV_DEFAULT); }
#if EV_FEATURE_API #if EV_FEATURE_API
EV_INLINE void ev_loop_count (EV_P) { ev_iteration (EV_A); } EV_INLINE unsigned int ev_loop_count (EV_P) { return ev_iteration (EV_A); }
EV_INLINE void ev_loop_depth (EV_P) { ev_depth (EV_A); } EV_INLINE unsigned int ev_loop_depth (EV_P) { return ev_depth (EV_A); }
EV_INLINE void ev_loop_verify (EV_P) { ev_verify (EV_A); } EV_INLINE void ev_loop_verify (EV_P) { ev_verify (EV_A); }
#endif #endif
#endif #endif
#else #else
@ -792,9 +823,7 @@ void ev_async_send (EV_P_ ev_async *w);
#endif #endif
#ifdef __cplusplus EV_CPP(})
}
#endif
#endif #endif

1170
deps/libev/ev.pod

File diff suppressed because it is too large

41
deps/libev/ev_epoll.c

@ -1,7 +1,7 @@
/* /*
* libev epoll fd activity backend * libev epoll fd activity backend
* *
* Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de> * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modifica- * Redistribution and use in source and binary forms, with or without modifica-
@ -53,7 +53,8 @@
* (such as files). while not critical, no other advanced interface * (such as files). while not critical, no other advanced interface
* seems to share this (rather non-unixy) limitation. * seems to share this (rather non-unixy) limitation.
* e) epoll claims to be embeddable, but in practise you never get * e) epoll claims to be embeddable, but in practise you never get
* a ready event for the epoll fd. * a ready event for the epoll fd (broken: <=2.6.26, working: >=2.6.32).
* f) epoll_ctl returning EPERM means the fd is always ready.
* *
* lots of "weird code" and complication handling in this file is due * 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 * to these design problems with epoll, as we try very hard to avoid
@ -64,6 +65,8 @@
#include <sys/epoll.h> #include <sys/epoll.h>
#define EV_EMASK_EPERM 0x80
static void static void
epoll_modify (EV_P_ int fd, int oev, int nev) epoll_modify (EV_P_ int fd, int oev, int nev)
{ {
@ -112,6 +115,21 @@ epoll_modify (EV_P_ int fd, int oev, int nev)
if (!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev)) if (!epoll_ctl (backend_fd, EPOLL_CTL_MOD, fd, &ev))
return; return;
} }
else if (expect_true (errno == EPERM))
{
/* EPERM means the fd is always ready, but epoll is too snobbish */
/* to handle it, unlike select or poll. */
anfds [fd].emask = EV_EMASK_EPERM;
/* add fd to epoll_eperms, if not already inside */
if (!(oldmask & EV_EMASK_EPERM))
{
array_needsize (int, epoll_eperms, epoll_epermmax, epoll_epermcnt + 1, EMPTY2);
epoll_eperms [epoll_epermcnt++] = fd;
}
return;
}
fd_kill (EV_A_ fd); fd_kill (EV_A_ fd);
@ -125,11 +143,12 @@ epoll_poll (EV_P_ ev_tstamp timeout)
{ {
int i; int i;
int eventcnt; int eventcnt;
/* epoll wait times cannot be larger than (LONG_MAX - 999UL) / HZ msecs, which is below */ /* epoll wait times cannot be larger than (LONG_MAX - 999UL) / HZ msecs, which is below */
/* the default libev max wait time, however. */ /* the default libev max wait time, however. */
EV_RELEASE_CB; EV_RELEASE_CB;
eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax, (int)ceil (timeout * 1000.)); eventcnt = epoll_wait (backend_fd, epoll_events, epoll_eventmax,
epoll_epermcnt ? 0 : (int)ceil (timeout * 1000.));
EV_ACQUIRE_CB; EV_ACQUIRE_CB;
if (expect_false (eventcnt < 0)) if (expect_false (eventcnt < 0))
@ -150,6 +169,7 @@ epoll_poll (EV_P_ ev_tstamp timeout)
| (ev->events & (EPOLLIN | EPOLLERR | EPOLLHUP) ? EV_READ : 0); | (ev->events & (EPOLLIN | EPOLLERR | EPOLLHUP) ? EV_READ : 0);
/* check for spurious notification */ /* check for spurious notification */
/* we assume that fd is always in range, as we never shrink the anfds array */
if (expect_false ((uint32_t)anfds [fd].egen != (uint32_t)(ev->data.u64 >> 32))) if (expect_false ((uint32_t)anfds [fd].egen != (uint32_t)(ev->data.u64 >> 32)))
{ {
/* recreate kernel state */ /* recreate kernel state */
@ -185,6 +205,18 @@ epoll_poll (EV_P_ ev_tstamp timeout)
epoll_eventmax = array_nextsize (sizeof (struct epoll_event), epoll_eventmax, epoll_eventmax + 1); epoll_eventmax = array_nextsize (sizeof (struct epoll_event), epoll_eventmax, epoll_eventmax + 1);
epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax); epoll_events = (struct epoll_event *)ev_malloc (sizeof (struct epoll_event) * epoll_eventmax);
} }
/* now synthesize events for all fds where epoll fails, while select works... */
for (i = epoll_epermcnt; i--; )
{
int fd = epoll_eperms [i];
unsigned char events = anfds [fd].events & (EV_READ | EV_WRITE);
if (anfds [fd].emask & EV_EMASK_EPERM && events)
fd_event (EV_A_ fd, events);
else
epoll_eperms [i] = epoll_eperms [--epoll_epermcnt];
}
} }
int inline_size int inline_size
@ -216,6 +248,7 @@ void inline_size
epoll_destroy (EV_P) epoll_destroy (EV_P)
{ {
ev_free (epoll_events); ev_free (epoll_events);
array_free (epoll_eperm, EMPTY);
} }
void inline_size void inline_size

29
deps/libev/ev_port.c

@ -37,6 +37,17 @@
* either the BSD or the GPL. * either the BSD or the GPL.
*/ */
/* useful reading:
*
* http://bugs.opensolaris.org/view_bug.do?bug_id=6268715 (random results)
* http://bugs.opensolaris.org/view_bug.do?bug_id=6455223 (just totally broken)
* http://bugs.opensolaris.org/view_bug.do?bug_id=6873782 (manpage ETIME)
* http://bugs.opensolaris.org/view_bug.do?bug_id=6874410 (implementation ETIME)
* http://www.mail-archive.com/networking-discuss@opensolaris.org/msg11898.html ETIME vs. nget
* http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/gen/event_port.c (libc)
* http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/uts/common/fs/portfs/port.c#1325 (kernel)
*/
#include <sys/types.h> #include <sys/types.h>
#include <sys/time.h> #include <sys/time.h>
#include <poll.h> #include <poll.h>
@ -85,18 +96,20 @@ port_poll (EV_P_ ev_tstamp timeout)
struct timespec ts; struct timespec ts;
uint_t nget = 1; uint_t nget = 1;
/* we initialise this to something we will skip in the loop, as */
/* port_getn can return with nget unchanged, but no indication */
/* whether it was the original value or has been updated :/ */
port_events [0].portev_source = 0;
EV_RELEASE_CB; EV_RELEASE_CB;
EV_TS_SET (ts, timeout); EV_TS_SET (ts, timeout);
res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts); res = port_getn (backend_fd, port_events, port_eventmax, &nget, &ts);
EV_ACQUIRE_CB; EV_ACQUIRE_CB;
if (res == -1) /* port_getn may or may not set nget on error */
{ /* so we rely on port_events [0].portev_source not being updated */
if (errno != EINTR && errno != ETIME) if (res == -1 && errno != ETIME && errno != EINTR)
ev_syserr ("(libev) port_getn (see http://bugs.opensolaris.org/view_bug.do?bug_id=6268715, try LIBEV_FLAGS=3 env variable)"); ev_syserr ("(libev) port_getn (see http://bugs.opensolaris.org/view_bug.do?bug_id=6268715, try LIBEV_FLAGS=3 env variable)");
return;
}
for (i = 0; i < nget; ++i) for (i = 0; i < nget; ++i)
{ {
@ -130,6 +143,8 @@ port_init (EV_P_ int flags)
if ((backend_fd = port_create ()) < 0) if ((backend_fd = port_create ()) < 0)
return 0; return 0;
assert (("libev: PORT_SOURCE_FD must not be zero", PORT_SOURCE_FD));
fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */ fcntl (backend_fd, F_SETFD, FD_CLOEXEC); /* not sure if necessary, hopefully doesn't hurt */
backend_fudge = 1e-3; /* needed to compensate for port_getn returning early */ backend_fudge = 1e-3; /* needed to compensate for port_getn returning early */

18
deps/libev/ev_vars.h

@ -1,7 +1,7 @@
/* /*
* loop member variable declarations * loop member variable declarations
* *
* Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de> * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without modifica- * Redistribution and use in source and binary forms, with or without modifica-
@ -102,6 +102,9 @@ VARx(int, pollidxmax)
#if EV_USE_EPOLL || EV_GENWRAP #if EV_USE_EPOLL || EV_GENWRAP
VARx(struct epoll_event *, epoll_events) VARx(struct epoll_event *, epoll_events)
VARx(int, epoll_eventmax) VARx(int, epoll_eventmax)
VARx(int *, epoll_eperms)
VARx(int, epoll_epermcnt)
VARx(int, epoll_epermmax)
#endif #endif
#if EV_USE_KQUEUE || EV_GENWRAP #if EV_USE_KQUEUE || EV_GENWRAP
@ -117,6 +120,10 @@ VARx(struct port_event *, port_events)
VARx(int, port_eventmax) VARx(int, port_eventmax)
#endif #endif
#if EV_USE_IOCP || EV_GENWRAP
VARx(HANDLE, iocp)
#endif
VARx(int *, fdchanges) VARx(int *, fdchanges)
VARx(int, fdchangemax) VARx(int, fdchangemax)
VARx(int, fdchangecnt) VARx(int, fdchangecnt)
@ -152,6 +159,12 @@ VARx(int, forkmax)
VARx(int, forkcnt) VARx(int, forkcnt)
#endif #endif
#if EV_CLEANUP_ENABLE || EV_GENWRAP
VARx(struct ev_cleanup **, cleanups)
VARx(int, cleanupmax)
VARx(int, cleanupcnt)
#endif
#if EV_ASYNC_ENABLE || EV_GENWRAP #if EV_ASYNC_ENABLE || EV_GENWRAP
VARx(EV_ATOMIC_T, async_pending) VARx(EV_ATOMIC_T, async_pending)
VARx(struct ev_async **, asyncs) VARx(struct ev_async **, asyncs)
@ -167,12 +180,15 @@ VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE])
#endif #endif
VARx(EV_ATOMIC_T, sig_pending) VARx(EV_ATOMIC_T, sig_pending)
VARx(int, nosigmask)
#if EV_USE_SIGNALFD || EV_GENWRAP #if EV_USE_SIGNALFD || EV_GENWRAP
VARx(int, sigfd) VARx(int, sigfd)
VARx(ev_io, sigfd_w) VARx(ev_io, sigfd_w)
VARx(sigset_t, sigfd_set) VARx(sigset_t, sigfd_set)
#endif #endif
VARx(unsigned int, origflags) /* original loop flags */
#if EV_FEATURE_API || EV_GENWRAP #if EV_FEATURE_API || EV_GENWRAP
VARx(unsigned int, loop_count) /* total number of loop iterations/blocks */ VARx(unsigned int, loop_count) /* total number of loop iterations/blocks */
VARx(unsigned int, loop_depth) /* #ev_run enters - #ev_run leaves */ VARx(unsigned int, loop_depth) /* #ev_run enters - #ev_run leaves */

18
deps/libev/ev_wrap.h

@ -40,6 +40,9 @@
#define pollidxmax ((loop)->pollidxmax) #define pollidxmax ((loop)->pollidxmax)
#define epoll_events ((loop)->epoll_events) #define epoll_events ((loop)->epoll_events)
#define epoll_eventmax ((loop)->epoll_eventmax) #define epoll_eventmax ((loop)->epoll_eventmax)
#define epoll_eperms ((loop)->epoll_eperms)
#define epoll_epermcnt ((loop)->epoll_epermcnt)
#define epoll_epermmax ((loop)->epoll_epermmax)
#define kqueue_changes ((loop)->kqueue_changes) #define kqueue_changes ((loop)->kqueue_changes)
#define kqueue_changemax ((loop)->kqueue_changemax) #define kqueue_changemax ((loop)->kqueue_changemax)
#define kqueue_changecnt ((loop)->kqueue_changecnt) #define kqueue_changecnt ((loop)->kqueue_changecnt)
@ -47,6 +50,7 @@
#define kqueue_eventmax ((loop)->kqueue_eventmax) #define kqueue_eventmax ((loop)->kqueue_eventmax)
#define port_events ((loop)->port_events) #define port_events ((loop)->port_events)
#define port_eventmax ((loop)->port_eventmax) #define port_eventmax ((loop)->port_eventmax)
#define iocp ((loop)->iocp)
#define fdchanges ((loop)->fdchanges) #define fdchanges ((loop)->fdchanges)
#define fdchangemax ((loop)->fdchangemax) #define fdchangemax ((loop)->fdchangemax)
#define fdchangecnt ((loop)->fdchangecnt) #define fdchangecnt ((loop)->fdchangecnt)
@ -69,6 +73,9 @@
#define forks ((loop)->forks) #define forks ((loop)->forks)
#define forkmax ((loop)->forkmax) #define forkmax ((loop)->forkmax)
#define forkcnt ((loop)->forkcnt) #define forkcnt ((loop)->forkcnt)
#define cleanups ((loop)->cleanups)
#define cleanupmax ((loop)->cleanupmax)
#define cleanupcnt ((loop)->cleanupcnt)
#define async_pending ((loop)->async_pending) #define async_pending ((loop)->async_pending)
#define asyncs ((loop)->asyncs) #define asyncs ((loop)->asyncs)
#define asyncmax ((loop)->asyncmax) #define asyncmax ((loop)->asyncmax)
@ -78,9 +85,11 @@
#define fs_2625 ((loop)->fs_2625) #define fs_2625 ((loop)->fs_2625)
#define fs_hash ((loop)->fs_hash) #define fs_hash ((loop)->fs_hash)
#define sig_pending ((loop)->sig_pending) #define sig_pending ((loop)->sig_pending)
#define nosigmask ((loop)->nosigmask)
#define sigfd ((loop)->sigfd) #define sigfd ((loop)->sigfd)
#define sigfd_w ((loop)->sigfd_w) #define sigfd_w ((loop)->sigfd_w)
#define sigfd_set ((loop)->sigfd_set) #define sigfd_set ((loop)->sigfd_set)
#define origflags ((loop)->origflags)
#define loop_count ((loop)->loop_count) #define loop_count ((loop)->loop_count)
#define loop_depth ((loop)->loop_depth) #define loop_depth ((loop)->loop_depth)
#define userdata ((loop)->userdata) #define userdata ((loop)->userdata)
@ -128,6 +137,9 @@
#undef pollidxmax #undef pollidxmax
#undef epoll_events #undef epoll_events
#undef epoll_eventmax #undef epoll_eventmax
#undef epoll_eperms
#undef epoll_epermcnt
#undef epoll_epermmax
#undef kqueue_changes #undef kqueue_changes
#undef kqueue_changemax #undef kqueue_changemax
#undef kqueue_changecnt #undef kqueue_changecnt
@ -135,6 +147,7 @@
#undef kqueue_eventmax #undef kqueue_eventmax
#undef port_events #undef port_events
#undef port_eventmax #undef port_eventmax
#undef iocp
#undef fdchanges #undef fdchanges
#undef fdchangemax #undef fdchangemax
#undef fdchangecnt #undef fdchangecnt
@ -157,6 +170,9 @@
#undef forks #undef forks
#undef forkmax #undef forkmax
#undef forkcnt #undef forkcnt
#undef cleanups
#undef cleanupmax
#undef cleanupcnt
#undef async_pending #undef async_pending
#undef asyncs #undef asyncs
#undef asyncmax #undef asyncmax
@ -166,9 +182,11 @@
#undef fs_2625 #undef fs_2625
#undef fs_hash #undef fs_hash
#undef sig_pending #undef sig_pending
#undef nosigmask
#undef sigfd #undef sigfd
#undef sigfd_w #undef sigfd_w
#undef sigfd_set #undef sigfd_set
#undef origflags
#undef loop_count #undef loop_count
#undef loop_depth #undef loop_depth
#undef userdata #undef userdata

9
deps/libev/event.c

@ -110,7 +110,7 @@ void event_base_free (struct event_base *base)
dLOOPbase; dLOOPbase;
#if EV_MULTIPLICITY #if EV_MULTIPLICITY
if (ev_default_loop (EVFLAG_AUTO) != loop) if (!ev_is_default_loop (loop))
ev_loop_destroy (loop); ev_loop_destroy (loop);
#endif #endif
} }
@ -298,7 +298,12 @@ int event_pending (struct event *ev, short events, struct timeval *tv)
revents |= EV_TIMEOUT; revents |= EV_TIMEOUT;
if (tv) if (tv)
EV_TV_SET (tv, ev_now (EV_A)); /* not sure if this is right :) */ {
ev_tstamp at = ev_now (EV_A);
tv->tv_sec = (long)at;
tv->tv_usec = (long)((at - (ev_tstamp)tv->tv_sec) * 1e6);
}
} }
return events & revents; return events & revents;

2
deps/libev/event.h

@ -95,6 +95,8 @@ struct event
short ev_events; short ev_events;
}; };
#define EV_READ EV_READ
#define EV_WRITE EV_WRITE
#define EV_PERSIST 0x10 #define EV_PERSIST 0x10
#define EVENT_SIGNAL(ev) ((int) (ev)->ev_fd) #define EVENT_SIGNAL(ev) ((int) (ev)->ev_fd)

Loading…
Cancel
Save