diff options
Diffstat (limited to 'src/util/k5ev')
| -rw-r--r-- | src/util/k5ev/Makefile.in | 52 | ||||
| -rw-r--r-- | src/util/k5ev/README | 31 | ||||
| -rw-r--r-- | src/util/k5ev/Symbols.ev | 73 | ||||
| -rw-r--r-- | src/util/k5ev/deps | 7 | ||||
| -rw-r--r-- | src/util/k5ev/ev.c | 3913 | ||||
| -rw-r--r-- | src/util/k5ev/ev.h | 829 | ||||
| -rw-r--r-- | src/util/k5ev/ev_poll.c | 148 | ||||
| -rw-r--r-- | src/util/k5ev/ev_select.c | 310 | ||||
| -rw-r--r-- | src/util/k5ev/ev_vars.h | 203 | ||||
| -rw-r--r-- | src/util/k5ev/ev_win32.c | 153 | ||||
| -rw-r--r-- | src/util/k5ev/ev_wrap.h | 196 | ||||
| -rw-r--r-- | src/util/k5ev/libverto-k5ev.exports | 3 | ||||
| -rw-r--r-- | src/util/k5ev/verto-k5ev.c | 215 | ||||
| -rw-r--r-- | src/util/k5ev/verto-k5ev.h | 33 | ||||
| -rw-r--r-- | src/util/k5ev/verto-libev.c | 199 |
15 files changed, 0 insertions, 6365 deletions
diff --git a/src/util/k5ev/Makefile.in b/src/util/k5ev/Makefile.in deleted file mode 100644 index b80a60dfb..000000000 --- a/src/util/k5ev/Makefile.in +++ /dev/null @@ -1,52 +0,0 @@ -mydir=util$(S)k5ev -BUILDTOP=$(REL)..$(S).. -RELDIR=../util/k5ev -DEFS= - -SED = sed - -LIBBASE=verto-k5ev -LIBMAJOR=0 -LIBMINOR=0 - -LOCALINCLUDES=-I. -I$(srcdir)/../verto - -# Turn off extra warnings since we're not going to clean up libev's code. -WARN_CFLAGS= - -STLIBOBJS=verto-k5ev.o -LIBOBJS=$(OUTPRE)verto-k5ev.$(OBJEXT) -SRCS=verto-k5ev.c - -STOBJLISTS=OBJS.ST -SHLIB_EXPLIBS= $(LIBS) -lverto -lm # libm needed for ceil() currently. -SHLIB_DIRS=-L$(TOPLIBD) -SHLIB_RDIRS=$(KRB5_LIBDIR) - -VERTO_K5EV_HDR=$(BUILDTOP)$(S)include$(S)verto-k5ev.h - -all-unix:: all-liblinks includes - -install-unix:: install-libs - -clean-unix:: clean-liblinks clean-libs clean-libobjs - $(RM) $(VERTO_K5EV_HDR) - -includes:: $(VERTO_K5EV_HDR) -depend:: $(VERTO_K5EV_HDR) - -$(VERTO_K5EV_HDR): $(srcdir)/verto-k5ev.h - $(RM) $@ - $(CP) $(srcdir)/verto-k5ev.h $@ - -rename.h: $(srcdir)/Symbols.ev - $(RM) $@ - $(SED) -e 's/.*/#define & k5&/' < $(srcdir)/Symbols.ev > $@ - -clean:: - $(RM) rename.h - -depend:: rename.h - -@lib_frag@ -@libobj_frag@ diff --git a/src/util/k5ev/README b/src/util/k5ev/README deleted file mode 100644 index 7a14f1327..000000000 --- a/src/util/k5ev/README +++ /dev/null @@ -1,31 +0,0 @@ -This directory builds a private libverto module using an embedded -libev with renamed symbols (so we don't leak libev symbols into the -namespace on platforms where we can't control the export list). - -libev has built-in support for this kind of embedding, so we don't -have to modify the libev sources. Following libev's documentation, -the following files have been copied from the ev sources: - - ev.h - ev_vars.h - ev_wrap.h - ev.c - ev_select.c - ev_poll.c - ev_win32.c - Symbols.ev - -(Symbols.ev wasn't included in the 4.04 tar file due to an oversight, -so it is taken from the appropriate tag in libev's source repository.) - -To rename the exported symbols, we create rename.h from Symbols.ev. -We also use Symbols.ev to construct the library export list. -(Renaming libev's symbols would be unnecessary if libev's embedding -had support for making its API symbols static, but it currently does -not.) The source file verto-k5ev.c wraps ev.c with appropriate -embedding defines, and then defines the libverto module functions -using the slightly modified contents of libverto's verto-ev.c. - -The libev upstream project page is at: - - http://software.schmorp.de/pkg/libev.html diff --git a/src/util/k5ev/Symbols.ev b/src/util/k5ev/Symbols.ev deleted file mode 100644 index 7a29a75cb..000000000 --- a/src/util/k5ev/Symbols.ev +++ /dev/null @@ -1,73 +0,0 @@ -ev_async_send -ev_async_start -ev_async_stop -ev_backend -ev_break -ev_check_start -ev_check_stop -ev_child_start -ev_child_stop -ev_cleanup_start -ev_cleanup_stop -ev_clear_pending -ev_default_loop -ev_default_loop_ptr -ev_depth -ev_embed_start -ev_embed_stop -ev_embed_sweep -ev_embeddable_backends -ev_feed_event -ev_feed_fd_event -ev_feed_signal -ev_feed_signal_event -ev_fork_start -ev_fork_stop -ev_idle_start -ev_idle_stop -ev_invoke -ev_invoke_pending -ev_io_start -ev_io_stop -ev_iteration -ev_loop_destroy -ev_loop_fork -ev_loop_new -ev_now -ev_now_update -ev_once -ev_pending_count -ev_periodic_again -ev_periodic_start -ev_periodic_stop -ev_prepare_start -ev_prepare_stop -ev_recommended_backends -ev_ref -ev_resume -ev_run -ev_set_allocator -ev_set_invoke_pending_cb -ev_set_io_collect_interval -ev_set_loop_release_cb -ev_set_syserr_cb -ev_set_timeout_collect_interval -ev_set_userdata -ev_signal_start -ev_signal_stop -ev_sleep -ev_stat_start -ev_stat_stat -ev_stat_stop -ev_supported_backends -ev_suspend -ev_time -ev_timer_again -ev_timer_remaining -ev_timer_start -ev_timer_stop -ev_unref -ev_userdata -ev_verify -ev_version_major -ev_version_minor diff --git a/src/util/k5ev/deps b/src/util/k5ev/deps deleted file mode 100644 index 5fd855249..000000000 --- a/src/util/k5ev/deps +++ /dev/null @@ -1,7 +0,0 @@ -# -# Generated makefile dependencies follow. -# -verto-k5ev.so verto-k5ev.po $(OUTPRE)verto-k5ev.$(OBJEXT): \ - $(BUILDTOP)/include/autoconf.h $(VERTO_DEPS) $(srcdir)/../verto/verto-module.h \ - ev.c ev.h ev_poll.c ev_select.c ev_vars.h ev_wrap.h \ - rename.h verto-k5ev.c verto-k5ev.h diff --git a/src/util/k5ev/ev.c b/src/util/k5ev/ev.c deleted file mode 100644 index 4187b18af..000000000 --- a/src/util/k5ev/ev.c +++ /dev/null @@ -1,3913 +0,0 @@ -/* - * libev event processing core, watcher management - * - * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modifica- - * tion, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- - * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- - * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- - * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License ("GPL") version 2 or any later version, - * in which case the provisions of the GPL are applicable instead of - * the above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the BSD license, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file under - * either the BSD or the GPL. - */ - -/* this big block deduces configuration from config.h */ -#ifndef EV_STANDALONE -# ifdef EV_CONFIG_H -# include EV_CONFIG_H -# else -# include "config.h" -# endif - -# if HAVE_CLOCK_SYSCALL -# ifndef EV_USE_CLOCK_SYSCALL -# define EV_USE_CLOCK_SYSCALL 1 -# ifndef EV_USE_REALTIME -# define EV_USE_REALTIME 0 -# endif -# ifndef EV_USE_MONOTONIC -# define EV_USE_MONOTONIC 1 -# endif -# endif -# elif !defined(EV_USE_CLOCK_SYSCALL) -# define EV_USE_CLOCK_SYSCALL 0 -# endif - -# if HAVE_CLOCK_GETTIME -# ifndef EV_USE_MONOTONIC -# define EV_USE_MONOTONIC 1 -# endif -# ifndef EV_USE_REALTIME -# define EV_USE_REALTIME 0 -# endif -# else -# ifndef EV_USE_MONOTONIC -# define EV_USE_MONOTONIC 0 -# endif -# ifndef EV_USE_REALTIME -# define EV_USE_REALTIME 0 -# endif -# endif - -# 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 - -# 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 - -# 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 - -# 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 - -# 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 - -# 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 - -# 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 - -# 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 - -# 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 - -#include <math.h> -#include <stdlib.h> -#include <string.h> -#include <fcntl.h> -#include <stddef.h> - -#include <stdio.h> - -#include <assert.h> -#include <errno.h> -#include <sys/types.h> -#include <time.h> -#include <limits.h> - -#include <signal.h> - -#ifdef EV_H -# include EV_H -#else -# include "ev.h" -#endif - -EV_CPP(extern "C" {) - -#ifndef _WIN32 -# include <sys/time.h> -# include <sys/wait.h> -# include <unistd.h> -#else -# include <io.h> -# define WIN32_LEAN_AND_MEAN -# include <windows.h> -# 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 */ -#if defined (EV_NSIG) -/* use what's provided */ -#elif defined (NSIG) -# define EV_NSIG (NSIG) -#elif defined(_NSIG) -# define EV_NSIG (_NSIG) -#elif defined (SIGMAX) -# define EV_NSIG (SIGMAX+1) -#elif defined (SIG_MAX) -# define EV_NSIG (SIG_MAX+1) -#elif defined (_SIG_MAX) -# define EV_NSIG (_SIG_MAX+1) -#elif defined (MAXSIG) -# define EV_NSIG (MAXSIG+1) -#elif defined (MAX_SIG) -# define EV_NSIG (MAX_SIG+1) -#elif defined (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, */ -/* but consider reporting it, too! :) */ -# define EV_NSIG 65 -#endif - -#ifndef EV_USE_CLOCK_SYSCALL -# if __linux && __GLIBC__ >= 2 -# define EV_USE_CLOCK_SYSCALL EV_FEATURE_OS -# else -# define EV_USE_CLOCK_SYSCALL 0 -# endif -#endif - -#ifndef EV_USE_MONOTONIC -# if defined (_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 -# define EV_USE_MONOTONIC EV_FEATURE_OS -# else -# define EV_USE_MONOTONIC 0 -# endif -#endif - -#ifndef EV_USE_REALTIME -# define EV_USE_REALTIME !EV_USE_CLOCK_SYSCALL -#endif - -#ifndef EV_USE_NANOSLEEP -# if _POSIX_C_SOURCE >= 199309L -# define EV_USE_NANOSLEEP EV_FEATURE_OS -# else -# define EV_USE_NANOSLEEP 0 -# endif -#endif - -#ifndef EV_USE_SELECT -# define EV_USE_SELECT EV_FEATURE_BACKENDS -#endif - -#ifndef EV_USE_POLL -# ifdef _WIN32 -# define EV_USE_POLL 0 -# else -# 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 EV_FEATURE_BACKENDS -# else -# define EV_USE_EPOLL 0 -# endif -#endif - -#ifndef EV_USE_KQUEUE -# define EV_USE_KQUEUE 0 -#endif - -#ifndef EV_USE_PORT -# define EV_USE_PORT 0 -#endif - -#ifndef EV_USE_INOTIFY -# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4)) -# define EV_USE_INOTIFY EV_FEATURE_OS -# else -# define EV_USE_INOTIFY 0 -# endif -#endif - -#ifndef EV_PID_HASHSIZE -# define EV_PID_HASHSIZE EV_FEATURE_DATA ? 16 : 1 -#endif - -#ifndef EV_INOTIFY_HASHSIZE -# 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 EV_FEATURE_OS -# else -# define EV_USE_EVENTFD 0 -# endif -#endif - -#ifndef EV_USE_SIGNALFD -# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7)) -# define EV_USE_SIGNALFD EV_FEATURE_OS -# else -# define EV_USE_SIGNALFD 0 -# endif -#endif - -#if 0 /* debugging */ -# define EV_VERIFY 3 -# define EV_USE_4HEAP 1 -# define EV_HEAP_CACHE_AT 1 -#endif - -#ifndef EV_VERIFY -# define EV_VERIFY (EV_FEATURE_API ? 1 : 0) -#endif - -#ifndef EV_USE_4HEAP -# define EV_USE_4HEAP EV_FEATURE_DATA -#endif - -#ifndef EV_HEAP_CACHE_AT -# define EV_HEAP_CACHE_AT EV_FEATURE_DATA -#endif - -/* on linux, we can use a (slow) syscall to avoid a dependency on pthread, */ -/* which makes programs even slower. might work on other unices, too. */ -#if EV_USE_CLOCK_SYSCALL -# include <syscall.h> -# ifdef SYS_clock_gettime -# define clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts)) -# undef EV_USE_MONOTONIC -# define EV_USE_MONOTONIC 1 -# else -# undef EV_USE_CLOCK_SYSCALL -# define EV_USE_CLOCK_SYSCALL 0 -# endif -#endif - -/* 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 -#endif - -#ifndef CLOCK_REALTIME -# undef EV_USE_REALTIME -# define EV_USE_REALTIME 0 -#endif - -#if !EV_STAT_ENABLE -# undef EV_USE_INOTIFY -# define EV_USE_INOTIFY 0 -#endif - -#if !EV_USE_NANOSLEEP -/* hp-ux has it in sys/time.h, which we unconditionally include above */ -# if !defined(_WIN32) && !defined(__hpux) -# include <sys/select.h> -# endif -#endif - -#if EV_USE_INOTIFY -# include <sys/statfs.h> -# include <sys/inotify.h> -/* some very old inotify.h headers don't have IN_DONT_FOLLOW */ -# ifndef IN_DONT_FOLLOW -# undef EV_USE_INOTIFY -# define EV_USE_INOTIFY 0 -# endif -#endif - -#if EV_SELECT_IS_WINSOCKET -# include <winsock.h> -#endif - -#if EV_USE_EVENTFD -/* our minimum requirement is glibc 2.7 which has the stub, but not the header */ -# include <stdint.h> -# ifndef EFD_NONBLOCK -# define EFD_NONBLOCK O_NONBLOCK -# endif -# ifndef EFD_CLOEXEC -# ifdef O_CLOEXEC -# define EFD_CLOEXEC O_CLOEXEC -# else -# define EFD_CLOEXEC 02000000 -# endif -# endif -EV_CPP(extern "C") int (eventfd) (unsigned int initval, int flags); -#endif - -#if EV_USE_SIGNALFD -/* our minimum requirement is glibc 2.7 which has the stub, but not the header */ -# include <stdint.h> -# ifndef SFD_NONBLOCK -# define SFD_NONBLOCK O_NONBLOCK -# endif -# ifndef SFD_CLOEXEC -# ifdef O_CLOEXEC -# define SFD_CLOEXEC O_CLOEXEC -# else -# define SFD_CLOEXEC 02000000 -# endif -# endif -EV_CPP (extern "C") int signalfd (int fd, const sigset_t *mask, int flags); - -struct signalfd_siginfo -{ - uint32_t ssi_signo; - char pad[128 - sizeof (uint32_t)]; -}; -#endif - -/**/ - -#if EV_VERIFY >= 3 -# define EV_FREQUENT_CHECK ev_verify (EV_A) -#else -# define EV_FREQUENT_CHECK do { } while (0) -#endif - -/* - * This is used to avoid floating point rounding problems. - * It is added to ev_rt_now when scheduling periodics - * to ensure progress, time-wise, even when rounding - * errors are against us. - * This value is good at least till the year 4000. - * Better solutions welcome. - */ -#define TIME_EPSILON 0.0001220703125 /* 1/8192 */ - -#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)) -#else -# define expect(expr,value) (expr) -# define noinline -# if __STDC_VERSION__ < 199901L && __GNUC__ < 2 -# define inline -# endif -#endif - -#define expect_false(expr) expect ((expr) != 0, 0) -#define expect_true(expr) expect ((expr) != 0, 1) -#define inline_size static inline - -#if EV_FEATURE_CODE -# define inline_speed static inline -#else -# define inline_speed static noinline -#endif - -#define NUMPRI (EV_MAXPRI - EV_MINPRI + 1) - -#if EV_MINPRI == EV_MAXPRI -# define ABSPRI(w) (((W)w), 0) -#else -# define ABSPRI(w) (((W)w)->priority - EV_MINPRI) -#endif - -#define EMPTY /* required for microsofts broken pseudo-c compiler */ -#define EMPTY2(a,b) /* used to suppress some warnings */ - -typedef ev_watcher *W; -typedef ev_watcher_list *WL; -typedef ev_watcher_time *WT; - -#define ev_active(w) ((W)(w))->active -#define ev_at(w) ((WT)(w))->at - -#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 architectures */ -static EV_ATOMIC_T have_realtime; /* did clock_gettime (CLOCK_REALTIME) work? */ -#endif - -#if EV_USE_MONOTONIC -static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */ -#endif - -#ifndef EV_FD_TO_WIN32_HANDLE -# 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 (handle, 0) -#endif -#ifndef EV_WIN32_CLOSE_FD -# define EV_WIN32_CLOSE_FD(fd) close (fd) -#endif - -#ifdef _WIN32 -# include "ev_win32.c" -#endif - -/*****************************************************************************/ - -#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 -static void noinline -ev_printerr (const char *msg) -{ - write (STDERR_FILENO, msg, strlen (msg)); -} -#endif - -static void (*syserr_cb)(const char *msg); - -void -ev_set_syserr_cb (void (*cb)(const char *msg)) -{ - syserr_cb = cb; -} - -static void noinline -ev_syserr (const char *msg) -{ - if (!msg) - msg = "(libev) system error"; - - if (syserr_cb) - syserr_cb (msg); - else - { -#if EV_AVOID_STDIO - ev_printerr (msg); - ev_printerr (": "); - ev_printerr (strerror (errno)); - ev_printerr ("\n"); -#else - perror (msg); -#endif - abort (); - } -} - -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-89 and - * the single unix specification, so work around them here. - */ - - if (size) - return realloc (ptr, size); - - free (ptr); - return 0; -#endif -} - -static void *(*alloc)(void *ptr, long size) = ev_realloc_emul; - -void -ev_set_allocator (void *(*cb)(void *ptr, long size)) -{ - alloc = cb; -} - -inline_speed void * -ev_realloc (void *ptr, long size) -{ - ptr = alloc (ptr, 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 (); - } - - return ptr; -} - -#define ev_malloc(size) ev_realloc (0, (size)) -#define ev_free(ptr) ev_realloc ((ptr), 0) - -/*****************************************************************************/ - -/* set in reify when reification needed */ -#define EV_ANFD_REIFY 1 - -/* file descriptor info structure */ -typedef struct -{ - WL head; - unsigned char events; /* the events watched for */ - unsigned char reify; /* flag set when this ANFD needs reification (EV_ANFD_REIFY, EV__IOFDSET) */ - unsigned char emask; /* the epoll backend stores the actual kernel mask in here */ - unsigned char unused; -#if EV_USE_EPOLL - unsigned int egen; /* generation counter to counter epoll bugs */ -#endif -#if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP - SOCKET handle; -#endif -#if EV_USE_IOCP - OVERLAPPED or, ow; -#endif -} ANFD; - -/* stores the pending event set for a given watcher */ -typedef struct -{ - W w; - int events; /* the pending event set for the given watcher */ -} ANPENDING; - -#if EV_USE_INOTIFY -/* hash table entry per inotify-id */ -typedef struct -{ - WL head; -} ANFS; -#endif - -/* Heap Entry */ -#if EV_HEAP_CACHE_AT - /* a heap element */ - typedef struct { - ev_tstamp at; - WT w; - } ANHE; - - #define ANHE_w(he) (he).w /* access watcher, read-write */ - #define ANHE_at(he) (he).at /* access cached at, read-only */ - #define ANHE_at_cache(he) (he).at = (he).w->at /* update at from watcher */ -#else - /* a heap element */ - typedef WT ANHE; - - #define ANHE_w(he) (he) - #define ANHE_at(he) (he)->at - #define ANHE_at_cache(he) -#endif - -#if EV_MULTIPLICITY - - struct ev_loop - { - ev_tstamp ev_rt_now; - #define ev_rt_now ((loop)->ev_rt_now) - #define VAR(name,decl) decl; - #include "ev_vars.h" - #undef VAR - }; - #include "ev_wrap.h" - - static struct ev_loop default_loop_struct; - struct ev_loop *ev_default_loop_ptr; - -#else - - ev_tstamp ev_rt_now; - #define VAR(name,decl) static decl; - #include "ev_vars.h" - #undef VAR - - static int ev_default_loop_ptr; - -#endif - -#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) -#else -# define EV_RELEASE_CB (void)0 -# define EV_ACQUIRE_CB (void)0 -# define EV_INVOKE_PENDING ev_invoke_pending (EV_A) -#endif - -#define EVBREAK_RECURSE 0x80 - -/*****************************************************************************/ - -#ifndef EV_HAVE_EV_TIME -ev_tstamp -ev_time (void) -{ -#if EV_USE_REALTIME - if (expect_true (have_realtime)) - { - struct timespec ts; - clock_gettime (CLOCK_REALTIME, &ts); - return ts.tv_sec + ts.tv_nsec * 1e-9; - } -#endif - - struct timeval tv; - gettimeofday (&tv, 0); - return tv.tv_sec + tv.tv_usec * 1e-6; -} -#endif - -inline_size ev_tstamp -get_clock (void) -{ -#if EV_USE_MONOTONIC - if (expect_true (have_monotonic)) - { - struct timespec ts; - clock_gettime (CLOCK_MONOTONIC, &ts); - return ts.tv_sec + ts.tv_nsec * 1e-9; - } -#endif - - return ev_time (); -} - -#if EV_MULTIPLICITY -ev_tstamp -ev_now (EV_P) -{ - return ev_rt_now; -} -#endif - -void -ev_sleep (ev_tstamp delay) -{ - if (delay > 0.) - { -#if EV_USE_NANOSLEEP - struct timespec ts; - - EV_TS_SET (ts, delay); - nanosleep (&ts, 0); -#elif defined(_WIN32) - Sleep ((unsigned long)(delay * 1e3)); -#else - struct timeval tv; - - /* 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 - } -} - -inline_speed int -ev_timeout_to_ms (ev_tstamp timeout) -{ - int ms = timeout * 1000. + .999999; - - return expect_true (ms) ? ms : timeout < 1e-6 ? 0 : 1; -} - -/*****************************************************************************/ - -#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 nice-to-malloc size */ -inline_size int -array_nextsize (int elem, int cur, int cnt) -{ - int ncur = cur + 1; - - do - ncur <<= 1; - while (cnt > ncur); - - /* if size is large, round to MALLOC_ROUND - 4 * longs to accomodate malloc overhead */ - if (elem * ncur > MALLOC_ROUND - sizeof (void *) * 4) - { - ncur *= elem; - ncur = (ncur + elem + (MALLOC_ROUND - 1) + sizeof (void *) * 4) & ~(MALLOC_ROUND - 1); - ncur = ncur - sizeof (void *) * 4; - ncur /= elem; - } - - return ncur; -} - -static noinline void * -array_realloc (int elem, void *base, int *cur, int cnt) -{ - *cur = array_nextsize (elem, *cur, cnt); - return ev_realloc (base, elem * *cur); -} - -#define array_init_zero(base,count) \ - memset ((void *)(base), 0, sizeof (*(base)) * (count)) - -#define array_needsize(type,base,cur,cnt,init) \ - if (expect_false ((cnt) > (cur))) \ - { \ - int ocur_ = (cur); \ - (base) = (type *)array_realloc \ - (sizeof (type), (base), &(cur), (cnt)); \ - init ((base) + (ocur_), (cur) - ocur_); \ - } - -#if 0 -#define array_slim(type,stem) \ - if (stem ## max < array_roundsize (stem ## cnt >> 2)) \ - { \ - stem ## max = array_roundsize (stem ## cnt >> 1); \ - base = (type *)ev_realloc (base, sizeof (type) * (stem ## max));\ - fprintf (stderr, "slimmed down " # stem " to %d\n", stem ## max);/*D*/\ - } -#endif - -#define array_free(stem, idx) \ - ev_free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0; stem ## s idx = 0 - -/*****************************************************************************/ - -/* dummy callback for pending events */ -static void noinline -pendingcb (EV_P_ ev_prepare *w, int revents) -{ -} - -void noinline -ev_feed_event (EV_P_ void *w, int revents) -{ - W w_ = (W)w; - int pri = ABSPRI (w_); - - if (expect_false (w_->pending)) - pendings [pri][w_->pending - 1].events |= revents; - else - { - w_->pending = ++pendingcnt [pri]; - array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending, EMPTY2); - pendings [pri][w_->pending - 1].w = w_; - pendings [pri][w_->pending - 1].events = revents; - } -} - -inline_speed void -feed_reverse (EV_P_ W w) -{ - array_needsize (W, rfeeds, rfeedmax, rfeedcnt + 1, EMPTY2); - rfeeds [rfeedcnt++] = w; -} - -inline_size void -feed_reverse_done (EV_P_ int revents) -{ - do - ev_feed_event (EV_A_ rfeeds [--rfeedcnt], revents); - while (rfeedcnt); -} - -inline_speed void -queue_events (EV_P_ W *events, int eventcnt, int type) -{ - int i; - - for (i = 0; i < eventcnt; ++i) - ev_feed_event (EV_A_ events [i], type); -} - -/*****************************************************************************/ - -inline_speed void -fd_event_nocheck (EV_P_ int fd, int revents) -{ - ANFD *anfd = anfds + fd; - ev_io *w; - - for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next) - { - int ev = w->events & revents; - - if (ev) - ev_feed_event (EV_A_ (W)w, ev); - } -} - -/* do not submit kernel events for fds that have reify set */ -/* because that means they changed while we were polling for new events */ -inline_speed void -fd_event (EV_P_ int fd, int revents) -{ - ANFD *anfd = anfds + fd; - - if (expect_true (!anfd->reify)) - 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_nocheck (EV_A_ fd, revents); -} - -/* make sure the external fd watch events are in-sync */ -/* with the kernel/libev internal state */ -inline_size void -fd_reify (EV_P) -{ - int i; - -#if EV_SELECT_IS_WINSOCKET || EV_USE_IOCP - for (i = 0; i < fdchangecnt; ++i) - { - int fd = fdchanges [i]; - ANFD *anfd = anfds + fd; - - if (anfd->reify & EV__IOFDSET) - { - SOCKET handle = EV_FD_TO_WIN32_HANDLE (fd); - - if (handle != anfd->handle) - { - unsigned long arg; - - assert (("libev: only socket fds supported in this configuration", ioctlsocket (handle, FIONREAD, &arg) == 0)); - - /* handle changed, but fd didn't - we need to do it in two steps */ - backend_modify (EV_A_ fd, anfd->events, 0); - anfd->events = 0; - anfd->handle = handle; - } - } - } -#endif - - for (i = 0; i < fdchangecnt; ++i) - { - int fd = fdchanges [i]; - ANFD *anfd = anfds + fd; - ev_io *w; - - unsigned char o_events = anfd->events; - unsigned char o_reify = anfd->reify; - - anfd->reify = 0; - - /*if (expect_true (o_reify & EV_ANFD_REIFY)) probably a deoptimisation */ - { - anfd->events = 0; - - for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next) - anfd->events |= (unsigned char)w->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; -} - -/* something about the given fd changed */ -inline_size void -fd_change (EV_P_ int fd, int flags) -{ - unsigned char reify = anfds [fd].reify; - anfds [fd].reify |= flags; - - if (expect_true (!reify)) - { - ++fdchangecnt; - array_needsize (int, fdchanges, fdchangemax, fdchangecnt, EMPTY2); - fdchanges [fdchangecnt - 1] = fd; - } -} - -/* the given fd is invalid/unusable, so make sure it doesn't hurt us anymore */ -inline_speed void -fd_kill (EV_P_ int fd) -{ - ev_io *w; - - while ((w = (ev_io *)anfds [fd].head)) - { - ev_io_stop (EV_A_ w); - ev_feed_event (EV_A_ (W)w, EV_ERROR | EV_READ | EV_WRITE); - } -} - -/* check whether the given fd is actually valid, for error recovery */ -inline_size int -fd_valid (int fd) -{ -#ifdef _WIN32 - return EV_FD_TO_WIN32_HANDLE (fd) != -1; -#else - return fcntl (fd, F_GETFD) != -1; -#endif -} - -/* called on EBADF to verify fds */ -static void noinline -fd_ebadf (EV_P) -{ - int fd; - - for (fd = 0; fd < anfdmax; ++fd) - if (anfds [fd].events) - if (!fd_valid (fd) && errno == EBADF) - fd_kill (EV_A_ fd); -} - -/* called on ENOMEM in select/poll to kill some fds and retry */ -static void noinline -fd_enomem (EV_P) -{ - int fd; - - for (fd = anfdmax; fd--; ) - if (anfds [fd].events) - { - fd_kill (EV_A_ fd); - break; - } -} - -/* usually called after fork if backend needs to re-arm all fds from scratch */ -static void noinline -fd_rearm_all (EV_P) -{ - int fd; - - for (fd = 0; fd < anfdmax; ++fd) - if (anfds [fd].events) - { - anfds [fd].events = 0; - anfds [fd].emask = 0; - fd_change (EV_A_ fd, EV__IOFDSET | EV_ANFD_REIFY); - } -} - -/* 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 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. - */ - -/* - * at the moment we allow libev the luxury of two heaps, - * a small-code-size 2-heap one and a ~1.5kb larger 4-heap - * which is more cache-efficient. - * the difference is about 5% with 50000+ watchers. - */ -#if EV_USE_4HEAP - -#define DHEAP 4 -#define HEAP0 (DHEAP - 1) /* index of first element in heap */ -#define HPARENT(k) ((((k) - HEAP0 - 1) / DHEAP) + HEAP0) -#define UPHEAP_DONE(p,k) ((p) == (k)) - -/* away from the root */ -inline_speed void -downheap (ANHE *heap, int N, int k) -{ - ANHE he = heap [k]; - ANHE *E = heap + N + HEAP0; - - for (;;) - { - ev_tstamp minat; - ANHE *minpos; - ANHE *pos = heap + DHEAP * (k - HEAP0) + HEAP0 + 1; - - /* find minimum child */ - if (expect_true (pos + DHEAP - 1 < E)) - { - /* fast path */ (minpos = pos + 0), (minat = ANHE_at (*minpos)); - if ( ANHE_at (pos [1]) < minat) (minpos = pos + 1), (minat = ANHE_at (*minpos)); - if ( ANHE_at (pos [2]) < minat) (minpos = pos + 2), (minat = ANHE_at (*minpos)); - if ( ANHE_at (pos [3]) < minat) (minpos = pos + 3), (minat = ANHE_at (*minpos)); - } - else if (pos < E) - { - /* slow path */ (minpos = pos + 0), (minat = ANHE_at (*minpos)); - if (pos + 1 < E && ANHE_at (pos [1]) < minat) (minpos = pos + 1), (minat = ANHE_at (*minpos)); - if (pos + 2 < E && ANHE_at (pos [2]) < minat) (minpos = pos + 2), (minat = ANHE_at (*minpos)); - if (pos + 3 < E && ANHE_at (pos [3]) < minat) (minpos = pos + 3), (minat = ANHE_at (*minpos)); - } - else - break; - - if (ANHE_at (he) <= minat) - break; - - heap [k] = *minpos; - ev_active (ANHE_w (*minpos)) = k; - - k = minpos - heap; - } - - heap [k] = he; - ev_active (ANHE_w (he)) = k; -} - -#else /* 4HEAP */ - -#define HEAP0 1 -#define HPARENT(k) ((k) >> 1) -#define UPHEAP_DONE(p,k) (!(p)) - -/* away from the root */ -inline_speed void -downheap (ANHE *heap, int N, int k) -{ - ANHE he = heap [k]; - - for (;;) - { - int c = k << 1; - - if (c >= N + HEAP0) - break; - - c += c + 1 < N + HEAP0 && ANHE_at (heap [c]) > ANHE_at (heap [c + 1]) - ? 1 : 0; - - if (ANHE_at (he) <= ANHE_at (heap [c])) - break; - - heap [k] = heap [c]; - ev_active (ANHE_w (heap [k])) = k; - - k = c; - } - - heap [k] = he; - ev_active (ANHE_w (he)) = k; -} -#endif - -/* towards the root */ -inline_speed void -upheap (ANHE *heap, int k) -{ - ANHE he = heap [k]; - - for (;;) - { - int p = HPARENT (k); - - if (UPHEAP_DONE (p, k) || ANHE_at (heap [p]) <= ANHE_at (he)) - break; - - heap [k] = heap [p]; - ev_active (ANHE_w (heap [k])) = k; - k = p; - } - - heap [k] = he; - ev_active (ANHE_w (he)) = k; -} - -/* move an element suitably so it is in a correct place */ -inline_size void -adjustheap (ANHE *heap, int N, int k) -{ - if (k > HEAP0 && ANHE_at (heap [k]) <= ANHE_at (heap [HPARENT (k)])) - upheap (heap, k); - else - downheap (heap, N, k); -} - -/* rebuild the heap: this function is used only once and executed rarely */ -inline_size void -reheap (ANHE *heap, int N) -{ - int i; - - /* we don't use floyds algorithm, upheap is simpler and is more cache-efficient */ - /* also, this is easy to implement and correct for both 2-heaps and 4-heaps */ - for (i = 0; i < N; ++i) - upheap (heap, i + HEAP0); -} - -/*****************************************************************************/ - -/* associate signal watchers to a signal signal */ -typedef struct -{ - EV_ATOMIC_T pending; -#if EV_MULTIPLICITY - EV_P; -#endif - WL head; -} ANSIG; - -static ANSIG signals [EV_NSIG - 1]; - -/*****************************************************************************/ - -#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE - -static void noinline -evpipe_init (EV_P) -{ - if (!ev_is_active (&pipe_w)) - { -# if EV_USE_EVENTFD - evfd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC); - if (evfd < 0 && errno == EINVAL) - evfd = eventfd (0, 0); - - if (evfd >= 0) - { - evpipe [0] = -1; - fd_intern (evfd); /* doing it twice doesn't hurt */ - ev_io_set (&pipe_w, evfd, EV_READ); - } - else -# endif - { - while (pipe (evpipe)) - ev_syserr ("(libev) error creating signal/async pipe"); - - fd_intern (evpipe [0]); - fd_intern (evpipe [1]); - ev_io_set (&pipe_w, evpipe [0], EV_READ); - } - - ev_io_start (EV_A_ &pipe_w); - ev_unref (EV_A); /* watcher should not keep loop alive */ - } -} - -inline_size void -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; - -#if EV_USE_EVENTFD - if (evfd >= 0) - { - uint64_t counter = 1; - write (evfd, &counter, sizeof (uint64_t)); - } - else -#endif - /* 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; - } -} - -/* called whenever the libev signal pipe */ -/* got some events (signal, async) */ -static void -pipecb (EV_P_ ev_io *iow, int revents) -{ - int i; - -#if EV_USE_EVENTFD - if (evfd >= 0) - { - uint64_t counter; - read (evfd, &counter, sizeof (uint64_t)); - } - else -#endif - { - char dummy; - /* see discussion in evpipe_write when you think this read should be recv in win32 */ - read (evpipe [0], &dummy, 1); - } - -#if EV_SIGNAL_ENABLE - if (sig_pending) - { - sig_pending = 0; - - for (i = EV_NSIG - 1; i--; ) - if (expect_false (signals [i].pending)) - ev_feed_signal_event (EV_A_ i + 1); - } -#endif - -#if EV_ASYNC_ENABLE - if (async_pending) - { - async_pending = 0; - - for (i = asynccnt; i--; ) - if (asyncs [i]->sent) - { - asyncs [i]->sent = 0; - ev_feed_event (EV_A_ asyncs [i], EV_ASYNC); - } - } -#endif -} - -/*****************************************************************************/ - -void -ev_feed_signal (int signum) -{ -#if EV_MULTIPLICITY - EV_P = signals [signum - 1].loop; - - if (!EV_A) - return; -#endif - - signals [signum - 1].pending = 1; - evpipe_write (EV_A_ &sig_pending); -} - -static void -ev_sighandler (int signum) -{ -#ifdef _WIN32 - signal (signum, ev_sighandler); -#endif - - ev_feed_signal (signum); -} - -void noinline -ev_feed_signal_event (EV_P_ int signum) -{ - WL w; - - if (expect_false (signum <= 0 || signum > EV_NSIG)) - return; - - --signum; - -#if EV_MULTIPLICITY - /* it is permissible to try to feed a signal to the wrong loop */ - /* or, likely more useful, feeding a signal nobody is waiting for */ - - if (expect_false (signals [signum].loop != EV_A)) - return; -#endif - - signals [signum].pending = 0; - - for (w = signals [signum].head; w; w = w->next) - ev_feed_event (EV_A_ (W)w, EV_SIGNAL); -} - -#if EV_USE_SIGNALFD -static void -sigfdcb (EV_P_ ev_io *iow, int revents) -{ - struct signalfd_siginfo si[2], *sip; /* these structs are big */ - - for (;;) - { - ssize_t res = read (sigfd, si, sizeof (si)); - - /* not ISO-C, as res might be -1, but works with SuS */ - for (sip = si; (char *)sip < (char *)si + res; ++sip) - ev_feed_signal_event (EV_A_ sip->ssi_signo); - - if (res < (ssize_t)sizeof (si)) - break; - } -} -#endif - -#endif - -/*****************************************************************************/ - -#if EV_CHILD_ENABLE -static WL childs [EV_PID_HASHSIZE]; - -static ev_signal childev; - -#ifndef WIFCONTINUED -# define WIFCONTINUED(status) 0 -#endif - -/* handle a single child status event */ -inline_speed void -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) - { - if ((w->pid == pid || !w->pid) - && (!traced || (w->flags & 1))) - { - ev_set_priority (w, EV_MAXPRI); /* need to do it *now*, this *must* be the same prio as the signal watcher itself */ - w->rpid = pid; - w->rstatus = status; - ev_feed_event (EV_A_ (W)w, EV_CHILD); - } - } -} - -#ifndef WCONTINUED -# define WCONTINUED 0 -#endif - -/* called on sigchld etc., calls waitpid */ -static void -childcb (EV_P_ ev_signal *sw, int revents) -{ - int pid, status; - - /* some systems define WCONTINUED but then fail to support it (linux 2.4) */ - if (0 >= (pid = waitpid (-1, &status, WNOHANG | WUNTRACED | WCONTINUED))) - if (!WCONTINUED - || errno != EINVAL - || 0 >= (pid = waitpid (-1, &status, WNOHANG | WUNTRACED))) - return; - - /* make sure we are called again until all children have been reaped */ - /* we need to do it this way so that the callback gets called before we continue */ - ev_feed_event (EV_A_ (W)sw, EV_SIGNAL); - - child_reap (EV_A_ pid, pid, status); - if ((EV_PID_HASHSIZE) > 1) - child_reap (EV_A_ 0, pid, status); /* this might trigger a watcher twice, but feed_event catches that */ -} - -#endif - -/*****************************************************************************/ - -#if EV_USE_IOCP -# include "ev_iocp.c" -#endif -#if EV_USE_PORT -# include "ev_port.c" -#endif -#if EV_USE_KQUEUE -# include "ev_kqueue.c" -#endif -#if EV_USE_EPOLL -# include "ev_epoll.c" -#endif -#if EV_USE_POLL -# include "ev_poll.c" -#endif -#if EV_USE_SELECT -# include "ev_select.c" -#endif - -int -ev_version_major (void) -{ - return EV_VERSION_MAJOR; -} - -int -ev_version_minor (void) -{ - return EV_VERSION_MINOR; -} - -/* return true if we are running with elevated privileges and should ignore env variables */ -int inline_size -enable_secure (void) -{ -#ifdef _WIN32 - return 0; -#else - return getuid () != geteuid () - || getgid () != getegid (); -#endif -} - -unsigned int -ev_supported_backends (void) -{ - unsigned int flags = 0; - - if (EV_USE_PORT ) flags |= EVBACKEND_PORT; - if (EV_USE_KQUEUE) flags |= EVBACKEND_KQUEUE; - if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL; - if (EV_USE_POLL ) flags |= EVBACKEND_POLL; - if (EV_USE_SELECT) flags |= EVBACKEND_SELECT; - - return flags; -} - -unsigned int -ev_recommended_backends (void) -{ - unsigned int flags = ev_supported_backends (); - -#ifndef __NetBSD__ - /* kqueue is borked on everything but netbsd apparently */ - /* it usually doesn't work correctly on anything but sockets and pipes */ - flags &= ~EVBACKEND_KQUEUE; -#endif -#ifdef __APPLE__ - /* only select works correctly on that "unix-certified" platform */ - 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; -} - -unsigned int -ev_embeddable_backends (void) -{ - int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT; - - /* epoll embeddability broken on all linux versions up to at least 2.6.23 */ - if (ev_linux_version () < 0x020620) /* disable it on linux < 2.6.32 */ - flags &= ~EVBACKEND_EPOLL; - - return flags; -} - -unsigned int -ev_backend (EV_P) -{ - return backend; -} - -#if EV_FEATURE_API -unsigned int -ev_iteration (EV_P) -{ - return loop_count; -} - -unsigned int -ev_depth (EV_P) -{ - return loop_depth; -} - -void -ev_set_io_collect_interval (EV_P_ ev_tstamp interval) -{ - io_blocktime = interval; -} - -void -ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) -{ - timeout_blocktime = interval; -} - -void -ev_set_userdata (EV_P_ void *data) -{ - userdata = data; -} - -void * -ev_userdata (EV_P) -{ - return userdata; -} - -void ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P)) -{ - invoke_cb = invoke_pending_cb; -} - -void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P)) -{ - release_cb = release; - acquire_cb = acquire; -} -#endif - -/* initialise a loop structure, must be zero-initialised */ -static void noinline -loop_init (EV_P_ unsigned int flags) -{ - if (!backend) - { - origflags = flags; - -#if EV_USE_REALTIME - if (!have_realtime) - { - struct timespec ts; - - if (!clock_gettime (CLOCK_REALTIME, &ts)) - have_realtime = 1; - } -#endif - -#if EV_USE_MONOTONIC - if (!have_monotonic) - { - struct timespec ts; - - if (!clock_gettime (CLOCK_MONOTONIC, &ts)) - have_monotonic = 1; - } -#endif - - /* pid check not overridable via env */ -#ifndef _WIN32 - if (flags & EVFLAG_FORKCHECK) - curpid = getpid (); -#endif - - if (!(flags & EVFLAG_NOENV) - && !enable_secure () - && getenv ("LIBEV_FLAGS")) - flags = atoi (getenv ("LIBEV_FLAGS")); - - ev_rt_now = ev_time (); - mn_now = get_clock (); - now_floor = mn_now; - rtmn_diff = ev_rt_now - mn_now; -#if EV_FEATURE_API - invoke_cb = ev_invoke_pending; -#endif - - io_blocktime = 0.; - timeout_blocktime = 0.; - backend = 0; - backend_fd = -1; - sig_pending = 0; -#if EV_ASYNC_ENABLE - async_pending = 0; -#endif -#if EV_USE_INOTIFY - fs_fd = flags & EVFLAG_NOINOTIFY ? -1 : -2; -#endif -#if EV_USE_SIGNALFD - sigfd = flags & EVFLAG_SIGNALFD ? -2 : -1; -#endif - - if (!(flags & EVBACKEND_MASK)) - 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 (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags); -#endif -#if EV_USE_KQUEUE - if (!backend && (flags & EVBACKEND_KQUEUE)) backend = kqueue_init (EV_A_ flags); -#endif -#if EV_USE_EPOLL - if (!backend && (flags & EVBACKEND_EPOLL )) backend = epoll_init (EV_A_ flags); -#endif -#if EV_USE_POLL - if (!backend && (flags & EVBACKEND_POLL )) backend = poll_init (EV_A_ flags); -#endif -#if EV_USE_SELECT - if (!backend && (flags & EVBACKEND_SELECT)) backend = select_init (EV_A_ flags); -#endif - - 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 - } -} - -/* free up a loop structure */ -void -ev_loop_destroy (EV_P) -{ - 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)) - { - /*ev_ref (EV_A);*/ - /*ev_io_stop (EV_A_ &pipe_w);*/ - -#if EV_USE_EVENTFD - if (evfd >= 0) - close (evfd); -#endif - - if (evpipe [0] >= 0) - { - EV_WIN32_CLOSE_FD (evpipe [0]); - EV_WIN32_CLOSE_FD (evpipe [1]); - } - } - -#if EV_USE_SIGNALFD - if (ev_is_active (&sigfd_w)) - close (sigfd); -#endif - -#if EV_USE_INOTIFY - if (fs_fd >= 0) - close (fs_fd); -#endif - - if (backend_fd >= 0) - close (backend_fd); - -#if EV_USE_IOCP - if (backend == EVBACKEND_IOCP ) iocp_destroy (EV_A); -#endif -#if EV_USE_PORT - if (backend == EVBACKEND_PORT ) port_destroy (EV_A); -#endif -#if EV_USE_KQUEUE - if (backend == EVBACKEND_KQUEUE) kqueue_destroy (EV_A); -#endif -#if EV_USE_EPOLL - if (backend == EVBACKEND_EPOLL ) epoll_destroy (EV_A); -#endif -#if EV_USE_POLL - if (backend == EVBACKEND_POLL ) poll_destroy (EV_A); -#endif -#if EV_USE_SELECT - if (backend == EVBACKEND_SELECT) select_destroy (EV_A); -#endif - - for (i = NUMPRI; i--; ) - { - array_free (pending, [i]); -#if EV_IDLE_ENABLE - array_free (idle, [i]); -#endif - } - - ev_free (anfds); anfds = 0; anfdmax = 0; - - /* have to use the microsoft-never-gets-it-right macro */ - array_free (rfeed, EMPTY); - array_free (fdchange, EMPTY); - array_free (timer, EMPTY); -#if EV_PERIODIC_ENABLE - array_free (periodic, EMPTY); -#endif -#if EV_FORK_ENABLE - array_free (fork, EMPTY); -#endif -#if EV_CLEANUP_ENABLE - array_free (cleanup, EMPTY); -#endif - array_free (prepare, EMPTY); - array_free (check, EMPTY); -#if EV_ASYNC_ENABLE - array_free (async, EMPTY); -#endif - - 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 -inline_size void infy_fork (EV_P); -#endif - -inline_size void -loop_fork (EV_P) -{ -#if EV_USE_PORT - if (backend == EVBACKEND_PORT ) port_fork (EV_A); -#endif -#if EV_USE_KQUEUE - if (backend == EVBACKEND_KQUEUE) kqueue_fork (EV_A); -#endif -#if EV_USE_EPOLL - if (backend == EVBACKEND_EPOLL ) epoll_fork (EV_A); -#endif -#if EV_USE_INOTIFY - infy_fork (EV_A); -#endif - - if (ev_is_active (&pipe_w)) - { - /* this "locks" the handlers against writing to the pipe */ - /* while we modify the fd vars */ - sig_pending = 1; -#if EV_ASYNC_ENABLE - async_pending = 1; -#endif - - ev_ref (EV_A); - ev_io_stop (EV_A_ &pipe_w); - -#if EV_USE_EVENTFD - if (evfd >= 0) - close (evfd); -#endif - - if (evpipe [0] >= 0) - { - EV_WIN32_CLOSE_FD (evpipe [0]); - 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; -} - -#if EV_MULTIPLICITY - -struct ev_loop * -ev_loop_new (unsigned int flags) -{ - EV_P = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop)); - - memset (EV_A, 0, sizeof (struct ev_loop)); - loop_init (EV_A_ flags); - - if (ev_backend (EV_A)) - return EV_A; - - ev_free (EV_A); - return 0; -} - -#endif /* multiplicity */ - -#if EV_VERIFY -static void noinline -verify_watcher (EV_P_ W w) -{ - assert (("libev: watcher has invalid priority", ABSPRI (w) >= 0 && ABSPRI (w) < NUMPRI)); - - if (w->pending) - assert (("libev: pending watcher not on pending queue", pendings [ABSPRI (w)][w->pending - 1].w == w)); -} - -static void noinline -verify_heap (EV_P_ ANHE *heap, int N) -{ - int i; - - for (i = HEAP0; i < N + HEAP0; ++i) - { - assert (("libev: active index mismatch in heap", ev_active (ANHE_w (heap [i])) == i)); - assert (("libev: heap condition violated", i == HEAP0 || ANHE_at (heap [HPARENT (i)]) <= ANHE_at (heap [i]))); - assert (("libev: heap at cache mismatch", ANHE_at (heap [i]) == ev_at (ANHE_w (heap [i])))); - - verify_watcher (EV_A_ (W)ANHE_w (heap [i])); - } -} - -static void noinline -array_verify (EV_P_ W *ws, int cnt) -{ - while (cnt--) - { - assert (("libev: active index mismatch", ev_active (ws [cnt]) == cnt + 1)); - verify_watcher (EV_A_ ws [cnt]); - } -} -#endif - -#if EV_FEATURE_API -void -ev_verify (EV_P) -{ -#if EV_VERIFY - int i; - WL w; - - assert (activecnt >= -1); - - assert (fdchangemax >= fdchangecnt); - for (i = 0; i < fdchangecnt; ++i) - assert (("libev: negative fd in fdchanges", fdchanges [i] >= 0)); - - assert (anfdmax >= 0); - for (i = 0; i < anfdmax; ++i) - for (w = anfds [i].head; w; w = w->next) - { - verify_watcher (EV_A_ (W)w); - assert (("libev: inactive fd watcher on anfd list", ev_active (w) == 1)); - assert (("libev: fd mismatch between watcher and anfd", ((ev_io *)w)->fd == i)); - } - - assert (timermax >= timercnt); - verify_heap (EV_A_ timers, timercnt); - -#if EV_PERIODIC_ENABLE - assert (periodicmax >= periodiccnt); - verify_heap (EV_A_ periodics, periodiccnt); -#endif - - for (i = NUMPRI; i--; ) - { - assert (pendingmax [i] >= pendingcnt [i]); -#if EV_IDLE_ENABLE - assert (idleall >= 0); - assert (idlemax [i] >= idlecnt [i]); - array_verify (EV_A_ (W *)idles [i], idlecnt [i]); -#endif - } - -#if EV_FORK_ENABLE - assert (forkmax >= forkcnt); - array_verify (EV_A_ (W *)forks, forkcnt); -#endif - -#if EV_CLEANUP_ENABLE - assert (cleanupmax >= cleanupcnt); - array_verify (EV_A_ (W *)cleanups, cleanupcnt); -#endif - -#if EV_ASYNC_ENABLE - assert (asyncmax >= asynccnt); - 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 -#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 -} -#endif - -#if EV_MULTIPLICITY -struct ev_loop * -#else -int -#endif -ev_default_loop (unsigned int flags) -{ - if (!ev_default_loop_ptr) - { -#if EV_MULTIPLICITY - EV_P = ev_default_loop_ptr = &default_loop_struct; -#else - ev_default_loop_ptr = 1; -#endif - - loop_init (EV_A_ flags); - - if (ev_backend (EV_A)) - { -#if EV_CHILD_ENABLE - ev_signal_init (&childev, childcb, SIGCHLD); - ev_set_priority (&childev, EV_MAXPRI); - ev_signal_start (EV_A_ &childev); - ev_unref (EV_A); /* child watcher should not keep loop alive */ -#endif - } - else - ev_default_loop_ptr = 0; - } - - return ev_default_loop_ptr; -} - -void -ev_loop_fork (EV_P) -{ - postfork = 1; /* must be in line with ev_default_fork */ -} - -/*****************************************************************************/ - -void -ev_invoke (EV_P_ void *w, int revents) -{ - EV_CB_INVOKE ((W)w, revents); -} - -unsigned int -ev_pending_count (EV_P) -{ - int pri; - unsigned int count = 0; - - for (pri = NUMPRI; pri--; ) - count += pendingcnt [pri]; - - return count; -} - -void noinline -ev_invoke_pending (EV_P) -{ - int pri; - - for (pri = NUMPRI; pri--; ) - while (pendingcnt [pri]) - { - ANPENDING *p = pendings [pri] + --pendingcnt [pri]; - - p->w->pending = 0; - EV_CB_INVOKE (p->w, p->events); - EV_FREQUENT_CHECK; - } -} - -#if EV_IDLE_ENABLE -/* make idle watchers pending. this handles the "call-idle */ -/* only when higher priorities are idle" logic */ -inline_size void -idle_reify (EV_P) -{ - if (expect_false (idleall)) - { - int pri; - - for (pri = NUMPRI; pri--; ) - { - if (pendingcnt [pri]) - break; - - if (idlecnt [pri]) - { - queue_events (EV_A_ (W *)idles [pri], idlecnt [pri], EV_IDLE); - break; - } - } - } -} -#endif - -/* make timers pending */ -inline_size void -timers_reify (EV_P) -{ - EV_FREQUENT_CHECK; - - if (timercnt && ANHE_at (timers [HEAP0]) < mn_now) - { - do - { - ev_timer *w = (ev_timer *)ANHE_w (timers [HEAP0]); - - /*assert (("libev: inactive timer on timer heap detected", ev_is_active (w)));*/ - - /* first reschedule or stop timer */ - if (w->repeat) - { - ev_at (w) += w->repeat; - if (ev_at (w) < mn_now) - ev_at (w) = mn_now; - - assert (("libev: negative ev_timer repeat value found while processing timers", w->repeat > 0.)); - - ANHE_at_cache (timers [HEAP0]); - downheap (timers, timercnt, HEAP0); - } - else - ev_timer_stop (EV_A_ w); /* nonrepeating: stop timer */ - - EV_FREQUENT_CHECK; - feed_reverse (EV_A_ (W)w); - } - while (timercnt && ANHE_at (timers [HEAP0]) < mn_now); - - feed_reverse_done (EV_A_ EV_TIMER); - } -} - -#if EV_PERIODIC_ENABLE - -inline_speed void -periodic_recalc (EV_P_ ev_periodic *w) -{ - /* TODO: use slow but potentially more correct incremental algo, */ - /* also do not rely on ceil */ - ev_at (w) = w->offset + ceil ((ev_rt_now - w->offset) / w->interval) * w->interval; -} - -/* make periodics pending */ -inline_size void -periodics_reify (EV_P) -{ - EV_FREQUENT_CHECK; - - while (periodiccnt && ANHE_at (periodics [HEAP0]) < ev_rt_now) - { - int feed_count = 0; - - do - { - ev_periodic *w = (ev_periodic *)ANHE_w (periodics [HEAP0]); - - /*assert (("libev: inactive timer on periodic heap detected", ev_is_active (w)));*/ - - /* first reschedule or stop timer */ - if (w->reschedule_cb) - { - ev_at (w) = w->reschedule_cb (w, ev_rt_now); - - assert (("libev: ev_periodic reschedule callback returned time in the past", ev_at (w) >= ev_rt_now)); - - ANHE_at_cache (periodics [HEAP0]); - downheap (periodics, periodiccnt, HEAP0); - } - else if (w->interval) - { - periodic_recalc (EV_A_ w); - - /* if next trigger time is not sufficiently in the future, put it there */ - /* this might happen because of floating point inexactness */ - if (ev_at (w) - ev_rt_now < TIME_EPSILON) - { - ev_at (w) += w->interval; - - /* if interval is unreasonably low we might still have a time in the past */ - /* so correct this. this will make the periodic very inexact, but the user */ - /* has effectively asked to get triggered more often than possible */ - if (ev_at (w) < ev_rt_now) - ev_at (w) = ev_rt_now; - } - - ANHE_at_cache (periodics [HEAP0]); - downheap (periodics, periodiccnt, HEAP0); - } - else - ev_periodic_stop (EV_A_ w); /* nonrepeating: stop timer */ - - EV_FREQUENT_CHECK; - feed_reverse (EV_A_ (W)w); - } - while (periodiccnt && ANHE_at (periodics [HEAP0]) < ev_rt_now); - - feed_reverse_done (EV_A_ EV_PERIODIC); - } -} - -/* simply recalculate all periodics */ -/* TODO: maybe ensure that at least one event happens when jumping forward? */ -static void noinline -periodics_reschedule (EV_P) -{ - int i; - - /* adjust periodics after time jump */ - for (i = HEAP0; i < periodiccnt + HEAP0; ++i) - { - ev_periodic *w = (ev_periodic *)ANHE_w (periodics [i]); - - if (w->reschedule_cb) - ev_at (w) = w->reschedule_cb (w, ev_rt_now); - else if (w->interval) - periodic_recalc (EV_A_ w); - - ANHE_at_cache (periodics [i]); - } - - reheap (periodics, periodiccnt); -} -#endif - -/* adjust all timers by a given offset */ -static void noinline -timers_reschedule (EV_P_ ev_tstamp adjust) -{ - int i; - - for (i = 0; i < timercnt; ++i) - { - ANHE *he = timers + i + HEAP0; - ANHE_w (*he)->at += adjust; - ANHE_at_cache (*he); - } -} - -/* fetch new monotonic and realtime times from the kernel */ -/* also detect if there was a timejump, and act accordingly */ -inline_speed void -time_update (EV_P_ ev_tstamp max_block) -{ -#if EV_USE_MONOTONIC - if (expect_true (have_monotonic)) - { - int i; - ev_tstamp odiff = rtmn_diff; - - mn_now = get_clock (); - - /* only fetch the realtime clock every 0.5*MIN_TIMEJUMP seconds */ - /* interpolate in the meantime */ - if (expect_true (mn_now - now_floor < MIN_TIMEJUMP * .5)) - { - ev_rt_now = rtmn_diff + mn_now; - return; - } - - now_floor = mn_now; - ev_rt_now = ev_time (); - - /* loop a few times, before making important decisions. - * on the choice of "4": one iteration isn't enough, - * in case we get preempted during the calls to - * ev_time and get_clock. a second call is almost guaranteed - * to succeed in that case, though. and looping a few more times - * doesn't hurt either as we only do this on time-jumps or - * in the unlikely event of having been preempted here. - */ - for (i = 4; --i; ) - { - rtmn_diff = ev_rt_now - mn_now; - - if (expect_true (fabs (odiff - rtmn_diff) < MIN_TIMEJUMP)) - return; /* all is well */ - - ev_rt_now = ev_time (); - mn_now = get_clock (); - now_floor = mn_now; - } - - /* no timer adjustment, as the monotonic clock doesn't jump */ - /* timers_reschedule (EV_A_ rtmn_diff - odiff) */ -# if EV_PERIODIC_ENABLE - periodics_reschedule (EV_A); -# endif - } - else -#endif - { - ev_rt_now = ev_time (); - - if (expect_false (mn_now > ev_rt_now || ev_rt_now > mn_now + max_block + MIN_TIMEJUMP)) - { - /* adjust timers. this is easy, as the offset is the same for all of them */ - timers_reschedule (EV_A_ ev_rt_now - mn_now); -#if EV_PERIODIC_ENABLE - periodics_reschedule (EV_A); -#endif - } - - mn_now = ev_rt_now; - } -} - -void -ev_run (EV_P_ int flags) -{ -#if EV_FEATURE_API - ++loop_depth; -#endif - - assert (("libev: ev_loop recursion during release detected", loop_done != EVBREAK_RECURSE)); - - loop_done = EVBREAK_CANCEL; - - EV_INVOKE_PENDING; /* in case we recurse, ensure ordering stays nice and clean */ - - do - { -#if EV_VERIFY >= 2 - ev_verify (EV_A); -#endif - -#ifndef _WIN32 - if (expect_false (curpid)) /* penalise the forking check even more */ - if (expect_false (getpid () != curpid)) - { - curpid = getpid (); - postfork = 1; - } -#endif - -#if EV_FORK_ENABLE - /* we might have forked, so queue fork handlers */ - if (expect_false (postfork)) - if (forkcnt) - { - queue_events (EV_A_ (W *)forks, forkcnt, EV_FORK); - EV_INVOKE_PENDING; - } -#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; - - /* we might have forked, so reify kernel state if necessary */ - if (expect_false (postfork)) - loop_fork (EV_A); - - /* update fd-related kernel structures */ - fd_reify (EV_A); - - /* calculate blocking time */ - { - ev_tstamp waittime = 0.; - ev_tstamp sleeptime = 0.; - - /* 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); - - if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt))) - { - waittime = MAX_BLOCKTIME; - - if (timercnt) - { - ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now + backend_fudge; - if (waittime > to) waittime = to; - } - -#if EV_PERIODIC_ENABLE - if (periodiccnt) - { - ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now + backend_fudge; - if (waittime > to) waittime = to; - } -#endif - - /* don't let timeouts decrease the waittime below timeout_blocktime */ - if (expect_false (waittime < timeout_blocktime)) - waittime = timeout_blocktime; - - /* extra check because io_blocktime is commonly 0 */ - if (expect_false (io_blocktime)) - { - sleeptime = io_blocktime - (mn_now - prev_mn_now); - - if (sleeptime > waittime - backend_fudge) - sleeptime = waittime - backend_fudge; - - if (expect_true (sleeptime > 0.)) - { - ev_sleep (sleeptime); - waittime -= sleeptime; - } - } - } - -#if EV_FEATURE_API - ++loop_count; -#endif - assert ((loop_done = EVBREAK_RECURSE, 1)); /* assert for side effect */ - backend_poll (EV_A_ waittime); - assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */ - - /* update ev_rt_now, do magic */ - time_update (EV_A_ waittime + sleeptime); - } - - /* queue pending timers and reschedule them */ - timers_reify (EV_A); /* relative timers called last */ -#if EV_PERIODIC_ENABLE - periodics_reify (EV_A); /* absolute timers called first */ -#endif - -#if EV_IDLE_ENABLE - /* queue idle watchers unless other events are pending */ - 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 & (EVRUN_ONCE | EVRUN_NOWAIT)) - )); - - if (loop_done == EVBREAK_ONE) - loop_done = EVBREAK_CANCEL; - -#if EV_FEATURE_API - --loop_depth; -#endif -} - -void -ev_break (EV_P_ int how) -{ - loop_done = how; -} - -void -ev_ref (EV_P) -{ - ++activecnt; -} - -void -ev_unref (EV_P) -{ - --activecnt; -} - -void -ev_now_update (EV_P) -{ - time_update (EV_A_ 1e100); -} - -void -ev_suspend (EV_P) -{ - ev_now_update (EV_A); -} - -void -ev_resume (EV_P) -{ - ev_tstamp mn_prev = mn_now; - - ev_now_update (EV_A); - timers_reschedule (EV_A_ mn_now - mn_prev); -#if EV_PERIODIC_ENABLE - /* TODO: really do this? */ - periodics_reschedule (EV_A); -#endif -} - -/*****************************************************************************/ -/* singly-linked list management, used when the expected list length is short */ - -inline_size void -wlist_add (WL *head, WL elem) -{ - elem->next = *head; - *head = elem; -} - -inline_size void -wlist_del (WL *head, WL elem) -{ - while (*head) - { - if (expect_true (*head == elem)) - { - *head = elem->next; - break; - } - - head = &(*head)->next; - } -} - -/* internal, faster, version of ev_clear_pending */ -inline_speed void -clear_pending (EV_P_ W w) -{ - if (w->pending) - { - pendings [ABSPRI (w)][w->pending - 1].w = (W)&pending_w; - w->pending = 0; - } -} - -int -ev_clear_pending (EV_P_ void *w) -{ - W w_ = (W)w; - int pending = w_->pending; - - if (expect_true (pending)) - { - ANPENDING *p = pendings [ABSPRI (w_)] + pending - 1; - p->w = (W)&pending_w; - w_->pending = 0; - return p->events; - } - else - return 0; -} - -inline_size void -pri_adjust (EV_P_ W w) -{ - int pri = ev_priority (w); - pri = pri < EV_MINPRI ? EV_MINPRI : pri; - pri = pri > EV_MAXPRI ? EV_MAXPRI : pri; - ev_set_priority (w, pri); -} - -inline_speed void -ev_start (EV_P_ W w, int active) -{ - pri_adjust (EV_A_ w); - w->active = active; - ev_ref (EV_A); -} - -inline_size void -ev_stop (EV_P_ W w) -{ - ev_unref (EV_A); - w->active = 0; -} - -/*****************************************************************************/ - -void noinline -ev_io_start (EV_P_ ev_io *w) -{ - int fd = w->fd; - - if (expect_false (ev_is_active (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)))); - - EV_FREQUENT_CHECK; - - ev_start (EV_A_ (W)w, 1); - array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero); - wlist_add (&anfds[fd].head, (WL)w); - - fd_change (EV_A_ fd, w->events & EV__IOFDSET | EV_ANFD_REIFY); - w->events &= ~EV__IOFDSET; - - EV_FREQUENT_CHECK; -} - -void noinline -ev_io_stop (EV_P_ ev_io *w) -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - assert (("libev: ev_io_stop called with illegal fd (must stay constant after start!)", w->fd >= 0 && w->fd < anfdmax)); - - EV_FREQUENT_CHECK; - - wlist_del (&anfds[w->fd].head, (WL)w); - ev_stop (EV_A_ (W)w); - - fd_change (EV_A_ w->fd, EV_ANFD_REIFY); - - EV_FREQUENT_CHECK; -} - -void noinline -ev_timer_start (EV_P_ ev_timer *w) -{ - if (expect_false (ev_is_active (w))) - return; - - ev_at (w) += mn_now; - - assert (("libev: ev_timer_start called with negative timer repeat value", w->repeat >= 0.)); - - EV_FREQUENT_CHECK; - - ++timercnt; - ev_start (EV_A_ (W)w, timercnt + HEAP0 - 1); - array_needsize (ANHE, timers, timermax, ev_active (w) + 1, EMPTY2); - ANHE_w (timers [ev_active (w)]) = (WT)w; - ANHE_at_cache (timers [ev_active (w)]); - upheap (timers, ev_active (w)); - - EV_FREQUENT_CHECK; - - /*assert (("libev: internal timer heap corruption", timers [ev_active (w)] == (WT)w));*/ -} - -void noinline -ev_timer_stop (EV_P_ ev_timer *w) -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - { - int active = ev_active (w); - - assert (("libev: internal timer heap corruption", ANHE_w (timers [active]) == (WT)w)); - - --timercnt; - - if (expect_true (active < timercnt + HEAP0)) - { - timers [active] = timers [timercnt + HEAP0]; - adjustheap (timers, timercnt, active); - } - } - - ev_at (w) -= mn_now; - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} - -void noinline -ev_timer_again (EV_P_ ev_timer *w) -{ - EV_FREQUENT_CHECK; - - if (ev_is_active (w)) - { - if (w->repeat) - { - ev_at (w) = mn_now + w->repeat; - ANHE_at_cache (timers [ev_active (w)]); - adjustheap (timers, timercnt, ev_active (w)); - } - else - ev_timer_stop (EV_A_ w); - } - else if (w->repeat) - { - ev_at (w) = w->repeat; - ev_timer_start (EV_A_ w); - } - - EV_FREQUENT_CHECK; -} - -ev_tstamp -ev_timer_remaining (EV_P_ ev_timer *w) -{ - return ev_at (w) - (ev_is_active (w) ? mn_now : 0.); -} - -#if EV_PERIODIC_ENABLE -void noinline -ev_periodic_start (EV_P_ ev_periodic *w) -{ - if (expect_false (ev_is_active (w))) - return; - - if (w->reschedule_cb) - ev_at (w) = w->reschedule_cb (w, ev_rt_now); - else if (w->interval) - { - assert (("libev: ev_periodic_start called with negative interval value", w->interval >= 0.)); - periodic_recalc (EV_A_ w); - } - else - ev_at (w) = w->offset; - - EV_FREQUENT_CHECK; - - ++periodiccnt; - ev_start (EV_A_ (W)w, periodiccnt + HEAP0 - 1); - array_needsize (ANHE, periodics, periodicmax, ev_active (w) + 1, EMPTY2); - ANHE_w (periodics [ev_active (w)]) = (WT)w; - ANHE_at_cache (periodics [ev_active (w)]); - upheap (periodics, ev_active (w)); - - EV_FREQUENT_CHECK; - - /*assert (("libev: internal periodic heap corruption", ANHE_w (periodics [ev_active (w)]) == (WT)w));*/ -} - -void noinline -ev_periodic_stop (EV_P_ ev_periodic *w) -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - { - int active = ev_active (w); - - assert (("libev: internal periodic heap corruption", ANHE_w (periodics [active]) == (WT)w)); - - --periodiccnt; - - if (expect_true (active < periodiccnt + HEAP0)) - { - periodics [active] = periodics [periodiccnt + HEAP0]; - adjustheap (periodics, periodiccnt, active); - } - } - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} - -void noinline -ev_periodic_again (EV_P_ ev_periodic *w) -{ - /* TODO: use adjustheap and recalculation */ - ev_periodic_stop (EV_A_ w); - ev_periodic_start (EV_A_ w); -} -#endif - -#ifndef SA_RESTART -# define SA_RESTART 0 -#endif - -#if EV_SIGNAL_ENABLE - -void noinline -ev_signal_start (EV_P_ ev_signal *w) -{ - if (expect_false (ev_is_active (w))) - return; - - assert (("libev: ev_signal_start called with illegal signal number", w->signum > 0 && w->signum < EV_NSIG)); - -#if EV_MULTIPLICITY - assert (("libev: a signal must not be attached to two different loops", - !signals [w->signum - 1].loop || signals [w->signum - 1].loop == loop)); - - signals [w->signum - 1].loop = EV_A; -#endif - - EV_FREQUENT_CHECK; - -#if EV_USE_SIGNALFD - if (sigfd == -2) - { - sigfd = signalfd (-1, &sigfd_set, SFD_NONBLOCK | SFD_CLOEXEC); - if (sigfd < 0 && errno == EINVAL) - sigfd = signalfd (-1, &sigfd_set, 0); /* retry without flags */ - - if (sigfd >= 0) - { - fd_intern (sigfd); /* doing it twice will not hurt */ - - sigemptyset (&sigfd_set); - - ev_io_init (&sigfd_w, sigfdcb, sigfd, EV_READ); - ev_set_priority (&sigfd_w, EV_MAXPRI); - ev_io_start (EV_A_ &sigfd_w); - ev_unref (EV_A); /* signalfd watcher should not keep loop alive */ - } - } - - if (sigfd >= 0) - { - /* TODO: check .head */ - sigaddset (&sigfd_set, w->signum); - sigprocmask (SIG_BLOCK, &sigfd_set, 0); - - signalfd (sigfd, &sigfd_set, 0); - } -#endif - - ev_start (EV_A_ (W)w, 1); - wlist_add (&signals [w->signum - 1].head, (WL)w); - - if (!((WL)w)->next) -# if EV_USE_SIGNALFD - if (sigfd < 0) /*TODO*/ -# endif - { -# ifdef _WIN32 - evpipe_init (EV_A); - - signal (w->signum, ev_sighandler); -# else - struct sigaction sa; - - evpipe_init (EV_A); - - sa.sa_handler = ev_sighandler; - sigfillset (&sa.sa_mask); - sa.sa_flags = SA_RESTART; /* if restarting works we save one iteration */ - sigaction (w->signum, &sa, 0); - - if (origflags & EVFLAG_NOSIGMASK) - { - sigemptyset (&sa.sa_mask); - sigaddset (&sa.sa_mask, w->signum); - sigprocmask (SIG_UNBLOCK, &sa.sa_mask, 0); - } -#endif - } - - EV_FREQUENT_CHECK; -} - -void noinline -ev_signal_stop (EV_P_ ev_signal *w) -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - wlist_del (&signals [w->signum - 1].head, (WL)w); - ev_stop (EV_A_ (W)w); - - if (!signals [w->signum - 1].head) - { -#if EV_MULTIPLICITY - signals [w->signum - 1].loop = 0; /* unattach from signal */ -#endif -#if EV_USE_SIGNALFD - if (sigfd >= 0) - { - sigset_t ss; - - sigemptyset (&ss); - sigaddset (&ss, w->signum); - sigdelset (&sigfd_set, w->signum); - - signalfd (sigfd, &sigfd_set, 0); - sigprocmask (SIG_UNBLOCK, &ss, 0); - } - else -#endif - signal (w->signum, SIG_DFL); - } - - EV_FREQUENT_CHECK; -} - -#endif - -#if EV_CHILD_ENABLE - -void -ev_child_start (EV_P_ ev_child *w) -{ -#if EV_MULTIPLICITY - assert (("libev: child watchers are only supported in the default loop", loop == ev_default_loop_ptr)); -#endif - if (expect_false (ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - ev_start (EV_A_ (W)w, 1); - wlist_add (&childs [w->pid & ((EV_PID_HASHSIZE) - 1)], (WL)w); - - EV_FREQUENT_CHECK; -} - -void -ev_child_stop (EV_P_ ev_child *w) -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - 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 -# undef lstat -# define lstat(a,b) _stati64 (a,b) -# endif - -#define DEF_STAT_INTERVAL 5.0074891 -#define NFS_STAT_INTERVAL 30.1074891 /* for filesystems potentially failing inotify */ -#define MIN_STAT_INTERVAL 0.1074891 - -static void noinline stat_timer_cb (EV_P_ ev_timer *w_, int revents); - -#if EV_USE_INOTIFY - -/* 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) -{ - w->wd = inotify_add_watch (fs_fd, w->path, IN_ATTRIB | IN_DELETE_SELF | IN_MOVE_SELF | IN_MODIFY | IN_DONT_FOLLOW | IN_MASK_ADD); - - if (w->wd >= 0) - { - struct statfs sfs; - - /* now local changes will be tracked by inotify, but remote changes won't */ - /* unless the filesystem is known to be local, we therefore still poll */ - /* also do poll on <2.6.25, but with normal frequency */ - - if (!fs_2625) - w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL; - else if (!statfs (w->path, &sfs) - && (sfs.f_type == 0x1373 /* devfs */ - || sfs.f_type == 0xEF53 /* ext2/3 */ - || sfs.f_type == 0x3153464a /* jfs */ - || sfs.f_type == 0x52654973 /* reiser3 */ - || sfs.f_type == 0x01021994 /* tempfs */ - || sfs.f_type == 0x58465342 /* xfs */)) - w->timer.repeat = 0.; /* filesystem is local, kernel new enough */ - else - w->timer.repeat = w->interval ? w->interval : NFS_STAT_INTERVAL; /* remote, use reduced frequency */ - } - else - { - /* can't use inotify, continue to stat */ - w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL; - - /* if path is not there, monitor some parent directory for speedup hints */ - /* note that exceeding the hardcoded path limit is not a correctness issue, */ - /* but an efficiency issue only */ - if ((errno == ENOENT || errno == EACCES) && strlen (w->path) < 4096) - { - char path [4096]; - strcpy (path, w->path); - - do - { - int mask = IN_MASK_ADD | IN_DELETE_SELF | IN_MOVE_SELF - | (errno == EACCES ? IN_ATTRIB : IN_CREATE | IN_MOVED_TO); - - char *pend = strrchr (path, '/'); - - if (!pend || pend == path) - break; - - *pend = 0; - w->wd = inotify_add_watch (fs_fd, path, mask); - } - while (w->wd < 0 && (errno == ENOENT || errno == EACCES)); - } - } - - if (w->wd >= 0) - 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); - ev_timer_again (EV_A_ &w->timer); - if (ev_is_active (&w->timer)) ev_unref (EV_A); -} - -static void noinline -infy_del (EV_P_ ev_stat *w) -{ - int slot; - int wd = w->wd; - - if (wd < 0) - return; - - w->wd = -2; - 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 */ - inotify_rm_watch (fs_fd, wd); -} - -static void noinline -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) - infy_wd (EV_A_ slot, wd, ev); - else - { - WL 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 */ - - if (w->wd == wd || wd == -1) - { - if (ev->mask & (IN_IGNORED | IN_UNMOUNT | IN_DELETE_SELF)) - { - 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 */ - } - - stat_timer_cb (EV_A_ &w->timer, 0); - } - } - } -} - -static void -infy_cb (EV_P_ ev_io *w, int revents) -{ - char buf [EV_INOTIFY_BUFSIZE]; - int ofs; - int len = read (fs_fd, buf, sizeof (buf)); - - 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 -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; -} - -inline_size int -infy_newfd (void) -{ -#if defined (IN_CLOEXEC) && defined (IN_NONBLOCK) - int fd = inotify_init1 (IN_CLOEXEC | IN_NONBLOCK); - if (fd >= 0) - return fd; -#endif - return inotify_init (); -} - -inline_size void -infy_init (EV_P) -{ - if (fs_fd != -2) - return; - - fs_fd = -1; - - ev_check_2625 (EV_A); - - fs_fd = infy_newfd (); - - if (fs_fd >= 0) - { - fd_intern (fs_fd); - ev_io_init (&fs_w, infy_cb, fs_fd, EV_READ); - ev_set_priority (&fs_w, EV_MAXPRI); - ev_io_start (EV_A_ &fs_w); - ev_unref (EV_A); - } -} - -inline_size void -infy_fork (EV_P) -{ - int slot; - - if (fs_fd < 0) - return; - - ev_ref (EV_A); - ev_io_stop (EV_A_ &fs_w); - close (fs_fd); - fs_fd = infy_newfd (); - - if (fs_fd >= 0) - { - fd_intern (fs_fd); - ev_io_set (&fs_w, fs_fd, EV_READ); - ev_io_start (EV_A_ &fs_w); - ev_unref (EV_A); - } - - for (slot = 0; slot < (EV_INOTIFY_HASHSIZE); ++slot) - { - WL w_ = fs_hash [slot].head; - fs_hash [slot].head = 0; - - while (w_) - { - ev_stat *w = (ev_stat *)w_; - w_ = w_->next; /* lets us add this watcher */ - - w->wd = -1; - - if (fs_fd >= 0) - infy_add (EV_A_ w); /* re-add, no matter what */ - else - { - w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL; - if (ev_is_active (&w->timer)) ev_ref (EV_A); - ev_timer_again (EV_A_ &w->timer); - if (ev_is_active (&w->timer)) ev_unref (EV_A); - } - } - } -} - -#endif - -#ifdef _WIN32 -# define EV_LSTAT(p,b) _stati64 (p, b) -#else -# define EV_LSTAT(p,b) lstat (p, b) -#endif - -void -ev_stat_stat (EV_P_ ev_stat *w) -{ - if (lstat (w->path, &w->attr) < 0) - w->attr.st_nlink = 0; - else if (!w->attr.st_nlink) - w->attr.st_nlink = 1; -} - -static void noinline -stat_timer_cb (EV_P_ ev_timer *w_, int revents) -{ - ev_stat *w = (ev_stat *)(((char *)w_) - offsetof (ev_stat, timer)); - - ev_statdata prev = w->attr; - ev_stat_stat (EV_A_ w); - - /* memcmp doesn't work on netbsd, they.... do stuff to their struct stat */ - if ( - prev.st_dev != w->attr.st_dev - || prev.st_ino != w->attr.st_ino - || prev.st_mode != w->attr.st_mode - || prev.st_nlink != w->attr.st_nlink - || prev.st_uid != w->attr.st_uid - || prev.st_gid != w->attr.st_gid - || prev.st_rdev != w->attr.st_rdev - || prev.st_size != w->attr.st_size - || prev.st_atime != w->attr.st_atime - || prev.st_mtime != w->attr.st_mtime - || prev.st_ctime != w->attr.st_ctime - ) { - /* we only update w->prev on actual differences */ - /* in case we test more often than invoke the callback, */ - /* to ensure that prev is always different to attr */ - w->prev = prev; - - #if EV_USE_INOTIFY - if (fs_fd >= 0) - { - infy_del (EV_A_ w); - infy_add (EV_A_ w); - ev_stat_stat (EV_A_ w); /* avoid race... */ - } - #endif - - ev_feed_event (EV_A_ w, EV_STAT); - } -} - -void -ev_stat_start (EV_P_ ev_stat *w) -{ - if (expect_false (ev_is_active (w))) - return; - - ev_stat_stat (EV_A_ w); - - if (w->interval < MIN_STAT_INTERVAL && w->interval) - w->interval = MIN_STAT_INTERVAL; - - ev_timer_init (&w->timer, stat_timer_cb, 0., w->interval ? w->interval : DEF_STAT_INTERVAL); - ev_set_priority (&w->timer, ev_priority (w)); - -#if EV_USE_INOTIFY - infy_init (EV_A); - - if (fs_fd >= 0) - infy_add (EV_A_ w); - else -#endif - { - ev_timer_again (EV_A_ &w->timer); - ev_unref (EV_A); - } - - ev_start (EV_A_ (W)w, 1); - - EV_FREQUENT_CHECK; -} - -void -ev_stat_stop (EV_P_ ev_stat *w) -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - -#if EV_USE_INOTIFY - infy_del (EV_A_ w); -#endif - - if (ev_is_active (&w->timer)) - { - ev_ref (EV_A); - ev_timer_stop (EV_A_ &w->timer); - } - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} -#endif - -#if EV_IDLE_ENABLE -void -ev_idle_start (EV_P_ ev_idle *w) -{ - if (expect_false (ev_is_active (w))) - return; - - pri_adjust (EV_A_ (W)w); - - EV_FREQUENT_CHECK; - - { - int active = ++idlecnt [ABSPRI (w)]; - - ++idleall; - ev_start (EV_A_ (W)w, active); - - array_needsize (ev_idle *, idles [ABSPRI (w)], idlemax [ABSPRI (w)], active, EMPTY2); - idles [ABSPRI (w)][active - 1] = w; - } - - EV_FREQUENT_CHECK; -} - -void -ev_idle_stop (EV_P_ ev_idle *w) -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - { - int active = ev_active (w); - - idles [ABSPRI (w)][active - 1] = idles [ABSPRI (w)][--idlecnt [ABSPRI (w)]]; - ev_active (idles [ABSPRI (w)][active - 1]) = active; - - ev_stop (EV_A_ (W)w); - --idleall; - } - - EV_FREQUENT_CHECK; -} -#endif - -#if EV_PREPARE_ENABLE -void -ev_prepare_start (EV_P_ ev_prepare *w) -{ - if (expect_false (ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - ev_start (EV_A_ (W)w, ++preparecnt); - array_needsize (ev_prepare *, prepares, preparemax, preparecnt, EMPTY2); - prepares [preparecnt - 1] = w; - - EV_FREQUENT_CHECK; -} - -void -ev_prepare_stop (EV_P_ ev_prepare *w) -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - { - int active = ev_active (w); - - prepares [active - 1] = prepares [--preparecnt]; - ev_active (prepares [active - 1]) = active; - } - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} -#endif - -#if EV_CHECK_ENABLE -void -ev_check_start (EV_P_ ev_check *w) -{ - if (expect_false (ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - ev_start (EV_A_ (W)w, ++checkcnt); - array_needsize (ev_check *, checks, checkmax, checkcnt, EMPTY2); - checks [checkcnt - 1] = w; - - EV_FREQUENT_CHECK; -} - -void -ev_check_stop (EV_P_ ev_check *w) -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - { - int active = ev_active (w); - - checks [active - 1] = checks [--checkcnt]; - ev_active (checks [active - 1]) = active; - } - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} -#endif - -#if EV_EMBED_ENABLE -void noinline -ev_embed_sweep (EV_P_ ev_embed *w) -{ - ev_run (w->other, EVRUN_NOWAIT); -} - -static void -embed_io_cb (EV_P_ ev_io *io, int revents) -{ - ev_embed *w = (ev_embed *)(((char *)io) - offsetof (ev_embed, io)); - - if (ev_cb (w)) - ev_feed_event (EV_A_ (W)w, EV_EMBED); - else - ev_run (w->other, EVRUN_NOWAIT); -} - -static void -embed_prepare_cb (EV_P_ ev_prepare *prepare, int revents) -{ - ev_embed *w = (ev_embed *)(((char *)prepare) - offsetof (ev_embed, prepare)); - - { - EV_P = w->other; - - while (fdchangecnt) - { - fd_reify (EV_A); - ev_run (EV_A_ EVRUN_NOWAIT); - } - } -} - -static void -embed_fork_cb (EV_P_ ev_fork *fork_w, int revents) -{ - ev_embed *w = (ev_embed *)(((char *)fork_w) - offsetof (ev_embed, fork)); - - ev_embed_stop (EV_A_ w); - - { - EV_P = w->other; - - ev_loop_fork (EV_A); - ev_run (EV_A_ EVRUN_NOWAIT); - } - - ev_embed_start (EV_A_ w); -} - -#if 0 -static void -embed_idle_cb (EV_P_ ev_idle *idle, int revents) -{ - ev_idle_stop (EV_A_ idle); -} -#endif - -void -ev_embed_start (EV_P_ ev_embed *w) -{ - if (expect_false (ev_is_active (w))) - return; - - { - EV_P = w->other; - assert (("libev: loop to be embedded is not embeddable", backend & ev_embeddable_backends ())); - ev_io_init (&w->io, embed_io_cb, backend_fd, EV_READ); - } - - EV_FREQUENT_CHECK; - - ev_set_priority (&w->io, ev_priority (w)); - ev_io_start (EV_A_ &w->io); - - ev_prepare_init (&w->prepare, embed_prepare_cb); - ev_set_priority (&w->prepare, EV_MINPRI); - ev_prepare_start (EV_A_ &w->prepare); - - ev_fork_init (&w->fork, embed_fork_cb); - ev_fork_start (EV_A_ &w->fork); - - /*ev_idle_init (&w->idle, e,bed_idle_cb);*/ - - ev_start (EV_A_ (W)w, 1); - - EV_FREQUENT_CHECK; -} - -void -ev_embed_stop (EV_P_ ev_embed *w) -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - ev_io_stop (EV_A_ &w->io); - ev_prepare_stop (EV_A_ &w->prepare); - ev_fork_stop (EV_A_ &w->fork); - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} -#endif - -#if EV_FORK_ENABLE -void -ev_fork_start (EV_P_ ev_fork *w) -{ - if (expect_false (ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - ev_start (EV_A_ (W)w, ++forkcnt); - array_needsize (ev_fork *, forks, forkmax, forkcnt, EMPTY2); - forks [forkcnt - 1] = w; - - EV_FREQUENT_CHECK; -} - -void -ev_fork_stop (EV_P_ ev_fork *w) -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - { - int active = ev_active (w); - - forks [active - 1] = forks [--forkcnt]; - ev_active (forks [active - 1]) = active; - } - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} -#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 -void -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; - - ev_start (EV_A_ (W)w, ++asynccnt); - array_needsize (ev_async *, asyncs, asyncmax, asynccnt, EMPTY2); - asyncs [asynccnt - 1] = w; - - EV_FREQUENT_CHECK; -} - -void -ev_async_stop (EV_P_ ev_async *w) -{ - clear_pending (EV_A_ (W)w); - if (expect_false (!ev_is_active (w))) - return; - - EV_FREQUENT_CHECK; - - { - int active = ev_active (w); - - asyncs [active - 1] = asyncs [--asynccnt]; - ev_active (asyncs [active - 1]) = active; - } - - ev_stop (EV_A_ (W)w); - - EV_FREQUENT_CHECK; -} - -void -ev_async_send (EV_P_ ev_async *w) -{ - w->sent = 1; - evpipe_write (EV_A_ &async_pending); -} -#endif - -/*****************************************************************************/ - -struct ev_once -{ - ev_io io; - ev_timer to; - void (*cb)(int revents, void *arg); - void *arg; -}; - -static void -once_cb (EV_P_ struct ev_once *once, int revents) -{ - void (*cb)(int revents, void *arg) = once->cb; - void *arg = once->arg; - - ev_io_stop (EV_A_ &once->io); - ev_timer_stop (EV_A_ &once->to); - ev_free (once); - - cb (revents, arg); -} - -static void -once_cb_io (EV_P_ ev_io *w, int revents) -{ - struct ev_once *once = (struct ev_once *)(((char *)w) - offsetof (struct ev_once, io)); - - once_cb (EV_A_ once, revents | ev_clear_pending (EV_A_ &once->to)); -} - -static void -once_cb_to (EV_P_ ev_timer *w, int revents) -{ - struct ev_once *once = (struct ev_once *)(((char *)w) - offsetof (struct ev_once, to)); - - once_cb (EV_A_ once, revents | ev_clear_pending (EV_A_ &once->io)); -} - -void -ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) -{ - struct ev_once *once = (struct ev_once *)ev_malloc (sizeof (struct ev_once)); - - if (expect_false (!once)) - { - cb (EV_ERROR | EV_READ | EV_WRITE | EV_TIMER, arg); - return; - } - - once->cb = cb; - once->arg = arg; - - ev_init (&once->io, once_cb_io); - if (fd >= 0) - { - ev_io_set (&once->io, fd, events); - ev_io_start (EV_A_ &once->io); - } - - ev_init (&once->to, once_cb_to); - if (timeout >= 0.) - { - ev_timer_set (&once->to, timeout, 0.); - ev_timer_start (EV_A_ &once->to); - } -} - -/*****************************************************************************/ - -#if EV_WALK_ENABLE -void -ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) -{ - int i, j; - ev_watcher_list *wl, *wn; - - if (types & (EV_IO | EV_EMBED)) - for (i = 0; i < anfdmax; ++i) - for (wl = anfds [i].head; wl; ) - { - wn = wl->next; - -#if EV_EMBED_ENABLE - if (ev_cb ((ev_io *)wl) == embed_io_cb) - { - if (types & EV_EMBED) - cb (EV_A_ EV_EMBED, ((char *)wl) - offsetof (struct ev_embed, io)); - } - else -#endif -#if EV_USE_INOTIFY - if (ev_cb ((ev_io *)wl) == infy_cb) - ; - else -#endif - if ((ev_io *)wl != &pipe_w) - if (types & EV_IO) - cb (EV_A_ EV_IO, wl); - - wl = wn; - } - - if (types & (EV_TIMER | EV_STAT)) - for (i = timercnt + HEAP0; i-- > HEAP0; ) -#if EV_STAT_ENABLE - /*TODO: timer is not always active*/ - if (ev_cb ((ev_timer *)ANHE_w (timers [i])) == stat_timer_cb) - { - if (types & EV_STAT) - cb (EV_A_ EV_STAT, ((char *)ANHE_w (timers [i])) - offsetof (struct ev_stat, timer)); - } - else -#endif - if (types & EV_TIMER) - cb (EV_A_ EV_TIMER, ANHE_w (timers [i])); - -#if EV_PERIODIC_ENABLE - if (types & EV_PERIODIC) - for (i = periodiccnt + HEAP0; i-- > HEAP0; ) - cb (EV_A_ EV_PERIODIC, ANHE_w (periodics [i])); -#endif - -#if EV_IDLE_ENABLE - if (types & EV_IDLE) - for (j = NUMPRI; i--; ) - for (i = idlecnt [j]; i--; ) - cb (EV_A_ EV_IDLE, idles [j][i]); -#endif - -#if EV_FORK_ENABLE - if (types & EV_FORK) - for (i = forkcnt; i--; ) - if (ev_cb (forks [i]) != embed_fork_cb) - cb (EV_A_ EV_FORK, forks [i]); -#endif - -#if EV_ASYNC_ENABLE - if (types & EV_ASYNC) - for (i = asynccnt; i--; ) - 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_cb (prepares [i]) != embed_prepare_cb) -# 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; ) - { - wn = wl->next; - cb (EV_A_ EV_SIGNAL, wl); - wl = wn; - } -#endif - -#if EV_CHILD_ENABLE - if (types & EV_CHILD) - 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 */ -} -#endif - -#if EV_MULTIPLICITY - #include "ev_wrap.h" -#endif - -EV_CPP(}) - diff --git a/src/util/k5ev/ev.h b/src/util/k5ev/ev.h deleted file mode 100644 index 27c1778f1..000000000 --- a/src/util/k5ev/ev.h +++ /dev/null @@ -1,829 +0,0 @@ -/* - * libev native API header - * - * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modifica- - * tion, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- - * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- - * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- - * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License ("GPL") version 2 or any later version, - * in which case the provisions of the GPL are applicable instead of - * the above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the BSD license, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file under - * either the BSD or the GPL. - */ - -#ifndef EV_H_ -#define EV_H_ - -#ifdef __cplusplus -# define EV_CPP(x) x -#else -# define EV_CPP(x) -#endif - -EV_CPP(extern "C" {) - -/*****************************************************************************/ - -/* 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 invoked earlier */ -#ifndef EV_MINPRI -# define EV_MINPRI (EV_FEATURE_CONFIG ? -2 : 0) -#endif -#ifndef EV_MAXPRI -# define EV_MAXPRI (EV_FEATURE_CONFIG ? +2 : 0) -#endif - -#ifndef EV_MULTIPLICITY -# define EV_MULTIPLICITY EV_FEATURE_CONFIG -#endif - -#ifndef EV_PERIODIC_ENABLE -# define EV_PERIODIC_ENABLE EV_FEATURE_WATCHERS -#endif - -#ifndef EV_STAT_ENABLE -# 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 EV_FEATURE_WATCHERS -#endif - -#ifndef EV_FORK_ENABLE -# define EV_FORK_ENABLE EV_FEATURE_WATCHERS -#endif - -#ifndef EV_CLEANUP_ENABLE -# define EV_CLEANUP_ENABLE EV_FEATURE_WATCHERS -#endif - -#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 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 <signal.h> -# define EV_ATOMIC_T sig_atomic_t volatile -#endif - -#if EV_STAT_ENABLE -# ifdef _WIN32 -# include <time.h> -# include <sys/types.h> -# endif -# include <sys/stat.h> -#endif - -/* support multiple event loops? */ -#if EV_MULTIPLICITY -struct ev_loop; -# define EV_P struct ev_loop *loop /* a loop as sole parameter in a declaration */ -# define EV_P_ EV_P, /* a loop as first of multiple parameters */ -# define EV_A loop /* a loop as sole argument to a function call */ -# define EV_A_ EV_A, /* a loop as first of multiple arguments */ -# define EV_DEFAULT_UC ev_default_loop_uc_ () /* the default loop, if initialised, as sole arg */ -# define EV_DEFAULT_UC_ EV_DEFAULT_UC, /* the default loop as first of multiple arguments */ -# define EV_DEFAULT ev_default_loop (0) /* the default loop as sole arg */ -# define EV_DEFAULT_ EV_DEFAULT, /* the default loop as first of multiple arguments */ -#else -# define EV_P void -# define EV_P_ -# define EV_A -# define EV_A_ -# define EV_DEFAULT -# define EV_DEFAULT_ -# define EV_DEFAULT_UC -# define EV_DEFAULT_UC_ -# undef EV_EMBED_ENABLE -#endif - -/* EV_INLINE is used for functions in header files */ -#if __STDC_VERSION__ >= 199901L || __GNUC__ >= 3 -# define EV_INLINE static inline -#else -# define EV_INLINE static -#endif - -/* EV_PROTOTYPES can be used to switch of prototype declarations */ -#ifndef EV_PROTOTYPES -# define EV_PROTOTYPES 1 -#endif - -/*****************************************************************************/ - -#define EV_VERSION_MAJOR 4 -#define EV_VERSION_MINOR 4 - -/* eventmask, revents, events... */ -enum { - EV_UNDEF = 0xFFFFFFFF, /* 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 */ -#if EV_COMPAT3 - EV_TIMEOUT = EV_TIMER, /* pre 4.0 API compatibility */ -#endif - 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_CLEANUP = 0x00040000, /* event loop resumed in child */ - EV_ASYNC = 0x00080000, /* 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_CB_DECLARE -# define EV_CB_DECLARE(type) void (*cb)(EV_P_ struct type *w, int revents); -#endif -#ifndef EV_CB_INVOKE -# 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, - * and they might not mean anything to you. - * ro: can be read anytime, but only changed when the watcher isn't active. - * rw: can be read and modified anytime, even when the watcher is active. - * - * some internal details that might be helpful for debugging: - * - * active is either 0, which means the watcher is not active, - * or the array index of the watcher (periodics, timers) - * or the array index + 1 (most other watchers) - * or simply 1 for watchers that aren't in some array. - * pending is either 0, in which case the watcher isn't, - * or the array index + 1 in the pendings array. - */ - -#if EV_MINPRI == EV_MAXPRI -# define EV_DECL_PRIORITY -#elif !defined (EV_DECL_PRIORITY) -# define EV_DECL_PRIORITY int priority; -#endif - -/* shared by all watchers */ -#define EV_WATCHER(type) \ - int active; /* private */ \ - int pending; /* private */ \ - EV_DECL_PRIORITY /* private */ \ - EV_COMMON /* rw */ \ - EV_CB_DECLARE (type) /* private */ - -#define EV_WATCHER_LIST(type) \ - EV_WATCHER (type) \ - struct ev_watcher_list *next; /* private */ - -#define EV_WATCHER_TIME(type) \ - EV_WATCHER (type) \ - ev_tstamp at; /* private */ - -/* base class, nothing to see here unless you subclass */ -typedef struct ev_watcher -{ - EV_WATCHER (ev_watcher) -} ev_watcher; - -/* base class, nothing to see here unless you subclass */ -typedef struct ev_watcher_list -{ - EV_WATCHER_LIST (ev_watcher_list) -} ev_watcher_list; - -/* base class, nothing to see here unless you subclass */ -typedef struct ev_watcher_time -{ - EV_WATCHER_TIME (ev_watcher_time) -} ev_watcher_time; - -/* invoked when fd is either EV_READable or EV_WRITEable */ -/* revent EV_READ, EV_WRITE */ -typedef struct ev_io -{ - EV_WATCHER_LIST (ev_io) - - int fd; /* ro */ - int events; /* ro */ -} ev_io; - -/* invoked after a specific time, repeatable (based on monotonic clock) */ -/* revent EV_TIMEOUT */ -typedef struct ev_timer -{ - EV_WATCHER_TIME (ev_timer) - - ev_tstamp repeat; /* rw */ -} ev_timer; - -/* invoked at some specific time, possibly repeating at regular intervals (based on UTC) */ -/* revent EV_PERIODIC */ -typedef struct ev_periodic -{ - EV_WATCHER_TIME (ev_periodic) - - ev_tstamp offset; /* rw */ - ev_tstamp interval; /* rw */ - ev_tstamp (*reschedule_cb)(struct ev_periodic *w, ev_tstamp now); /* rw */ -} ev_periodic; - -/* invoked when the given signal has been received */ -/* revent EV_SIGNAL */ -typedef struct ev_signal -{ - EV_WATCHER_LIST (ev_signal) - - int signum; /* ro */ -} ev_signal; - -/* invoked when sigchld is received and waitpid indicates the given pid */ -/* revent EV_CHILD */ -/* does not support priorities */ -typedef struct ev_child -{ - EV_WATCHER_LIST (ev_child) - - int flags; /* private */ - int pid; /* ro */ - int rpid; /* rw, holds the received pid */ - int rstatus; /* rw, holds the exit status, use the macros from sys/wait.h */ -} ev_child; - -#if EV_STAT_ENABLE -/* st_nlink = 0 means missing file or other error */ -# ifdef _WIN32 -typedef struct _stati64 ev_statdata; -# else -typedef struct stat ev_statdata; -# endif - -/* invoked each time the stat data changes for a given path */ -/* revent EV_STAT */ -typedef struct ev_stat -{ - EV_WATCHER_LIST (ev_stat) - - ev_timer timer; /* private */ - ev_tstamp interval; /* ro */ - const char *path; /* ro */ - ev_statdata prev; /* ro */ - ev_statdata attr; /* ro */ - - int wd; /* wd for inotify, fd for kqueue */ -} ev_stat; -#endif - -#if EV_IDLE_ENABLE -/* invoked when the nothing else needs to be done, keeps the process from blocking */ -/* revent EV_IDLE */ -typedef struct ev_idle -{ - EV_WATCHER (ev_idle) -} ev_idle; -#endif - -/* invoked for each run of the mainloop, just before the blocking call */ -/* you can still change events in any way you like */ -/* revent EV_PREPARE */ -typedef struct ev_prepare -{ - EV_WATCHER (ev_prepare) -} ev_prepare; - -/* invoked for each run of the mainloop, just after the blocking call */ -/* revent EV_CHECK */ -typedef struct ev_check -{ - EV_WATCHER (ev_check) -} ev_check; - -#if EV_FORK_ENABLE -/* the callback gets invoked before check in the child process when a fork was detected */ -/* revent EV_FORK */ -typedef struct ev_fork -{ - EV_WATCHER (ev_fork) -} ev_fork; -#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 -/* used to embed an event loop inside another */ -/* the callback gets invoked when the event loop has handled events, and can be 0 */ -typedef struct ev_embed -{ - EV_WATCHER (ev_embed) - - struct ev_loop *other; /* ro */ - ev_io io; /* private */ - ev_prepare prepare; /* private */ - ev_check check; /* unused */ - ev_timer timer; /* unused */ - ev_periodic periodic; /* unused */ - ev_idle idle; /* unused */ - ev_fork fork; /* private */ -#if EV_CLEANUP_ENABLE - ev_cleanup cleanup; /* unused */ -#endif -} ev_embed; -#endif - -#if EV_ASYNC_ENABLE -/* invoked when somebody calls ev_async_send on the watcher */ -/* revent EV_ASYNC */ -typedef struct ev_async -{ - EV_WATCHER (ev_async) - - EV_ATOMIC_T sent; /* private */ -} ev_async; - -# define ev_async_pending(w) (+(w)->sent) -#endif - -/* the presence of this union forces similar struct layout */ -union ev_any_watcher -{ - struct ev_watcher w; - struct ev_watcher_list wl; - - struct ev_io io; - struct ev_timer timer; - struct ev_periodic periodic; - struct ev_signal signal; - struct ev_child child; -#if EV_STAT_ENABLE - struct ev_stat stat; -#endif -#if EV_IDLE_ENABLE - struct ev_idle idle; -#endif - struct ev_prepare prepare; - struct ev_check check; -#if EV_FORK_ENABLE - struct ev_fork fork; -#endif -#if EV_CLEANUP_ENABLE - struct ev_cleanup cleanup; -#endif -#if EV_EMBED_ENABLE - struct ev_embed embed; -#endif -#if EV_ASYNC_ENABLE - struct ev_async async; -#endif -}; - -/* 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 */ - EVFLAG_NOSIGMASK = 0x00400000U /* avoid modifying the signal mask */ -}; - -/* method bits to be ored together */ -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, /* all known backends */ - EVBACKEND_MASK = 0x0000FFFFU /* all future backends */ -}; - -#if EV_PROTOTYPES -int ev_version_major (void); -int ev_version_minor (void); - -unsigned int ev_supported_backends (void); -unsigned int ev_recommended_backends (void); -unsigned int ev_embeddable_backends (void); - -ev_tstamp ev_time (void); -void ev_sleep (ev_tstamp delay); /* sleep for a while */ - -/* Sets the allocation function to use, works like realloc. - * It is used to allocate and free memory. - * If it returns zero when memory needs to be allocated, the library might abort - * or take some potentially destructive action. - * The default is your system realloc function. - */ -void ev_set_allocator (void *(*cb)(void *ptr, long size)); - -/* set the callback function to call on a - * retryable syscall error - * (such as failed select, poll, epoll_wait) - */ -void ev_set_syserr_cb (void (*cb)(const char *msg)); - -#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_default_loop_uc_ (void) -{ - extern struct ev_loop *ev_default_loop_ptr; - - return ev_default_loop_ptr; -} - -EV_INLINE int -ev_is_default_loop (EV_P) -{ - return EV_A == EV_DEFAULT_UC; -} - -/* create and destroy alternative loops that don't handle signals */ -struct ev_loop *ev_loop_new (unsigned int flags EV_CPP (= 0)); - -ev_tstamp ev_now (EV_P); /* time w.r.t. timers and the eventloop, updated after each poll */ - -#else - -int ev_default_loop (unsigned int flags EV_CPP (= 0)); /* returns true when successful */ - -EV_INLINE ev_tstamp -ev_now (void) -{ - extern ev_tstamp ev_rt_now; - - return ev_rt_now; -} - -/* looks weird, but ev_is_default_loop (EV_A) still works if this exists */ -EV_INLINE int -ev_is_default_loop (void) -{ - return 1; -} - -#endif /* multiplicity */ - -/* 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 actually call it at any time, anywhere :) */ -void ev_loop_fork (EV_P); - -unsigned int ev_backend (EV_P); /* backend in use by loop */ - -void ev_now_update (EV_P); /* update event loop time */ - -#if EV_WALK_ENABLE -/* walk (almost) all watchers in the loop of a given type, invoking the */ -/* callback on every such watcher. The callback might stop the watcher, */ -/* but do nothing else with the loop */ -void ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)); -#endif - -#endif /* prototypes */ - -/* 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_run (EV_P_ int flags EV_CPP (= 0)); -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 - * keeps one reference. if you have a long-running watcher you never unregister that - * should not keep ev_loop from running, unref() after starting, and ref() before stopping. - */ -void ev_ref (EV_P); -void ev_unref (EV_P); - -/* - * convenience function, wait for a single event, without registering an event watcher - * if timeout is < 0, do wait indefinitely - */ -void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg); - -# 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 */ - -/* advanced stuff for threading etc. support, see docs */ -void ev_set_userdata (EV_P_ void *data); -void *ev_userdata (EV_P); -void ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P)); -void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P)); - -unsigned int ev_pending_count (EV_P); /* number of pending events, if any */ -void ev_invoke_pending (EV_P); /* invoke all pending watchers */ - -/* - * stop/start the timer handling. - */ -void ev_suspend (EV_P); -void ev_resume (EV_P); -#endif - -#endif - -/* these may evaluate ev multiple times, and the other arguments at most once */ -/* either use ev_init + ev_TYPE_set, or the ev_TYPE_init macro, below, to first initialise a watcher */ -#define ev_init(ev,cb_) do { \ - ((ev_watcher *)(void *)(ev))->active = \ - ((ev_watcher *)(void *)(ev))->pending = 0; \ - ev_set_priority ((ev), 0); \ - ev_set_cb ((ev), cb_); \ -} while (0) - -#define ev_io_set(ev,fd_,events_) do { (ev)->fd = (fd_); (ev)->events = (events_) | EV__IOFDSET; } while (0) -#define ev_timer_set(ev,after_,repeat_) do { ((ev_watcher_time *)(ev))->at = (after_); (ev)->repeat = (repeat_); } while (0) -#define ev_periodic_set(ev,ofs_,ival_,rcb_) do { (ev)->offset = (ofs_); (ev)->interval = (ival_); (ev)->reschedule_cb = (rcb_); } while (0) -#define ev_signal_set(ev,signum_) do { (ev)->signum = (signum_); } while (0) -#define ev_child_set(ev,pid_,trace_) do { (ev)->pid = (pid_); (ev)->flags = !!(trace_); } while (0) -#define ev_stat_set(ev,path_,interval_) do { (ev)->path = (path_); (ev)->interval = (interval_); (ev)->wd = -2; } while (0) -#define ev_idle_set(ev) /* nop, yes, this is a serious in-joke */ -#define ev_prepare_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_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_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) -#define ev_periodic_init(ev,cb,ofs,ival,rcb) do { ev_init ((ev), (cb)); ev_periodic_set ((ev),(ofs),(ival),(rcb)); } while (0) -#define ev_signal_init(ev,cb,signum) do { ev_init ((ev), (cb)); ev_signal_set ((ev), (signum)); } while (0) -#define ev_child_init(ev,cb,pid,trace) do { ev_init ((ev), (cb)); ev_child_set ((ev),(pid),(trace)); } while (0) -#define ev_stat_init(ev,cb,path,interval) do { ev_init ((ev), (cb)); ev_stat_set ((ev),(path),(interval)); } while (0) -#define ev_idle_init(ev,cb) do { ev_init ((ev), (cb)); ev_idle_set ((ev)); } while (0) -#define ev_prepare_init(ev,cb) do { ev_init ((ev), (cb)); ev_prepare_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_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_is_pending(ev) (0 + ((ev_watcher *)(void *)(ev))->pending) /* ro, true when watcher is waiting for callback invocation */ -#define ev_is_active(ev) (0 + ((ev_watcher *)(void *)(ev))->active) /* ro, true when the watcher has been started */ - -#define ev_cb(ev) (ev)->cb /* rw */ - -#if EV_MINPRI == EV_MAXPRI -# define ev_priority(ev) ((ev), EV_MINPRI) -# 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) -#endif - -#define ev_periodic_at(ev) (+((ev_watcher_time *)(ev))->at) - -#ifndef ev_set_cb -# define ev_set_cb(ev,cb_) ev_cb (ev) = (cb_) -#endif - -/* stopping (enabling, adding) a watcher does nothing if it is already running */ -/* stopping (disabling, deleting) a watcher does nothing unless its already running */ -#if EV_PROTOTYPES - -/* feeds an event into a watcher as if the event actually occured */ -/* 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 (int signum); -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); - -void ev_io_start (EV_P_ ev_io *w); -void ev_io_stop (EV_P_ ev_io *w); - -void ev_timer_start (EV_P_ ev_timer *w); -void ev_timer_stop (EV_P_ ev_timer *w); -/* stops if active and no repeat, restarts if active and repeating, starts if inactive and repeating */ -void ev_timer_again (EV_P_ ev_timer *w); -/* return remaining time */ -ev_tstamp ev_timer_remaining (EV_P_ ev_timer *w); - -#if EV_PERIODIC_ENABLE -void ev_periodic_start (EV_P_ ev_periodic *w); -void ev_periodic_stop (EV_P_ ev_periodic *w); -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); -void ev_stat_stop (EV_P_ ev_stat *w); -void ev_stat_stat (EV_P_ ev_stat *w); -# endif - -# if EV_IDLE_ENABLE -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); -void ev_fork_stop (EV_P_ ev_fork *w); -# 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 -/* only supported when loop to be embedded is in fact embeddable */ -void ev_embed_start (EV_P_ ev_embed *w); -void ev_embed_stop (EV_P_ ev_embed *w); -void ev_embed_sweep (EV_P_ ev_embed *w); -# endif - -# if EV_ASYNC_ENABLE -void ev_async_start (EV_P_ ev_async *w); -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 ); } - 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 - EV_INLINE unsigned int ev_loop_count (EV_P) { return ev_iteration (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); } - #endif - #endif -#else - typedef struct ev_loop ev_loop; -#endif - -#endif - -EV_CPP(}) - -#endif - diff --git a/src/util/k5ev/ev_poll.c b/src/util/k5ev/ev_poll.c deleted file mode 100644 index e53ae0de9..000000000 --- a/src/util/k5ev/ev_poll.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * libev poll fd activity backend - * - * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modifica- - * tion, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- - * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- - * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- - * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License ("GPL") version 2 or any later version, - * in which case the provisions of the GPL are applicable instead of - * the above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the BSD license, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file under - * either the BSD or the GPL. - */ - -#include <poll.h> - -void inline_size -pollidx_init (int *base, int count) -{ - /* consider using memset (.., -1, ...), which is practically guaranteed - * to work on all systems implementing poll */ - while (count--) - *base++ = -1; -} - -static void -poll_modify (EV_P_ int fd, int oev, int nev) -{ - int idx; - - if (oev == nev) - return; - - array_needsize (int, pollidxs, pollidxmax, fd + 1, pollidx_init); - - idx = pollidxs [fd]; - - if (idx < 0) /* need to allocate a new pollfd */ - { - pollidxs [fd] = idx = pollcnt++; - array_needsize (struct pollfd, polls, pollmax, pollcnt, EMPTY2); - polls [idx].fd = fd; - } - - assert (polls [idx].fd == fd); - - if (nev) - polls [idx].events = - (nev & EV_READ ? POLLIN : 0) - | (nev & EV_WRITE ? POLLOUT : 0); - else /* remove pollfd */ - { - pollidxs [fd] = -1; - - if (expect_true (idx < --pollcnt)) - { - polls [idx] = polls [pollcnt]; - pollidxs [polls [idx].fd] = idx; - } - } -} - -static void -poll_poll (EV_P_ ev_tstamp timeout) -{ - struct pollfd *p; - int res; - - EV_RELEASE_CB; - res = poll (polls, pollcnt, ev_timeout_to_ms (timeout)); - EV_ACQUIRE_CB; - - if (expect_false (res < 0)) - { - if (errno == EBADF) - fd_ebadf (EV_A); - else if (errno == ENOMEM && !syserr_cb) - fd_enomem (EV_A); - else if (errno != EINTR) - ev_syserr ("(libev) poll"); - } - else - for (p = polls; res; ++p) - { - 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 -poll_init (EV_P_ int flags) -{ - backend_fudge = 0.; /* posix says this is zero */ - backend_modify = poll_modify; - backend_poll = poll_poll; - - pollidxs = 0; pollidxmax = 0; - polls = 0; pollmax = 0; pollcnt = 0; - - return EVBACKEND_POLL; -} - -void inline_size -poll_destroy (EV_P) -{ - ev_free (pollidxs); - ev_free (polls); -} - diff --git a/src/util/k5ev/ev_select.c b/src/util/k5ev/ev_select.c deleted file mode 100644 index 0ea9467e4..000000000 --- a/src/util/k5ev/ev_select.c +++ /dev/null @@ -1,310 +0,0 @@ -/* - * libev select fd activity backend - * - * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev@schmorp.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modifica- - * tion, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- - * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- - * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- - * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License ("GPL") version 2 or any later version, - * in which case the provisions of the GPL are applicable instead of - * the above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the BSD license, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file under - * either the BSD or the GPL. - */ - -#ifndef _WIN32 -/* for unix systems */ -# include <inttypes.h> -# ifndef __hpux -/* for REAL unix systems */ -# include <sys/select.h> -# endif -#endif - -#ifndef EV_SELECT_USE_FD_SET -# ifdef NFDBITS -# define EV_SELECT_USE_FD_SET 0 -# else -# define EV_SELECT_USE_FD_SET 1 -# endif -#endif - -#if EV_SELECT_IS_WINSOCKET -# undef EV_SELECT_USE_FD_SET -# define EV_SELECT_USE_FD_SET 1 -# undef NFDBITS -# define NFDBITS 0 -#endif - -#if !EV_SELECT_USE_FD_SET -# define NFDBYTES (NFDBITS / 8) -#endif - -#include <string.h> - -static void -select_modify (EV_P_ int fd, int oev, int nev) -{ - if (oev == nev) - return; - - { -#if EV_SELECT_USE_FD_SET - - #if EV_SELECT_IS_WINSOCKET - SOCKET handle = anfds [fd].handle; - #else - int handle = fd; - #endif - - assert (("libev: fd >= FD_SETSIZE passed to fd_set-based select backend", fd < FD_SETSIZE)); - - /* FD_SET is broken on windows (it adds the fd to a set twice or more, - * which eventually leads to overflows). Need to call it only on changes. - */ - #if EV_SELECT_IS_WINSOCKET - if ((oev ^ nev) & EV_READ) - #endif - if (nev & EV_READ) - FD_SET (handle, (fd_set *)vec_ri); - else - FD_CLR (handle, (fd_set *)vec_ri); - - #if EV_SELECT_IS_WINSOCKET - if ((oev ^ nev) & EV_WRITE) - #endif - if (nev & EV_WRITE) - FD_SET (handle, (fd_set *)vec_wi); - else - FD_CLR (handle, (fd_set *)vec_wi); - -#else - - int word = fd / NFDBITS; - fd_mask mask = 1UL << (fd % NFDBITS); - - if (expect_false (vec_max <= word)) - { - int new_max = word + 1; - - vec_ri = ev_realloc (vec_ri, new_max * NFDBYTES); - vec_ro = ev_realloc (vec_ro, new_max * NFDBYTES); /* could free/malloc */ - vec_wi = ev_realloc (vec_wi, new_max * NFDBYTES); - vec_wo = ev_realloc (vec_wo, new_max * NFDBYTES); /* could free/malloc */ - #ifdef _WIN32 - vec_eo = ev_realloc (vec_eo, new_max * NFDBYTES); /* could free/malloc */ - #endif - - for (; vec_max < new_max; ++vec_max) - ((fd_mask *)vec_ri) [vec_max] = - ((fd_mask *)vec_wi) [vec_max] = 0; - } - - ((fd_mask *)vec_ri) [word] |= mask; - if (!(nev & EV_READ)) - ((fd_mask *)vec_ri) [word] &= ~mask; - - ((fd_mask *)vec_wi) [word] |= mask; - if (!(nev & EV_WRITE)) - ((fd_mask *)vec_wi) [word] &= ~mask; -#endif - } -} - -static void -select_poll (EV_P_ ev_tstamp timeout) -{ - struct timeval tv; - int res; - int fd_setsize; - - EV_RELEASE_CB; - EV_TV_SET (tv, timeout); - -#if EV_SELECT_USE_FD_SET - fd_setsize = sizeof (fd_set); -#else - fd_setsize = vec_max * NFDBYTES; -#endif - - memcpy (vec_ro, vec_ri, fd_setsize); - memcpy (vec_wo, vec_wi, fd_setsize); - -#ifdef _WIN32 - /* pass in the write set as except set. - * the idea behind this is to work around a windows bug that causes - * errors to be reported as an exception and not by setting - * the writable bit. this is so uncontrollably lame. - */ - memcpy (vec_eo, vec_wi, fd_setsize); - res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, (fd_set *)vec_eo, &tv); -#elif EV_SELECT_USE_FD_SET - fd_setsize = anfdmax < FD_SETSIZE ? anfdmax : FD_SETSIZE; - res = select (fd_setsize, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv); -#else - res = select (vec_max * NFDBITS, (fd_set *)vec_ro, (fd_set *)vec_wo, 0, &tv); -#endif - EV_ACQUIRE_CB; - - if (expect_false (res < 0)) - { - #if EV_SELECT_IS_WINSOCKET - errno = WSAGetLastError (); - #endif - #ifdef WSABASEERR - /* on windows, select returns incompatible error codes, fix this */ - if (errno >= WSABASEERR && errno < WSABASEERR + 1000) - if (errno == WSAENOTSOCK) - errno = EBADF; - else - errno -= WSABASEERR; - #endif - - #ifdef _WIN32 - /* 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. - * we also get EINVAL when the timeout is invalid, but we ignore this case here - * and assume that EINVAL always means: you have to wait manually. - */ - if (errno == EINVAL) - { - ev_sleep (timeout); - return; - } - #endif - - if (errno == EBADF) - fd_ebadf (EV_A); - else if (errno == ENOMEM && !syserr_cb) - fd_enomem (EV_A); - else if (errno != EINTR) - ev_syserr ("(libev) select"); - - return; - } - -#if EV_SELECT_USE_FD_SET - - { - int fd; - - for (fd = 0; fd < anfdmax; ++fd) - if (anfds [fd].events) - { - int events = 0; - #if EV_SELECT_IS_WINSOCKET - SOCKET handle = anfds [fd].handle; - #else - int handle = fd; - #endif - - if (FD_ISSET (handle, (fd_set *)vec_ro)) events |= EV_READ; - if (FD_ISSET (handle, (fd_set *)vec_wo)) events |= EV_WRITE; - #ifdef _WIN32 - if (FD_ISSET (handle, (fd_set *)vec_eo)) events |= EV_WRITE; - #endif - - if (expect_true (events)) - fd_event (EV_A_ fd, events); - } - } - -#else - - { - int word, bit; - for (word = vec_max; word--; ) - { - fd_mask word_r = ((fd_mask *)vec_ro) [word]; - fd_mask word_w = ((fd_mask *)vec_wo) [word]; - #ifdef _WIN32 - word_w |= ((fd_mask *)vec_eo) [word]; - #endif - - if (word_r || word_w) - for (bit = NFDBITS; bit--; ) - { - fd_mask mask = 1UL << bit; - int events = 0; - - events |= word_r & mask ? EV_READ : 0; - events |= word_w & mask ? EV_WRITE : 0; - - if (expect_true (events)) - fd_event (EV_A_ word * NFDBITS + bit, events); - } - } - } - -#endif -} - -int inline_size -select_init (EV_P_ int flags) -{ - backend_fudge = 0.; /* posix says this is zero */ - backend_modify = select_modify; - backend_poll = select_poll; - -#if EV_SELECT_USE_FD_SET - vec_ri = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_ri); - vec_ro = ev_malloc (sizeof (fd_set)); - vec_wi = ev_malloc (sizeof (fd_set)); FD_ZERO ((fd_set *)vec_wi); - vec_wo = ev_malloc (sizeof (fd_set)); - #ifdef _WIN32 - vec_eo = ev_malloc (sizeof (fd_set)); - #endif -#else - vec_max = 0; - vec_ri = 0; - vec_ro = 0; - vec_wi = 0; - vec_wo = 0; - #ifdef _WIN32 - vec_eo = 0; - #endif -#endif - - return EVBACKEND_SELECT; -} - -void inline_size -select_destroy (EV_P) -{ - ev_free (vec_ri); - ev_free (vec_ro); - ev_free (vec_wi); - ev_free (vec_wo); - #ifdef _WIN32 - ev_free (vec_eo); - #endif -} - - diff --git a/src/util/k5ev/ev_vars.h b/src/util/k5ev/ev_vars.h deleted file mode 100644 index 5ee3ed1b2..000000000 --- a/src/util/k5ev/ev_vars.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * loop member variable declarations - * - * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev@schmorp.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modifica- - * tion, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- - * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- - * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- - * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License ("GPL") version 2 or any later version, - * in which case the provisions of the GPL are applicable instead of - * the above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the BSD license, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file under - * either the BSD or the GPL. - */ - -#define VARx(type,name) VAR(name, type name) - -VARx(ev_tstamp, now_floor) /* last time we refreshed rt_time */ -VARx(ev_tstamp, mn_now) /* monotonic clock "now" */ -VARx(ev_tstamp, rtmn_diff) /* difference realtime - monotonic time */ - -VARx(ev_tstamp, io_blocktime) -VARx(ev_tstamp, timeout_blocktime) - -VARx(int, backend) -VARx(int, activecnt) /* total number of active events ("refcount") */ -VARx(EV_ATOMIC_T, loop_done) /* signal by ev_break */ - -VARx(int, backend_fd) -VARx(ev_tstamp, backend_fudge) /* assumed typical timer resolution */ -VAR (backend_modify, void (*backend_modify)(EV_P_ int fd, int oev, int nev)) -VAR (backend_poll , void (*backend_poll)(EV_P_ ev_tstamp timeout)) - -VARx(ANFD *, anfds) -VARx(int, anfdmax) - -VAR (pendings, ANPENDING *pendings [NUMPRI]) -VAR (pendingmax, int pendingmax [NUMPRI]) -VAR (pendingcnt, int pendingcnt [NUMPRI]) -VARx(ev_prepare, pending_w) /* dummy pending watcher */ - -/* for reverse feeding of events */ -VARx(W *, rfeeds) -VARx(int, rfeedmax) -VARx(int, rfeedcnt) - -#if EV_USE_EVENTFD || EV_GENWRAP -VARx(int, evfd) -#endif -VAR (evpipe, int evpipe [2]) -VARx(ev_io, pipe_w) - -#if !defined(_WIN32) || EV_GENWRAP -VARx(pid_t, curpid) -#endif - -VARx(char, postfork) /* true if we need to recreate kernel state after fork */ - -#if EV_USE_SELECT || EV_GENWRAP -VARx(void *, vec_ri) -VARx(void *, vec_ro) -VARx(void *, vec_wi) -VARx(void *, vec_wo) -#if defined(_WIN32) || EV_GENWRAP -VARx(void *, vec_eo) -#endif -VARx(int, vec_max) -#endif - -#if EV_USE_POLL || EV_GENWRAP -VARx(struct pollfd *, polls) -VARx(int, pollmax) -VARx(int, pollcnt) -VARx(int *, pollidxs) /* maps fds into structure indices */ -VARx(int, pollidxmax) -#endif - -#if EV_USE_EPOLL || EV_GENWRAP -VARx(struct epoll_event *, epoll_events) -VARx(int, epoll_eventmax) -VARx(int *, epoll_eperms) -VARx(int, epoll_epermcnt) -VARx(int, epoll_epermmax) -#endif - -#if EV_USE_KQUEUE || EV_GENWRAP -VARx(struct kevent *, kqueue_changes) -VARx(int, kqueue_changemax) -VARx(int, kqueue_changecnt) -VARx(struct kevent *, kqueue_events) -VARx(int, kqueue_eventmax) -#endif - -#if EV_USE_PORT || EV_GENWRAP -VARx(struct port_event *, port_events) -VARx(int, port_eventmax) -#endif - -#if EV_USE_IOCP || EV_GENWRAP -VARx(HANDLE, iocp) -#endif - -VARx(int *, fdchanges) -VARx(int, fdchangemax) -VARx(int, fdchangecnt) - -VARx(ANHE *, timers) -VARx(int, timermax) -VARx(int, timercnt) - -#if EV_PERIODIC_ENABLE || EV_GENWRAP -VARx(ANHE *, periodics) -VARx(int, periodicmax) -VARx(int, periodiccnt) -#endif - -#if EV_IDLE_ENABLE || EV_GENWRAP -VAR (idles, ev_idle **idles [NUMPRI]) -VAR (idlemax, int idlemax [NUMPRI]) -VAR (idlecnt, int idlecnt [NUMPRI]) -#endif -VARx(int, idleall) /* total number */ - -VARx(struct ev_prepare **, prepares) -VARx(int, preparemax) -VARx(int, preparecnt) - -VARx(struct ev_check **, checks) -VARx(int, checkmax) -VARx(int, checkcnt) - -#if EV_FORK_ENABLE || EV_GENWRAP -VARx(struct ev_fork **, forks) -VARx(int, forkmax) -VARx(int, forkcnt) -#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 -VARx(EV_ATOMIC_T, async_pending) -VARx(struct ev_async **, asyncs) -VARx(int, asyncmax) -VARx(int, asynccnt) -#endif - -#if EV_USE_INOTIFY || EV_GENWRAP -VARx(int, fs_fd) -VARx(ev_io, fs_w) -VARx(char, fs_2625) /* whether we are running in linux 2.6.25 or newer */ -VAR (fs_hash, ANFS fs_hash [EV_INOTIFY_HASHSIZE]) -#endif - -VARx(EV_ATOMIC_T, sig_pending) -VARx(int, nosigmask) -#if EV_USE_SIGNALFD || EV_GENWRAP -VARx(int, sigfd) -VARx(ev_io, sigfd_w) -VARx(sigset_t, sigfd_set) -#endif - -VARx(unsigned int, origflags) /* original loop flags */ - -#if EV_FEATURE_API || EV_GENWRAP -VARx(unsigned int, loop_count) /* total number of loop iterations/blocks */ -VARx(unsigned int, loop_depth) /* #ev_run enters - #ev_run leaves */ - -VARx(void *, userdata) -VAR (release_cb, void (*release_cb)(EV_P)) -VAR (acquire_cb, void (*acquire_cb)(EV_P)) -VAR (invoke_cb , void (*invoke_cb) (EV_P)) -#endif - -#undef VARx - diff --git a/src/util/k5ev/ev_win32.c b/src/util/k5ev/ev_win32.c deleted file mode 100644 index 338886efe..000000000 --- a/src/util/k5ev/ev_win32.c +++ /dev/null @@ -1,153 +0,0 @@ -/* - * libev win32 compatibility cruft (_not_ a backend) - * - * Copyright (c) 2007,2008,2009 Marc Alexander Lehmann <libev@schmorp.de> - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modifica- - * tion, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER- - * CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO - * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE- - * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; - * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH- - * ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Alternatively, the contents of this file may be used under the terms of - * the GNU General Public License ("GPL") version 2 or any later version, - * in which case the provisions of the GPL are applicable instead of - * the above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the BSD license, indicate your decision - * by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file under - * either the BSD or the GPL. - */ - -#ifdef _WIN32 - -/* timeb.h is actually xsi legacy functionality */ -#include <sys/timeb.h> - -/* note: the comment below could not be substantiated, but what would I care */ -/* MSDN says this is required to handle SIGFPE */ -/* my wild guess would be that using something floating-pointy is required */ -/* for the crt to do something about it */ -volatile double SIGFPE_REQ = 0.0f; - -/* oh, the humanity! */ -static int -ev_pipe (int filedes [2]) -{ - struct sockaddr_in addr = { 0 }; - int addr_size = sizeof (addr); - struct sockaddr_in adr2; - int adr2_size = sizeof (adr2); - SOCKET listener; - SOCKET sock [2] = { -1, -1 }; - - if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) - return -1; - - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); - addr.sin_port = 0; - - if (bind (listener, (struct sockaddr *)&addr, addr_size)) - goto fail; - - if (getsockname (listener, (struct sockaddr *)&addr, &addr_size)) - goto fail; - - if (listen (listener, 1)) - goto fail; - - if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) - goto fail; - - if (connect (sock [0], (struct sockaddr *)&addr, addr_size)) - goto fail; - - if ((sock [1] = accept (listener, 0, 0)) < 0) - goto fail; - - /* windows vista returns fantasy port numbers for sockets: - * example for two interconnected tcp sockets: - * - * (Socket::unpack_sockaddr_in getsockname $sock0)[0] == 53364 - * (Socket::unpack_sockaddr_in getpeername $sock0)[0] == 53363 - * (Socket::unpack_sockaddr_in getsockname $sock1)[0] == 53363 - * (Socket::unpack_sockaddr_in getpeername $sock1)[0] == 53365 - * - * wow! tridirectional sockets! - * - * this way of checking ports seems to work: - */ - if (getpeername (sock [0], (struct sockaddr *)&addr, &addr_size)) - goto fail; - - if (getsockname (sock [1], (struct sockaddr *)&adr2, &adr2_size)) - goto fail; - - errno = WSAEINVAL; - if (addr_size != adr2_size - || addr.sin_addr.s_addr != adr2.sin_addr.s_addr /* just to be sure, I mean, it's windows */ - || addr.sin_port != adr2.sin_port) - goto fail; - - closesocket (listener); - -#if EV_SELECT_IS_WINSOCKET - filedes [0] = EV_WIN32_HANDLE_TO_FD (sock [0]); - filedes [1] = EV_WIN32_HANDLE_TO_FD (sock [1]); -#else - /* when select isn't winsocket, we also expect socket, connect, accept etc. - * to work on fds */ - filedes [0] = sock [0]; - filedes [1] = sock [1]; -#endif - - return 0; - -fail: - closesocket (listener); - - if (sock [0] != INVALID_SOCKET) closesocket (sock [0]); - if (sock [1] != INVALID_SOCKET) closesocket (sock [1]); - - return -1; -} - -#undef pipe -#define pipe(filedes) ev_pipe (filedes) - -#define EV_HAVE_EV_TIME 1 -ev_tstamp -ev_time (void) -{ - FILETIME ft; - ULARGE_INTEGER ui; - - GetSystemTimeAsFileTime (&ft); - ui.u.LowPart = ft.dwLowDateTime; - ui.u.HighPart = ft.dwHighDateTime; - - /* msvc cannot convert ulonglong to double... yes, it is that sucky */ - return (LONGLONG)(ui.QuadPart - 116444736000000000) * 1e-7; -} - -#endif - diff --git a/src/util/k5ev/ev_wrap.h b/src/util/k5ev/ev_wrap.h deleted file mode 100644 index 2c195c5db..000000000 --- a/src/util/k5ev/ev_wrap.h +++ /dev/null @@ -1,196 +0,0 @@ -/* DO NOT EDIT, automatically generated by update_ev_wrap */ -#ifndef EV_WRAP_H -#define EV_WRAP_H -#define now_floor ((loop)->now_floor) -#define mn_now ((loop)->mn_now) -#define rtmn_diff ((loop)->rtmn_diff) -#define io_blocktime ((loop)->io_blocktime) -#define timeout_blocktime ((loop)->timeout_blocktime) -#define backend ((loop)->backend) -#define activecnt ((loop)->activecnt) -#define loop_done ((loop)->loop_done) -#define backend_fd ((loop)->backend_fd) -#define backend_fudge ((loop)->backend_fudge) -#define backend_modify ((loop)->backend_modify) -#define backend_poll ((loop)->backend_poll) -#define anfds ((loop)->anfds) -#define anfdmax ((loop)->anfdmax) -#define pendings ((loop)->pendings) -#define pendingmax ((loop)->pendingmax) -#define pendingcnt ((loop)->pendingcnt) -#define pending_w ((loop)->pending_w) -#define rfeeds ((loop)->rfeeds) -#define rfeedmax ((loop)->rfeedmax) -#define rfeedcnt ((loop)->rfeedcnt) -#define evfd ((loop)->evfd) -#define evpipe ((loop)->evpipe) -#define pipe_w ((loop)->pipe_w) -#define curpid ((loop)->curpid) -#define postfork ((loop)->postfork) -#define vec_ri ((loop)->vec_ri) -#define vec_ro ((loop)->vec_ro) -#define vec_wi ((loop)->vec_wi) -#define vec_wo ((loop)->vec_wo) -#define vec_eo ((loop)->vec_eo) -#define vec_max ((loop)->vec_max) -#define polls ((loop)->polls) -#define pollmax ((loop)->pollmax) -#define pollcnt ((loop)->pollcnt) -#define pollidxs ((loop)->pollidxs) -#define pollidxmax ((loop)->pollidxmax) -#define epoll_events ((loop)->epoll_events) -#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_changemax ((loop)->kqueue_changemax) -#define kqueue_changecnt ((loop)->kqueue_changecnt) -#define kqueue_events ((loop)->kqueue_events) -#define kqueue_eventmax ((loop)->kqueue_eventmax) -#define port_events ((loop)->port_events) -#define port_eventmax ((loop)->port_eventmax) -#define iocp ((loop)->iocp) -#define fdchanges ((loop)->fdchanges) -#define fdchangemax ((loop)->fdchangemax) -#define fdchangecnt ((loop)->fdchangecnt) -#define timers ((loop)->timers) -#define timermax ((loop)->timermax) -#define timercnt ((loop)->timercnt) -#define periodics ((loop)->periodics) -#define periodicmax ((loop)->periodicmax) -#define periodiccnt ((loop)->periodiccnt) -#define idles ((loop)->idles) -#define idlemax ((loop)->idlemax) -#define idlecnt ((loop)->idlecnt) -#define idleall ((loop)->idleall) -#define prepares ((loop)->prepares) -#define preparemax ((loop)->preparemax) -#define preparecnt ((loop)->preparecnt) -#define checks ((loop)->checks) -#define checkmax ((loop)->checkmax) -#define checkcnt ((loop)->checkcnt) -#define forks ((loop)->forks) -#define forkmax ((loop)->forkmax) -#define forkcnt ((loop)->forkcnt) -#define cleanups ((loop)->cleanups) -#define cleanupmax ((loop)->cleanupmax) -#define cleanupcnt ((loop)->cleanupcnt) -#define async_pending ((loop)->async_pending) -#define asyncs ((loop)->asyncs) -#define asyncmax ((loop)->asyncmax) -#define asynccnt ((loop)->asynccnt) -#define fs_fd ((loop)->fs_fd) -#define fs_w ((loop)->fs_w) -#define fs_2625 ((loop)->fs_2625) -#define fs_hash ((loop)->fs_hash) -#define sig_pending ((loop)->sig_pending) -#define nosigmask ((loop)->nosigmask) -#define sigfd ((loop)->sigfd) -#define sigfd_w ((loop)->sigfd_w) -#define sigfd_set ((loop)->sigfd_set) -#define origflags ((loop)->origflags) -#define loop_count ((loop)->loop_count) -#define loop_depth ((loop)->loop_depth) -#define userdata ((loop)->userdata) -#define release_cb ((loop)->release_cb) -#define acquire_cb ((loop)->acquire_cb) -#define invoke_cb ((loop)->invoke_cb) -#else -#undef EV_WRAP_H -#undef now_floor -#undef mn_now -#undef rtmn_diff -#undef io_blocktime -#undef timeout_blocktime -#undef backend -#undef activecnt -#undef loop_done -#undef backend_fd -#undef backend_fudge -#undef backend_modify -#undef backend_poll -#undef anfds -#undef anfdmax -#undef pendings -#undef pendingmax -#undef pendingcnt -#undef pending_w -#undef rfeeds -#undef rfeedmax -#undef rfeedcnt -#undef evfd -#undef evpipe -#undef pipe_w -#undef curpid -#undef postfork -#undef vec_ri -#undef vec_ro -#undef vec_wi -#undef vec_wo -#undef vec_eo -#undef vec_max -#undef polls -#undef pollmax -#undef pollcnt -#undef pollidxs -#undef pollidxmax -#undef epoll_events -#undef epoll_eventmax -#undef epoll_eperms -#undef epoll_epermcnt -#undef epoll_epermmax -#undef kqueue_changes -#undef kqueue_changemax -#undef kqueue_changecnt -#undef kqueue_events -#undef kqueue_eventmax -#undef port_events -#undef port_eventmax -#undef iocp -#undef fdchanges -#undef fdchangemax -#undef fdchangecnt -#undef timers -#undef timermax -#undef timercnt -#undef periodics -#undef periodicmax -#undef periodiccnt -#undef idles -#undef idlemax -#undef idlecnt -#undef idleall -#undef prepares -#undef preparemax -#undef preparecnt -#undef checks -#undef checkmax -#undef checkcnt -#undef forks -#undef forkmax -#undef forkcnt -#undef cleanups -#undef cleanupmax -#undef cleanupcnt -#undef async_pending -#undef asyncs -#undef asyncmax -#undef asynccnt -#undef fs_fd -#undef fs_w -#undef fs_2625 -#undef fs_hash -#undef sig_pending -#undef nosigmask -#undef sigfd -#undef sigfd_w -#undef sigfd_set -#undef origflags -#undef loop_count -#undef loop_depth -#undef userdata -#undef release_cb -#undef acquire_cb -#undef invoke_cb -#endif diff --git a/src/util/k5ev/libverto-k5ev.exports b/src/util/k5ev/libverto-k5ev.exports deleted file mode 100644 index 7907fbef7..000000000 --- a/src/util/k5ev/libverto-k5ev.exports +++ /dev/null @@ -1,3 +0,0 @@ -verto_default_k5ev -verto_module_table_k5ev -verto_new_k5ev diff --git a/src/util/k5ev/verto-k5ev.c b/src/util/k5ev/verto-k5ev.c deleted file mode 100644 index 35c94d66e..000000000 --- a/src/util/k5ev/verto-k5ev.c +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2011 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * An edited version of verto-libev.c, using an embedded libev with renamed - * symbols. The corresponding version of verto-libev.c is stored in this - * directory for reference, although it is not built here. - */ - -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -#include "verto-k5ev.h" -#include <verto-module.h> -#include "rename.h" -#include "autoconf.h" -#define EV_STANDALONE 1 -/* Avoid using clock_gettime, which would create a dependency on librt. */ -#define EV_USE_MONOTONIC 0 -#define EV_USE_REALTIME 0 -#define EV_FEATURES 0x5f /* Everything but back ends */ -#ifdef HAVE_POLL_H -#define EV_USE_POLL 1 -#endif -/* ev.c explicitly disables poll() on Mac or FreeBSD; fall back to select(). */ -#define EV_USE_SELECT 1 -#include "ev.c" - -static verto_mod_ctx * -k5ev_ctx_new(void) -{ - return ev_loop_new(EVFLAG_AUTO); -} - -static verto_mod_ctx * -k5ev_ctx_default(void) -{ - return ev_default_loop(EVFLAG_AUTO); -} - -static void -k5ev_ctx_free(verto_mod_ctx *ctx) -{ - if (ctx != EV_DEFAULT) - ev_loop_destroy(ctx); -} - -static void -k5ev_ctx_run(verto_mod_ctx *ctx) -{ - ev_run(ctx, 0); -} - -static void -k5ev_ctx_run_once(verto_mod_ctx *ctx) -{ - ev_run(ctx, EVRUN_ONCE); -} - -static void -k5ev_ctx_break(verto_mod_ctx *ctx) -{ - ev_break(ctx, EVBREAK_ONE); -} - -static void -k5ev_ctx_reinitialize(verto_mod_ctx *ctx) -{ - ev_loop_fork(ctx); -} - -static void -libev_callback(EV_P_ ev_watcher *w, int revents) -{ - verto_ev_flag state = VERTO_EV_FLAG_NONE; - - if (verto_get_type(w->data)== VERTO_EV_TYPE_CHILD) - verto_set_proc_status(w->data, ((ev_child*) w)->rstatus); - - if (revents & EV_READ) - state |= VERTO_EV_FLAG_IO_READ; - if (revents & EV_WRITE) - state |= VERTO_EV_FLAG_IO_WRITE; - if (revents & EV_ERROR) - state |= VERTO_EV_FLAG_IO_ERROR; - - verto_set_fd_state(w->data, state); - verto_fire(w->data); -} - -static void -k5ev_ctx_set_flags(verto_mod_ctx *ctx, const verto_ev *ev, - verto_mod_ev *evpriv) -{ - if (verto_get_type(ev) == VERTO_EV_TYPE_IO) { - int events = EV_NONE; - - if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_READ) - events |= EV_READ; - if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_WRITE) - events |= EV_WRITE; - - ev_io_stop(ctx, (ev_io*) evpriv); - ev_io_set(((ev_io*) evpriv), verto_get_fd(ev), events); - ev_io_start(ctx, (ev_io*) evpriv); - } -} - -#define setuptype(type, ...) \ - w.type = malloc(sizeof(ev_ ## type)); \ - if (w.type) { \ - ev_ ## type ## _init(w.type, (EV_CB(type, (*))) __VA_ARGS__); \ - ev_ ## type ## _start(ctx, w.type); \ - } \ - break - -static verto_mod_ev * -k5ev_ctx_add(verto_mod_ctx *ctx, const verto_ev *ev, verto_ev_flag *flags) -{ - union { - ev_watcher *watcher; - ev_io *io; - ev_timer *timer; - ev_idle *idle; - ev_signal *signal; - ev_child *child; - } w; - ev_tstamp interval; - - w.watcher = NULL; - *flags |= VERTO_EV_FLAG_PERSIST; - switch (verto_get_type(ev)) { - case VERTO_EV_TYPE_IO: - setuptype(io, libev_callback, verto_get_fd(ev), EV_NONE); - case VERTO_EV_TYPE_TIMEOUT: - interval = ((ev_tstamp) verto_get_interval(ev)) / 1000.0; - setuptype(timer, libev_callback, interval, interval); - case VERTO_EV_TYPE_IDLE: - setuptype(idle, libev_callback); - case VERTO_EV_TYPE_SIGNAL: - setuptype(signal, libev_callback, verto_get_signal(ev)); - case VERTO_EV_TYPE_CHILD: - *flags &= ~VERTO_EV_FLAG_PERSIST; /* Child events don't persist */ - setuptype(child, libev_callback, verto_get_proc(ev), 0); - default: - break; /* Not supported */ - } - - if (w.watcher) { - w.watcher->data = (void*) ev; - k5ev_ctx_set_flags(ctx, ev, w.watcher); - } - return w.watcher; -} - -static void -k5ev_ctx_del(verto_mod_ctx *ctx, const verto_ev *ev, verto_mod_ev *evpriv) -{ - switch (verto_get_type(ev)) { - case VERTO_EV_TYPE_IO: - ev_io_stop(ctx, (ev_io*) evpriv); - break; - case VERTO_EV_TYPE_TIMEOUT: - ev_timer_stop(ctx, (ev_timer*) evpriv); - break; - case VERTO_EV_TYPE_IDLE: - ev_idle_stop(ctx, (ev_idle*) evpriv); - break; - case VERTO_EV_TYPE_SIGNAL: - ev_signal_stop(ctx, (ev_signal*) evpriv); - break; - case VERTO_EV_TYPE_CHILD: - ev_child_stop(ctx, (ev_child*) evpriv); - break; - default: - break; - } - - free(evpriv); -} - -VERTO_MODULE(k5ev, NULL, - VERTO_EV_TYPE_IO | - VERTO_EV_TYPE_TIMEOUT | - VERTO_EV_TYPE_IDLE | - VERTO_EV_TYPE_SIGNAL | - VERTO_EV_TYPE_CHILD); - -verto_ctx * -verto_convert_k5ev(struct ev_loop* loop) -{ - return verto_convert(k5ev, 0, loop); -} diff --git a/src/util/k5ev/verto-k5ev.h b/src/util/k5ev/verto-k5ev.h deleted file mode 100644 index 0b1ad192c..000000000 --- a/src/util/k5ev/verto-k5ev.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2011 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef VERTO_K5EV_H_ -#define VERTO_K5EV_H_ - -#include <verto.h> - -verto_ctx *verto_new_k5ev(void); -verto_ctx *verto_default_k5ev(void); - -#endif /* VERTO_K5EV_H_ */ diff --git a/src/util/k5ev/verto-libev.c b/src/util/k5ev/verto-libev.c deleted file mode 100644 index 9c7c32449..000000000 --- a/src/util/k5ev/verto-libev.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2011 Red Hat, Inc. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation files - * (the "Software"), to deal in the Software without restriction, - * including without limitation the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include <stdlib.h> -#include <string.h> -#include <errno.h> - -#include <verto-libev.h> -#define VERTO_MODULE_TYPES -typedef struct ev_loop verto_mod_ctx; -typedef ev_watcher verto_mod_ev; -#include <verto-module.h> - -static verto_mod_ctx * -libev_ctx_new(void) -{ - return ev_loop_new(EVFLAG_AUTO); -} - -static verto_mod_ctx * -libev_ctx_default(void) -{ - return ev_default_loop(EVFLAG_AUTO); -} - -static void -libev_ctx_free(verto_mod_ctx *ctx) -{ - if (ctx != EV_DEFAULT) - ev_loop_destroy(ctx); -} - -static void -libev_ctx_run(verto_mod_ctx *ctx) -{ - ev_run(ctx, 0); -} - -static void -libev_ctx_run_once(verto_mod_ctx *ctx) -{ - ev_run(ctx, EVRUN_ONCE); -} - -static void -libev_ctx_break(verto_mod_ctx *ctx) -{ - ev_break(ctx, EVBREAK_ONE); -} - -static void -libev_ctx_reinitialize(verto_mod_ctx *ctx) -{ - ev_loop_fork(ctx); -} - -static void -libev_callback(EV_P_ ev_watcher *w, int revents) -{ - verto_ev_flag state = VERTO_EV_FLAG_NONE; - - if (verto_get_type(w->data)== VERTO_EV_TYPE_CHILD) - verto_set_proc_status(w->data, ((ev_child*) w)->rstatus); - - if (revents & EV_READ) - state |= VERTO_EV_FLAG_IO_READ; - if (revents & EV_WRITE) - state |= VERTO_EV_FLAG_IO_WRITE; - if (revents & EV_ERROR) - state |= VERTO_EV_FLAG_IO_ERROR; - - verto_set_fd_state(w->data, state); - verto_fire(w->data); -} - -static void -libev_ctx_set_flags(verto_mod_ctx *ctx, const verto_ev *ev, - verto_mod_ev *evpriv) -{ - if (verto_get_type(ev) == VERTO_EV_TYPE_IO) { - int events = EV_NONE; - - if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_READ) - events |= EV_READ; - if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_WRITE) - events |= EV_WRITE; - - ev_io_stop(ctx, (ev_io*) evpriv); - ev_io_set(((ev_io*) evpriv), verto_get_fd(ev), events); - ev_io_start(ctx, (ev_io*) evpriv); - } -} - -#define setuptype(type, ...) \ - w.type = malloc(sizeof(ev_ ## type)); \ - if (w.type) { \ - ev_ ## type ## _init(w.type, (EV_CB(type, (*))) __VA_ARGS__); \ - ev_ ## type ## _start(ctx, w.type); \ - } \ - break - -static verto_mod_ev * -libev_ctx_add(verto_mod_ctx *ctx, const verto_ev *ev, verto_ev_flag *flags) -{ - union { - ev_watcher *watcher; - ev_io *io; - ev_timer *timer; - ev_idle *idle; - ev_signal *signal; - ev_child *child; - } w; - ev_tstamp interval; - - w.watcher = NULL; - *flags |= VERTO_EV_FLAG_PERSIST; - switch (verto_get_type(ev)) { - case VERTO_EV_TYPE_IO: - setuptype(io, libev_callback, verto_get_fd(ev), EV_NONE); - case VERTO_EV_TYPE_TIMEOUT: - interval = ((ev_tstamp) verto_get_interval(ev)) / 1000.0; - setuptype(timer, libev_callback, interval, interval); - case VERTO_EV_TYPE_IDLE: - setuptype(idle, libev_callback); - case VERTO_EV_TYPE_SIGNAL: - setuptype(signal, libev_callback, verto_get_signal(ev)); - case VERTO_EV_TYPE_CHILD: - *flags &= ~VERTO_EV_FLAG_PERSIST; /* Child events don't persist */ - setuptype(child, libev_callback, verto_get_proc(ev), 0); - default: - break; /* Not supported */ - } - - if (w.watcher) { - w.watcher->data = (void*) ev; - libev_ctx_set_flags(ctx, ev, w.watcher); - } - return w.watcher; -} - -static void -libev_ctx_del(verto_mod_ctx *ctx, const verto_ev *ev, verto_mod_ev *evpriv) -{ - switch (verto_get_type(ev)) { - case VERTO_EV_TYPE_IO: - ev_io_stop(ctx, (ev_io*) evpriv); - break; - case VERTO_EV_TYPE_TIMEOUT: - ev_timer_stop(ctx, (ev_timer*) evpriv); - break; - case VERTO_EV_TYPE_IDLE: - ev_idle_stop(ctx, (ev_idle*) evpriv); - break; - case VERTO_EV_TYPE_SIGNAL: - ev_signal_stop(ctx, (ev_signal*) evpriv); - break; - case VERTO_EV_TYPE_CHILD: - ev_child_stop(ctx, (ev_child*) evpriv); - break; - default: - break; - } - - free(evpriv); -} - -VERTO_MODULE(libev, ev_loop_new, - VERTO_EV_TYPE_IO | - VERTO_EV_TYPE_TIMEOUT | - VERTO_EV_TYPE_IDLE | - VERTO_EV_TYPE_SIGNAL | - VERTO_EV_TYPE_CHILD); - -verto_ctx * -verto_convert_libev(struct ev_loop* loop) -{ - return verto_convert(libev, 0, loop); -} |
