krb5 commit: Update libev sources to 4.22

Greg Hudson ghudson at mit.edu
Wed Aug 10 13:51:31 EDT 2016


https://github.com/krb5/krb5/commit/0038afaaa4d0a2b038276e9719244bda628d6f29
commit 0038afaaa4d0a2b038276e9719244bda628d6f29
Author: Greg Hudson <ghudson at mit.edu>
Date:   Mon Jun 27 13:13:47 2016 -0400

    Update libev sources to 4.22
    
    This update fixes a memory leak when freeing null pointers using
    ev_realloc_emul().  In 4.04, that function assumed that realloc(x, 0)
    is equivalent to free(x) under glibc, but in at least some versions of
    glibc, realloc(NULL, 0) behaves like malloc(0) rather than free(NULL)
    and allocates memory.
    
    ticket: 8436 (new)

 src/util/verto/ev.c         | 1788 +++++++++++++++++++++++++++++++++++--------
 src/util/verto/ev.h         |  245 ++++---
 src/util/verto/ev_poll.c    |    8 +-
 src/util/verto/ev_select.c  |   16 +-
 src/util/verto/ev_vars.h    |   39 +-
 src/util/verto/ev_win32.c   |   21 +-
 src/util/verto/ev_wrap.h    |  324 ++++----
 src/util/verto/verto-k5ev.c |    1 +
 8 files changed, 1835 insertions(+), 607 deletions(-)

diff --git a/src/util/verto/ev.c b/src/util/verto/ev.c
index 4187b18..cf55835 100644
--- a/src/util/verto/ev.c
+++ b/src/util/verto/ev.c
@@ -1,7 +1,7 @@
 /*
  * libev event processing core, watcher management
  *
- * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev at schmorp.de>
+ * Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann <libev at schmorp.de>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modifica-
@@ -45,6 +45,12 @@
 #  include "config.h"
 # endif
 
+# if HAVE_FLOOR
+#  ifndef EV_USE_FLOOR
+#   define EV_USE_FLOOR 1
+#  endif
+# endif
+
 # if HAVE_CLOCK_SYSCALL
 #  ifndef EV_USE_CLOCK_SYSCALL
 #   define EV_USE_CLOCK_SYSCALL 1
@@ -55,7 +61,7 @@
 #    define EV_USE_MONOTONIC 1
 #   endif
 #  endif
-# elif !defined(EV_USE_CLOCK_SYSCALL)
+# elif !defined EV_USE_CLOCK_SYSCALL
 #  define EV_USE_CLOCK_SYSCALL 0
 # endif
 
@@ -158,7 +164,6 @@
  
 #endif
 
-#include <math.h>
 #include <stdlib.h>
 #include <string.h>
 #include <fcntl.h>
@@ -180,7 +185,16 @@
 # include "ev.h"
 #endif
 
-EV_CPP(extern "C" {)
+#if EV_NO_THREADS
+# undef EV_NO_SMP
+# define EV_NO_SMP 1
+# undef ECB_NO_THREADS
+# define ECB_NO_THREADS 1
+#endif
+#if EV_NO_SMP
+# undef EV_NO_SMP
+# define ECB_NO_SMP 1
+#endif
 
 #ifndef _WIN32
 # include <sys/time.h>
@@ -189,6 +203,7 @@ EV_CPP(extern "C" {)
 #else
 # include <io.h>
 # define WIN32_LEAN_AND_MEAN
+# include <winsock2.h>
 # include <windows.h>
 # ifndef EV_SELECT_IS_WINSOCKET
 #  define EV_SELECT_IS_WINSOCKET 1
@@ -207,43 +222,53 @@ EV_CPP(extern "C" {)
 /* 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)
+#if defined EV_NSIG
 /* use what's provided */
-#elif defined (NSIG)
+#elif defined NSIG
 # define EV_NSIG (NSIG)
-#elif defined(_NSIG)
+#elif defined _NSIG
 # define EV_NSIG (_NSIG)
-#elif defined (SIGMAX)
+#elif defined SIGMAX
 # define EV_NSIG (SIGMAX+1)
-#elif defined (SIG_MAX)
+#elif defined SIG_MAX
 # define EV_NSIG (SIG_MAX+1)
-#elif defined (_SIG_MAX)
+#elif defined _SIG_MAX
 # define EV_NSIG (_SIG_MAX+1)
-#elif defined (MAXSIG)
+#elif defined MAXSIG
 # define EV_NSIG (MAXSIG+1)
-#elif defined (MAX_SIG)
+#elif defined MAX_SIG
 # define EV_NSIG (MAX_SIG+1)
-#elif defined (SIGARRAYSIZE)
+#elif defined SIGARRAYSIZE
 # define EV_NSIG (SIGARRAYSIZE) /* Assume ary[SIGARRAYSIZE] */
-#elif defined (_sys_nsig)
+#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
+# define EV_NSIG (8 * sizeof (sigset_t) + 1)
+#endif
+
+#ifndef EV_USE_FLOOR
+# define EV_USE_FLOOR 0
 #endif
 
 #ifndef EV_USE_CLOCK_SYSCALL
-# if __linux && __GLIBC__ >= 2
+# if __linux && __GLIBC__ == 2 && __GLIBC_MINOR__ < 17
 #  define EV_USE_CLOCK_SYSCALL EV_FEATURE_OS
 # else
 #  define EV_USE_CLOCK_SYSCALL 0
 # endif
 #endif
 
+#if !(_POSIX_TIMERS > 0)
+# ifndef EV_USE_MONOTONIC
+#  define EV_USE_MONOTONIC 0
+# endif
+# ifndef EV_USE_REALTIME
+#  define EV_USE_REALTIME 0
+# endif
+#endif
+
 #ifndef EV_USE_MONOTONIC
-# if defined (_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
+# if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
 #  define EV_USE_MONOTONIC EV_FEATURE_OS
 # else
 #  define EV_USE_MONOTONIC 0
@@ -340,10 +365,26 @@ EV_CPP(extern "C" {)
 # define EV_HEAP_CACHE_AT EV_FEATURE_DATA
 #endif
 
+#ifdef ANDROID
+/* supposedly, android doesn't typedef fd_mask */
+# undef EV_USE_SELECT
+# define EV_USE_SELECT 0
+/* supposedly, we need to include syscall.h, not sys/syscall.h, so just disable */
+# undef EV_USE_CLOCK_SYSCALL
+# define EV_USE_CLOCK_SYSCALL 0
+#endif
+
+/* aix's poll.h seems to cause lots of trouble */
+#ifdef _AIX
+/* AIX has a completely broken poll.h header */
+# undef EV_USE_POLL
+# define EV_USE_POLL 0
+#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>
+# include <sys/syscall.h>
 # ifdef SYS_clock_gettime
 #  define clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts))
 #  undef EV_USE_MONOTONIC
@@ -356,12 +397,6 @@ EV_CPP(extern "C" {)
 
 /* this block fixes any misconfiguration where we know we run into trouble otherwise */
 
-#ifdef _AIX
-/* AIX has a completely broken poll.h header */
-# undef EV_USE_POLL
-# define EV_USE_POLL 0
-#endif
-
 #ifndef CLOCK_MONOTONIC
 # undef EV_USE_MONOTONIC
 # define EV_USE_MONOTONIC 0
@@ -379,7 +414,7 @@ EV_CPP(extern "C" {)
 
 #if !EV_USE_NANOSLEEP
 /* hp-ux has it in sys/time.h, which we unconditionally include above */
-# if !defined(_WIN32) && !defined(__hpux)
+# if !defined _WIN32 && !defined __hpux
 #  include <sys/select.h>
 # endif
 #endif
@@ -394,10 +429,6 @@ EV_CPP(extern "C" {)
 # 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>
@@ -445,14 +476,11 @@ struct signalfd_siginfo
 #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 is used to work around floating point rounding problems.
  * This value is good at least till the year 4000.
- * Better solutions welcome.
  */
-#define TIME_EPSILON  0.0001220703125 /* 1/8192 */
+#define MIN_INTERVAL  0.0001220703125 /* 1/2**13, good till 4000 */
+/*#define MIN_INTERVAL  0.00000095367431640625 /* 1/2**20, good till 2200 */
 
 #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) */
@@ -460,23 +488,1046 @@ struct signalfd_siginfo
 #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))
+/* the following is ecb.h embedded into libev - use update_ev_c to update from an external copy */
+/* ECB.H BEGIN */
+/*
+ * libecb - http://software.schmorp.de/pkg/libecb
+ *
+ * Copyright (©) 2009-2015 Marc Alexander Lehmann <libecb at schmorp.de>
+ * Copyright (©) 2011 Emanuele Giaquinta
+ * 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 ECB_H
+#define ECB_H
+
+/* 16 bits major, 16 bits minor */
+#define ECB_VERSION 0x00010005
+
+#ifdef _WIN32
+  typedef   signed char   int8_t;
+  typedef unsigned char  uint8_t;
+  typedef   signed short  int16_t;
+  typedef unsigned short uint16_t;
+  typedef   signed int    int32_t;
+  typedef unsigned int   uint32_t;
+  #if __GNUC__
+    typedef   signed long long int64_t;
+    typedef unsigned long long uint64_t;
+  #else /* _MSC_VER || __BORLANDC__ */
+    typedef   signed __int64   int64_t;
+    typedef unsigned __int64   uint64_t;
+  #endif
+  #ifdef _WIN64
+    #define ECB_PTRSIZE 8
+    typedef uint64_t uintptr_t;
+    typedef  int64_t  intptr_t;
+  #else
+    #define ECB_PTRSIZE 4
+    typedef uint32_t uintptr_t;
+    typedef  int32_t  intptr_t;
+  #endif
 #else
-# define expect(expr,value)         (expr)
-# define noinline
-# if __STDC_VERSION__ < 199901L && __GNUC__ < 2
-#  define inline
-# endif
+  #include <inttypes.h>
+  #if (defined INTPTR_MAX ? INTPTR_MAX : ULONG_MAX) > 0xffffffffU
+    #define ECB_PTRSIZE 8
+  #else
+    #define ECB_PTRSIZE 4
+  #endif
+#endif
+
+#define ECB_GCC_AMD64 (__amd64 || __amd64__ || __x86_64 || __x86_64__)
+#define ECB_MSVC_AMD64 (_M_AMD64 || _M_X64)
+
+/* work around x32 idiocy by defining proper macros */
+#if ECB_GCC_AMD64 || ECB_MSVC_AMD64
+  #if _ILP32
+    #define ECB_AMD64_X32 1
+  #else
+    #define ECB_AMD64 1
+  #endif
+#endif
+
+/* many compilers define _GNUC_ to some versions but then only implement
+ * what their idiot authors think are the "more important" extensions,
+ * causing enormous grief in return for some better fake benchmark numbers.
+ * or so.
+ * we try to detect these and simply assume they are not gcc - if they have
+ * an issue with that they should have done it right in the first place.
+ */
+#if !defined __GNUC_MINOR__ || defined __INTEL_COMPILER || defined __SUNPRO_C || defined __SUNPRO_CC || defined __llvm__ || defined __clang__
+  #define ECB_GCC_VERSION(major,minor) 0
+#else
+  #define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
+#endif
+
+#define ECB_CLANG_VERSION(major,minor) (__clang_major__ > (major) || (__clang_major__ == (major) && __clang_minor__ >= (minor)))
+
+#if __clang__ && defined __has_builtin
+  #define ECB_CLANG_BUILTIN(x) __has_builtin (x)
+#else
+  #define ECB_CLANG_BUILTIN(x) 0
+#endif
+
+#if __clang__ && defined __has_extension
+  #define ECB_CLANG_EXTENSION(x) __has_extension (x)
+#else
+  #define ECB_CLANG_EXTENSION(x) 0
+#endif
+
+#define ECB_CPP   (__cplusplus+0)
+#define ECB_CPP11 (__cplusplus >= 201103L)
+
+#if ECB_CPP
+  #define ECB_C            0
+  #define ECB_STDC_VERSION 0
+#else
+  #define ECB_C            1
+  #define ECB_STDC_VERSION __STDC_VERSION__
+#endif
+
+#define ECB_C99   (ECB_STDC_VERSION >= 199901L)
+#define ECB_C11   (ECB_STDC_VERSION >= 201112L)
+
+#if ECB_CPP
+  #define ECB_EXTERN_C extern "C"
+  #define ECB_EXTERN_C_BEG ECB_EXTERN_C {
+  #define ECB_EXTERN_C_END }
+#else
+  #define ECB_EXTERN_C extern
+  #define ECB_EXTERN_C_BEG
+  #define ECB_EXTERN_C_END
+#endif
+
+/*****************************************************************************/
+
+/* ECB_NO_THREADS - ecb is not used by multiple threads, ever */
+/* ECB_NO_SMP     - ecb might be used in multiple threads, but only on a single cpu */
+
+#if ECB_NO_THREADS
+  #define ECB_NO_SMP 1
+#endif
+
+#if ECB_NO_SMP
+  #define ECB_MEMORY_FENCE do { } while (0)
+#endif
+
+/* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/compiler_ref/compiler_builtins.html */
+#if __xlC__ && ECB_CPP
+  #include <builtins.h>
+#endif
+
+#if 1400 <= _MSC_VER
+  #include <intrin.h> /* fence functions _ReadBarrier, also bit search functions _BitScanReverse */
+#endif
+
+#ifndef ECB_MEMORY_FENCE
+  #if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
+    #if __i386 || __i386__
+      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory")
+      #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ (""                        : : : "memory")
+      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
+    #elif ECB_GCC_AMD64
+      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("mfence"   : : : "memory")
+      #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ (""         : : : "memory")
+      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
+    #elif __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__
+      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("sync"     : : : "memory")
+    #elif defined __ARM_ARCH_2__ \
+      || defined __ARM_ARCH_3__  || defined __ARM_ARCH_3M__  \
+      || defined __ARM_ARCH_4__  || defined __ARM_ARCH_4T__  \
+      || defined __ARM_ARCH_5__  || defined __ARM_ARCH_5E__  \
+      || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__ \
+      || defined __ARM_ARCH_5TEJ__
+      /* should not need any, unless running old code on newer cpu - arm doesn't support that */
+    #elif defined __ARM_ARCH_6__  || defined __ARM_ARCH_6J__  \
+       || defined __ARM_ARCH_6K__ || defined __ARM_ARCH_6ZK__ \
+       || defined __ARM_ARCH_6T2__
+      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("mcr p15,0,%0,c7,c10,5" : : "r" (0) : "memory")
+    #elif defined __ARM_ARCH_7__  || defined __ARM_ARCH_7A__  \
+       || defined __ARM_ARCH_7R__ || defined __ARM_ARCH_7M__
+      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("dmb"      : : : "memory")
+    #elif __aarch64__
+      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("dmb ish"  : : : "memory")
+    #elif (__sparc || __sparc__) && !(__sparc_v8__ || defined __sparcv8)
+      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("membar #LoadStore | #LoadLoad | #StoreStore | #StoreLoad" : : : "memory")
+      #define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad"                            : : : "memory")
+      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("membar #LoadStore             | #StoreStore")
+    #elif defined __s390__ || defined __s390x__
+      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("bcr 15,0" : : : "memory")
+    #elif defined __mips__
+      /* GNU/Linux emulates sync on mips1 architectures, so we force its use */
+      /* anybody else who still uses mips1 is supposed to send in their version, with detection code. */
+      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (".set mips2; sync; .set mips0" : : : "memory")
+    #elif defined __alpha__
+      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("mb"       : : : "memory")
+    #elif defined __hppa__
+      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (""         : : : "memory")
+      #define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("")
+    #elif defined __ia64__
+      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("mf"       : : : "memory")
+    #elif defined __m68k__
+      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (""         : : : "memory")
+    #elif defined __m88k__
+      #define ECB_MEMORY_FENCE         __asm__ __volatile__ ("tb1 0,%%r0,128" : : : "memory")
+    #elif defined __sh__
+      #define ECB_MEMORY_FENCE         __asm__ __volatile__ (""         : : : "memory")
+    #endif
+  #endif
+#endif
+
+#ifndef ECB_MEMORY_FENCE
+  #if ECB_GCC_VERSION(4,7)
+    /* see comment below (stdatomic.h) about the C11 memory model. */
+    #define ECB_MEMORY_FENCE         __atomic_thread_fence (__ATOMIC_SEQ_CST)
+    #define ECB_MEMORY_FENCE_ACQUIRE __atomic_thread_fence (__ATOMIC_ACQUIRE)
+    #define ECB_MEMORY_FENCE_RELEASE __atomic_thread_fence (__ATOMIC_RELEASE)
+
+  #elif ECB_CLANG_EXTENSION(c_atomic)
+    /* see comment below (stdatomic.h) about the C11 memory model. */
+    #define ECB_MEMORY_FENCE         __c11_atomic_thread_fence (__ATOMIC_SEQ_CST)
+    #define ECB_MEMORY_FENCE_ACQUIRE __c11_atomic_thread_fence (__ATOMIC_ACQUIRE)
+    #define ECB_MEMORY_FENCE_RELEASE __c11_atomic_thread_fence (__ATOMIC_RELEASE)
+
+  #elif ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__
+    #define ECB_MEMORY_FENCE         __sync_synchronize ()
+  #elif _MSC_VER >= 1500 /* VC++ 2008 */
+    /* apparently, microsoft broke all the memory barrier stuff in Visual Studio 2008... */
+    #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)
+    #define ECB_MEMORY_FENCE         _ReadWriteBarrier (); MemoryBarrier()
+    #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier (); MemoryBarrier() /* according to msdn, _ReadBarrier is not a load fence */
+    #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier (); MemoryBarrier()
+  #elif _MSC_VER >= 1400 /* VC++ 2005 */
+    #pragma intrinsic(_ReadBarrier,_WriteBarrier,_ReadWriteBarrier)
+    #define ECB_MEMORY_FENCE         _ReadWriteBarrier ()
+    #define ECB_MEMORY_FENCE_ACQUIRE _ReadWriteBarrier () /* according to msdn, _ReadBarrier is not a load fence */
+    #define ECB_MEMORY_FENCE_RELEASE _WriteBarrier ()
+  #elif defined _WIN32
+    #include <WinNT.h>
+    #define ECB_MEMORY_FENCE         MemoryBarrier () /* actually just xchg on x86... scary */
+  #elif __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
+    #include <mbarrier.h>
+    #define ECB_MEMORY_FENCE         __machine_rw_barrier ()
+    #define ECB_MEMORY_FENCE_ACQUIRE __machine_r_barrier  ()
+    #define ECB_MEMORY_FENCE_RELEASE __machine_w_barrier  ()
+  #elif __xlC__
+    #define ECB_MEMORY_FENCE         __sync ()
+  #endif
+#endif
+
+#ifndef ECB_MEMORY_FENCE
+  #if ECB_C11 && !defined __STDC_NO_ATOMICS__
+    /* we assume that these memory fences work on all variables/all memory accesses, */
+    /* not just C11 atomics and atomic accesses */
+    #include <stdatomic.h>
+    /* Unfortunately, neither gcc 4.7 nor clang 3.1 generate any instructions for */
+    /* any fence other than seq_cst, which isn't very efficient for us. */
+    /* Why that is, we don't know - either the C11 memory model is quite useless */
+    /* for most usages, or gcc and clang have a bug */
+    /* I *currently* lean towards the latter, and inefficiently implement */
+    /* all three of ecb's fences as a seq_cst fence */
+    /* Update, gcc-4.8 generates mfence for all c++ fences, but nothing */
+    /* for all __atomic_thread_fence's except seq_cst */
+    #define ECB_MEMORY_FENCE         atomic_thread_fence (memory_order_seq_cst)
+  #endif
+#endif
+
+#ifndef ECB_MEMORY_FENCE
+  #if !ECB_AVOID_PTHREADS
+    /*
+     * if you get undefined symbol references to pthread_mutex_lock,
+     * or failure to find pthread.h, then you should implement
+     * the ECB_MEMORY_FENCE operations for your cpu/compiler
+     * OR provide pthread.h and link against the posix thread library
+     * of your system.
+     */
+    #include <pthread.h>
+    #define ECB_NEEDS_PTHREADS 1
+    #define ECB_MEMORY_FENCE_NEEDS_PTHREADS 1
+
+    static pthread_mutex_t ecb_mf_lock = PTHREAD_MUTEX_INITIALIZER;
+    #define ECB_MEMORY_FENCE do { pthread_mutex_lock (&ecb_mf_lock); pthread_mutex_unlock (&ecb_mf_lock); } while (0)
+  #endif
+#endif
+
+#if !defined ECB_MEMORY_FENCE_ACQUIRE && defined ECB_MEMORY_FENCE
+  #define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE
+#endif
+
+#if !defined ECB_MEMORY_FENCE_RELEASE && defined ECB_MEMORY_FENCE
+  #define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
+#endif
+
+/*****************************************************************************/
+
+#if ECB_CPP
+  #define ecb_inline static inline
+#elif ECB_GCC_VERSION(2,5)
+  #define ecb_inline static __inline__
+#elif ECB_C99
+  #define ecb_inline static inline
+#else
+  #define ecb_inline static
+#endif
+
+#if ECB_GCC_VERSION(3,3)
+  #define ecb_restrict __restrict__
+#elif ECB_C99
+  #define ecb_restrict restrict
+#else
+  #define ecb_restrict
+#endif
+
+typedef int ecb_bool;
+
+#define ECB_CONCAT_(a, b) a ## b
+#define ECB_CONCAT(a, b) ECB_CONCAT_(a, b)
+#define ECB_STRINGIFY_(a) # a
+#define ECB_STRINGIFY(a) ECB_STRINGIFY_(a)
+#define ECB_STRINGIFY_EXPR(expr) ((expr), ECB_STRINGIFY_ (expr))
+
+#define ecb_function_ ecb_inline
+
+#if ECB_GCC_VERSION(3,1) || ECB_CLANG_VERSION(2,8)
+  #define ecb_attribute(attrlist)        __attribute__ (attrlist)
+#else
+  #define ecb_attribute(attrlist)
+#endif
+
+#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_constant_p)
+  #define ecb_is_constant(expr)          __builtin_constant_p (expr)
+#else
+  /* possible C11 impl for integral types
+  typedef struct ecb_is_constant_struct ecb_is_constant_struct;
+  #define ecb_is_constant(expr)          _Generic ((1 ? (struct ecb_is_constant_struct *)0 : (void *)((expr) - (expr)), ecb_is_constant_struct *: 0, default: 1)) */
+
+  #define ecb_is_constant(expr)          0
+#endif
+
+#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_expect)
+  #define ecb_expect(expr,value)         __builtin_expect ((expr),(value))
+#else
+  #define ecb_expect(expr,value)         (expr)
+#endif
+
+#if ECB_GCC_VERSION(3,1) || ECB_CLANG_BUILTIN(__builtin_prefetch)
+  #define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality)
+#else
+  #define ecb_prefetch(addr,rw,locality)
+#endif
+
+/* no emulation for ecb_decltype */
+#if ECB_CPP11
+  // older implementations might have problems with decltype(x)::type, work around it
+  template<class T> struct ecb_decltype_t { typedef T type; };
+  #define ecb_decltype(x) ecb_decltype_t<decltype (x)>::type
+#elif ECB_GCC_VERSION(3,0) || ECB_CLANG_VERSION(2,8)
+  #define ecb_decltype(x) __typeof__ (x)
+#endif
+
+#if _MSC_VER >= 1300
+  #define ecb_deprecated __declspec (deprecated)
+#else
+  #define ecb_deprecated ecb_attribute ((__deprecated__))
+#endif
+
+#if _MSC_VER >= 1500
+  #define ecb_deprecated_message(msg) __declspec (deprecated (msg))
+#elif ECB_GCC_VERSION(4,5)
+  #define ecb_deprecated_message(msg) ecb_attribute ((__deprecated__ (msg))
+#else
+  #define ecb_deprecated_message(msg) ecb_deprecated
+#endif
+
+#if _MSC_VER >= 1400
+  #define ecb_noinline __declspec (noinline)
+#else
+  #define ecb_noinline ecb_attribute ((__noinline__))
+#endif
+
+#define ecb_unused     ecb_attribute ((__unused__))
+#define ecb_const      ecb_attribute ((__const__))
+#define ecb_pure       ecb_attribute ((__pure__))
+
+#if ECB_C11 || __IBMC_NORETURN
+  /* http://www-01.ibm.com/support/knowledgecenter/SSGH3R_13.1.0/com.ibm.xlcpp131.aix.doc/language_ref/noreturn.html */
+  #define ecb_noreturn   _Noreturn
+#elif ECB_CPP11
+  #define ecb_noreturn   [[noreturn]]
+#elif _MSC_VER >= 1200
+  /* http://msdn.microsoft.com/en-us/library/k6ktzx3s.aspx */
+  #define ecb_noreturn   __declspec (noreturn)
+#else
+  #define ecb_noreturn   ecb_attribute ((__noreturn__))
 #endif
 
-#define expect_false(expr) expect ((expr) != 0, 0)
-#define expect_true(expr)  expect ((expr) != 0, 1)
-#define inline_size        static inline
+#if ECB_GCC_VERSION(4,3)
+  #define ecb_artificial ecb_attribute ((__artificial__))
+  #define ecb_hot        ecb_attribute ((__hot__))
+  #define ecb_cold       ecb_attribute ((__cold__))
+#else
+  #define ecb_artificial
+  #define ecb_hot
+  #define ecb_cold
+#endif
+
+/* put around conditional expressions if you are very sure that the  */
+/* expression is mostly true or mostly false. note that these return */
+/* booleans, not the expression.                                     */
+#define ecb_expect_false(expr) ecb_expect (!!(expr), 0)
+#define ecb_expect_true(expr)  ecb_expect (!!(expr), 1)
+/* for compatibility to the rest of the world */
+#define ecb_likely(expr)   ecb_expect_true  (expr)
+#define ecb_unlikely(expr) ecb_expect_false (expr)
+
+/* count trailing zero bits and count # of one bits */
+#if ECB_GCC_VERSION(3,4) \
+    || (ECB_CLANG_BUILTIN(__builtin_clz) && ECB_CLANG_BUILTIN(__builtin_clzll) \
+        && ECB_CLANG_BUILTIN(__builtin_ctz) && ECB_CLANG_BUILTIN(__builtin_ctzll) \
+        && ECB_CLANG_BUILTIN(__builtin_popcount))
+  /* we assume int == 32 bit, long == 32 or 64 bit and long long == 64 bit */
+  #define ecb_ld32(x)      (__builtin_clz      (x) ^ 31)
+  #define ecb_ld64(x)      (__builtin_clzll    (x) ^ 63)
+  #define ecb_ctz32(x)      __builtin_ctz      (x)
+  #define ecb_ctz64(x)      __builtin_ctzll    (x)
+  #define ecb_popcount32(x) __builtin_popcount (x)
+  /* no popcountll */
+#else
+  ecb_function_ ecb_const int ecb_ctz32 (uint32_t x);
+  ecb_function_ ecb_const int
+  ecb_ctz32 (uint32_t x)
+  {
+#if 1400 <= _MSC_VER && (_M_IX86 || _M_X64 || _M_IA64 || _M_ARM)
+    unsigned long r;
+    _BitScanForward (&r, x);
+    return (int)r;
+#else
+    int r = 0;
+
+    x &= ~x + 1; /* this isolates the lowest bit */
+
+#if ECB_branchless_on_i386
+    r += !!(x & 0xaaaaaaaa) << 0;
+    r += !!(x & 0xcccccccc) << 1;
+    r += !!(x & 0xf0f0f0f0) << 2;
+    r += !!(x & 0xff00ff00) << 3;
+    r += !!(x & 0xffff0000) << 4;
+#else
+    if (x & 0xaaaaaaaa) r +=  1;
+    if (x & 0xcccccccc) r +=  2;
+    if (x & 0xf0f0f0f0) r +=  4;
+    if (x & 0xff00ff00) r +=  8;
+    if (x & 0xffff0000) r += 16;
+#endif
+
+    return r;
+#endif
+  }
+
+  ecb_function_ ecb_const int ecb_ctz64 (uint64_t x);
+  ecb_function_ ecb_const int
+  ecb_ctz64 (uint64_t x)
+  {
+#if 1400 <= _MSC_VER && (_M_X64 || _M_IA64 || _M_ARM)
+    unsigned long r;
+    _BitScanForward64 (&r, x);
+    return (int)r;
+#else
+    int shift = x & 0xffffffff ? 0 : 32;
+    return ecb_ctz32 (x >> shift) + shift;
+#endif
+  }
+
+  ecb_function_ ecb_const int ecb_popcount32 (uint32_t x);
+  ecb_function_ ecb_const int
+  ecb_popcount32 (uint32_t x)
+  {
+    x -=  (x >> 1) & 0x55555555;
+    x  = ((x >> 2) & 0x33333333) + (x & 0x33333333);
+    x  = ((x >> 4) + x) & 0x0f0f0f0f;
+    x *= 0x01010101;
+
+    return x >> 24;
+  }
+
+  ecb_function_ ecb_const int ecb_ld32 (uint32_t x);
+  ecb_function_ ecb_const int ecb_ld32 (uint32_t x)
+  {
+#if 1400 <= _MSC_VER && (_M_IX86 || _M_X64 || _M_IA64 || _M_ARM)
+    unsigned long r;
+    _BitScanReverse (&r, x);
+    return (int)r;
+#else
+    int r = 0;
+
+    if (x >> 16) { x >>= 16; r += 16; }
+    if (x >>  8) { x >>=  8; r +=  8; }
+    if (x >>  4) { x >>=  4; r +=  4; }
+    if (x >>  2) { x >>=  2; r +=  2; }
+    if (x >>  1) {           r +=  1; }
+
+    return r;
+#endif
+  }
+
+  ecb_function_ ecb_const int ecb_ld64 (uint64_t x);
+  ecb_function_ ecb_const int ecb_ld64 (uint64_t x)
+  {
+#if 1400 <= _MSC_VER && (_M_X64 || _M_IA64 || _M_ARM)
+    unsigned long r;
+    _BitScanReverse64 (&r, x);
+    return (int)r;
+#else
+    int r = 0;
+
+    if (x >> 32) { x >>= 32; r += 32; }
+
+    return r + ecb_ld32 (x);
+#endif
+  }
+#endif
+
+ecb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x);
+ecb_function_ ecb_const ecb_bool ecb_is_pot32 (uint32_t x) { return !(x & (x - 1)); }
+ecb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x);
+ecb_function_ ecb_const ecb_bool ecb_is_pot64 (uint64_t x) { return !(x & (x - 1)); }
+
+ecb_function_ ecb_const uint8_t  ecb_bitrev8  (uint8_t  x);
+ecb_function_ ecb_const uint8_t  ecb_bitrev8  (uint8_t  x)
+{
+  return (  (x * 0x0802U & 0x22110U)
+          | (x * 0x8020U & 0x88440U)) * 0x10101U >> 16;
+}
+
+ecb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x);
+ecb_function_ ecb_const uint16_t ecb_bitrev16 (uint16_t x)
+{
+  x = ((x >>  1) &     0x5555) | ((x &     0x5555) <<  1);
+  x = ((x >>  2) &     0x3333) | ((x &     0x3333) <<  2);
+  x = ((x >>  4) &     0x0f0f) | ((x &     0x0f0f) <<  4);
+  x = ( x >>  8              ) | ( x               <<  8);
+
+  return x;
+}
+
+ecb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x);
+ecb_function_ ecb_const uint32_t ecb_bitrev32 (uint32_t x)
+{
+  x = ((x >>  1) & 0x55555555) | ((x & 0x55555555) <<  1);
+  x = ((x >>  2) & 0x33333333) | ((x & 0x33333333) <<  2);
+  x = ((x >>  4) & 0x0f0f0f0f) | ((x & 0x0f0f0f0f) <<  4);
+  x = ((x >>  8) & 0x00ff00ff) | ((x & 0x00ff00ff) <<  8);
+  x = ( x >> 16              ) | ( x               << 16);
+
+  return x;
+}
+
+/* popcount64 is only available on 64 bit cpus as gcc builtin */
+/* so for this version we are lazy */
+ecb_function_ ecb_const int ecb_popcount64 (uint64_t x);
+ecb_function_ ecb_const int
+ecb_popcount64 (uint64_t x)
+{
+  return ecb_popcount32 (x) + ecb_popcount32 (x >> 32);
+}
+
+ecb_inline ecb_const uint8_t  ecb_rotl8  (uint8_t  x, unsigned int count);
+ecb_inline ecb_const uint8_t  ecb_rotr8  (uint8_t  x, unsigned int count);
+ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count);
+ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count);
+ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count);
+ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count);
+ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count);
+ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count);
+
+ecb_inline ecb_const uint8_t  ecb_rotl8  (uint8_t  x, unsigned int count) { return (x >> ( 8 - count)) | (x << count); }
+ecb_inline ecb_const uint8_t  ecb_rotr8  (uint8_t  x, unsigned int count) { return (x << ( 8 - count)) | (x >> count); }
+ecb_inline ecb_const uint16_t ecb_rotl16 (uint16_t x, unsigned int count) { return (x >> (16 - count)) | (x << count); }
+ecb_inline ecb_const uint16_t ecb_rotr16 (uint16_t x, unsigned int count) { return (x << (16 - count)) | (x >> count); }
+ecb_inline ecb_const uint32_t ecb_rotl32 (uint32_t x, unsigned int count) { return (x >> (32 - count)) | (x << count); }
+ecb_inline ecb_const uint32_t ecb_rotr32 (uint32_t x, unsigned int count) { return (x << (32 - count)) | (x >> count); }
+ecb_inline ecb_const uint64_t ecb_rotl64 (uint64_t x, unsigned int count) { return (x >> (64 - count)) | (x << count); }
+ecb_inline ecb_const uint64_t ecb_rotr64 (uint64_t x, unsigned int count) { return (x << (64 - count)) | (x >> count); }
+
+#if ECB_GCC_VERSION(4,3) || (ECB_CLANG_BUILTIN(__builtin_bswap32) && ECB_CLANG_BUILTIN(__builtin_bswap64))
+  #if ECB_GCC_VERSION(4,8) || ECB_CLANG_BUILTIN(__builtin_bswap16)
+  #define ecb_bswap16(x)  __builtin_bswap16 (x)
+  #else
+  #define ecb_bswap16(x) (__builtin_bswap32 (x) >> 16)
+  #endif
+  #define ecb_bswap32(x)  __builtin_bswap32 (x)
+  #define ecb_bswap64(x)  __builtin_bswap64 (x)
+#elif _MSC_VER
+  #include <stdlib.h>
+  #define ecb_bswap16(x) ((uint16_t)_byteswap_ushort ((uint16_t)(x)))
+  #define ecb_bswap32(x) ((uint32_t)_byteswap_ulong  ((uint32_t)(x)))
+  #define ecb_bswap64(x) ((uint64_t)_byteswap_uint64 ((uint64_t)(x)))
+#else
+  ecb_function_ ecb_const uint16_t ecb_bswap16 (uint16_t x);
+  ecb_function_ ecb_const uint16_t
+  ecb_bswap16 (uint16_t x)
+  {
+    return ecb_rotl16 (x, 8);
+  }
+
+  ecb_function_ ecb_const uint32_t ecb_bswap32 (uint32_t x);
+  ecb_function_ ecb_const uint32_t
+  ecb_bswap32 (uint32_t x)
+  {
+    return (((uint32_t)ecb_bswap16 (x)) << 16) | ecb_bswap16 (x >> 16);
+  }
+
+  ecb_function_ ecb_const uint64_t ecb_bswap64 (uint64_t x);
+  ecb_function_ ecb_const uint64_t
+  ecb_bswap64 (uint64_t x)
+  {
+    return (((uint64_t)ecb_bswap32 (x)) << 32) | ecb_bswap32 (x >> 32);
+  }
+#endif
+
+#if ECB_GCC_VERSION(4,5) || ECB_CLANG_BUILTIN(__builtin_unreachable)
+  #define ecb_unreachable() __builtin_unreachable ()
+#else
+  /* this seems to work fine, but gcc always emits a warning for it :/ */
+  ecb_inline ecb_noreturn void ecb_unreachable (void);
+  ecb_inline ecb_noreturn void ecb_unreachable (void) { }
+#endif
+
+/* try to tell the compiler that some condition is definitely true */
+#define ecb_assume(cond) if (!(cond)) ecb_unreachable (); else 0
+
+ecb_inline ecb_const uint32_t ecb_byteorder_helper (void);
+ecb_inline ecb_const uint32_t
+ecb_byteorder_helper (void)
+{
+  /* the union code still generates code under pressure in gcc, */
+  /* but less than using pointers, and always seems to */
+  /* successfully return a constant. */
+  /* the reason why we have this horrible preprocessor mess */
+  /* is to avoid it in all cases, at least on common architectures */
+  /* or when using a recent enough gcc version (>= 4.6) */
+#if (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \
+    || ((__i386 || __i386__ || _M_IX86 || ECB_GCC_AMD64 || ECB_MSVC_AMD64) && !__VOS__)
+  #define ECB_LITTLE_ENDIAN 1
+  return 0x44332211;
+#elif (defined __BYTE_ORDER__ && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) \
+      || ((__AARCH64EB__ || __MIPSEB__ || __ARMEB__) && !__VOS__)
+  #define ECB_BIG_ENDIAN 1
+  return 0x11223344;
+#else
+  union
+  {
+    uint8_t c[4];
+    uint32_t u;
+  } u = { 0x11, 0x22, 0x33, 0x44 };
+  return u.u;
+#endif
+}
+
+ecb_inline ecb_const ecb_bool ecb_big_endian    (void);
+ecb_inline ecb_const ecb_bool ecb_big_endian    (void) { return ecb_byteorder_helper () == 0x11223344; }
+ecb_inline ecb_const ecb_bool ecb_little_endian (void);
+ecb_inline ecb_const ecb_bool ecb_little_endian (void) { return ecb_byteorder_helper () == 0x44332211; }
+
+#if ECB_GCC_VERSION(3,0) || ECB_C99
+  #define ecb_mod(m,n) ((m) % (n) + ((m) % (n) < 0 ? (n) : 0))
+#else
+  #define ecb_mod(m,n) ((m) < 0 ? ((n) - 1 - ((-1 - (m)) % (n))) : ((m) % (n)))
+#endif
+
+#if ECB_CPP
+  template<typename T>
+  static inline T ecb_div_rd (T val, T div)
+  {
+    return val < 0 ? - ((-val + div - 1) / div) : (val          ) / div;
+  }
+  template<typename T>
+  static inline T ecb_div_ru (T val, T div)
+  {
+    return val < 0 ? - ((-val          ) / div) : (val + div - 1) / div;
+  }
+#else
+  #define ecb_div_rd(val,div) ((val) < 0 ? - ((-(val) + (div) - 1) / (div)) : ((val)            ) / (div))
+  #define ecb_div_ru(val,div) ((val) < 0 ? - ((-(val)            ) / (div)) : ((val) + (div) - 1) / (div))
+#endif
+
+#if ecb_cplusplus_does_not_suck
+  /* does not work for local types (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm) */
+  template<typename T, int N>
+  static inline int ecb_array_length (const T (&arr)[N])
+  {
+    return N;
+  }
+#else
+  #define ecb_array_length(name) (sizeof (name) / sizeof (name [0]))
+#endif
+
+ecb_function_ ecb_const uint32_t ecb_binary16_to_binary32 (uint32_t x);
+ecb_function_ ecb_const uint32_t
+ecb_binary16_to_binary32 (uint32_t x)
+{
+  unsigned int s = (x & 0x8000) << (31 - 15);
+  int          e = (x >> 10) & 0x001f;
+  unsigned int m =  x        & 0x03ff;
+
+  if (ecb_expect_false (e == 31))
+    /* infinity or NaN */
+    e = 255 - (127 - 15);
+  else if (ecb_expect_false (!e))
+    {
+      if (ecb_expect_true (!m))
+        /* zero, handled by code below by forcing e to 0 */
+        e = 0 - (127 - 15);
+      else
+        {
+          /* subnormal, renormalise */
+          unsigned int s = 10 - ecb_ld32 (m);
+
+          m = (m << s) & 0x3ff; /* mask implicit bit */
+          e -= s - 1;
+        }
+    }
+
+  /* e and m now are normalised, or zero, (or inf or nan) */
+  e += 127 - 15;
+
+  return s | (e << 23) | (m << (23 - 10));
+}
+
+ecb_function_ ecb_const uint16_t ecb_binary32_to_binary16 (uint32_t x);
+ecb_function_ ecb_const uint16_t
+ecb_binary32_to_binary16 (uint32_t x)
+{
+  unsigned int s =  (x >> 16) & 0x00008000; /* sign bit, the easy part */
+  unsigned int e = ((x >> 23) & 0x000000ff) - (127 - 15); /* the desired exponent */
+  unsigned int m =   x        & 0x007fffff;
+
+  x &= 0x7fffffff;
+
+  /* if it's within range of binary16 normals, use fast path */
+  if (ecb_expect_true (0x38800000 <= x && x <= 0x477fefff))
+    {
+      /* mantissa round-to-even */
+      m += 0x00000fff + ((m >> (23 - 10)) & 1);
+
+      /* handle overflow */
+      if (ecb_expect_false (m >= 0x00800000))
+        {
+          m >>= 1;
+          e +=  1;
+        }
+
+      return s | (e << 10) | (m >> (23 - 10));
+    }
+
+  /* handle large numbers and infinity */
+  if (ecb_expect_true (0x477fefff < x && x <= 0x7f800000))
+    return s | 0x7c00;
+
+  /* handle zero, subnormals and small numbers */
+  if (ecb_expect_true (x < 0x38800000))
+    {
+      /* zero */
+      if (ecb_expect_true (!x))
+        return s;
+
+      /* handle subnormals */
+
+      /* too small, will be zero */
+      if (e < (14 - 24)) /* might not be sharp, but is good enough */
+        return s;
+
+      m |= 0x00800000; /* make implicit bit explicit */
+
+      /* very tricky - we need to round to the nearest e (+10) bit value */
+      {
+        unsigned int bits = 14 - e;
+        unsigned int half = (1 << (bits - 1)) - 1;
+        unsigned int even = (m >> bits) & 1;
+
+        /* if this overflows, we will end up with a normalised number */
+        m = (m + half + even) >> bits;
+      }
+
+      return s | m;
+    }
+
+  /* handle NaNs, preserve leftmost nan bits, but make sure we don't turn them into infinities */
+  m >>= 13;
+
+  return s | 0x7c00 | m | !m;
+}
+
+/*******************************************************************************/
+/* floating point stuff, can be disabled by defining ECB_NO_LIBM */
+
+/* basically, everything uses "ieee pure-endian" floating point numbers */
+/* the only noteworthy exception is ancient armle, which uses order 43218765 */
+#if 0 \
+    || __i386 || __i386__ \
+    || ECB_GCC_AMD64 \
+    || __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__ \
+    || defined __s390__ || defined __s390x__ \
+    || defined __mips__ \
+    || defined __alpha__ \
+    || defined __hppa__ \
+    || defined __ia64__ \
+    || defined __m68k__ \
+    || defined __m88k__ \
+    || defined __sh__ \
+    || defined _M_IX86 || defined ECB_MSVC_AMD64 || defined _M_IA64 \
+    || (defined __arm__ && (defined __ARM_EABI__ || defined __EABI__ || defined __VFP_FP__ || defined _WIN32_WCE || defined __ANDROID__)) \
+    || defined __aarch64__
+  #define ECB_STDFP 1
+  #include <string.h> /* for memcpy */
+#else
+  #define ECB_STDFP 0
+#endif
+
+#ifndef ECB_NO_LIBM
+
+  #include <math.h> /* for frexp*, ldexp*, INFINITY, NAN */
+
+  /* only the oldest of old doesn't have this one. solaris. */
+  #ifdef INFINITY
+    #define ECB_INFINITY INFINITY
+  #else
+    #define ECB_INFINITY HUGE_VAL
+  #endif
+
+  #ifdef NAN
+    #define ECB_NAN NAN
+  #else
+    #define ECB_NAN ECB_INFINITY
+  #endif
+
+  #if ECB_C99 || _XOPEN_VERSION >= 600 || _POSIX_VERSION >= 200112L
+    #define ecb_ldexpf(x,e) ldexpf ((x), (e))
+    #define ecb_frexpf(x,e) frexpf ((x), (e))
+  #else
+    #define ecb_ldexpf(x,e) (float) ldexp ((double) (x), (e))
+    #define ecb_frexpf(x,e) (float) frexp ((double) (x), (e))
+  #endif
+
+  /* convert a float to ieee single/binary32 */
+  ecb_function_ ecb_const uint32_t ecb_float_to_binary32 (float x);
+  ecb_function_ ecb_const uint32_t
+  ecb_float_to_binary32 (float x)
+  {
+    uint32_t r;
+
+    #if ECB_STDFP
+      memcpy (&r, &x, 4);
+    #else
+      /* slow emulation, works for anything but -0 */
+      uint32_t m;
+      int e;
+
+      if (x == 0e0f                    ) return 0x00000000U;
+      if (x > +3.40282346638528860e+38f) return 0x7f800000U;
+      if (x < -3.40282346638528860e+38f) return 0xff800000U;
+      if (x != x                       ) return 0x7fbfffffU;
+
+      m = ecb_frexpf (x, &e) * 0x1000000U;
+
+      r = m & 0x80000000U;
+
+      if (r)
+        m = -m;
+
+      if (e <= -126)
+        {
+          m &= 0xffffffU;
+          m >>= (-125 - e);
+          e = -126;
+        }
+
+      r |= (e + 126) << 23;
+      r |= m & 0x7fffffU;
+    #endif
+
+    return r;
+  }
+
+  /* converts an ieee single/binary32 to a float */
+  ecb_function_ ecb_const float ecb_binary32_to_float (uint32_t x);
+  ecb_function_ ecb_const float
+  ecb_binary32_to_float (uint32_t x)
+  {
+    float r;
+
+    #if ECB_STDFP
+      memcpy (&r, &x, 4);
+    #else
+      /* emulation, only works for normals and subnormals and +0 */
+      int neg = x >> 31;
+      int e = (x >> 23) & 0xffU;
+
+      x &= 0x7fffffU;
+
+      if (e)
+        x |= 0x800000U;
+      else
+        e = 1;
+
+      /* we distrust ldexpf a bit and do the 2**-24 scaling by an extra multiply */
+      r = ecb_ldexpf (x * (0.5f / 0x800000U), e - 126);
+
+      r = neg ? -r : r;
+    #endif
+
+    return r;
+  }
+
+  /* convert a double to ieee double/binary64 */
+  ecb_function_ ecb_const uint64_t ecb_double_to_binary64 (double x);
+  ecb_function_ ecb_const uint64_t
+  ecb_double_to_binary64 (double x)
+  {
+    uint64_t r;
+
+    #if ECB_STDFP
+      memcpy (&r, &x, 8);
+    #else
+      /* slow emulation, works for anything but -0 */
+      uint64_t m;
+      int e;
+
+      if (x == 0e0                     ) return 0x0000000000000000U;
+      if (x > +1.79769313486231470e+308) return 0x7ff0000000000000U;
+      if (x < -1.79769313486231470e+308) return 0xfff0000000000000U;
+      if (x != x                       ) return 0X7ff7ffffffffffffU;
+
+      m = frexp (x, &e) * 0x20000000000000U;
+
+      r = m & 0x8000000000000000;;
+
+      if (r)
+        m = -m;
+
+      if (e <= -1022)
+        {
+          m &= 0x1fffffffffffffU;
+          m >>= (-1021 - e);
+          e = -1022;
+        }
+
+      r |= ((uint64_t)(e + 1022)) << 52;
+      r |= m & 0xfffffffffffffU;
+    #endif
+
+    return r;
+  }
+
+  /* converts an ieee double/binary64 to a double */
+  ecb_function_ ecb_const double ecb_binary64_to_double (uint64_t x);
+  ecb_function_ ecb_const double
+  ecb_binary64_to_double (uint64_t x)
+  {
+    double r;
+
+    #if ECB_STDFP
+      memcpy (&r, &x, 8);
+    #else
+      /* emulation, only works for normals and subnormals and +0 */
+      int neg = x >> 63;
+      int e = (x >> 52) & 0x7ffU;
+
+      x &= 0xfffffffffffffU;
+
+      if (e)
+        x |= 0x10000000000000U;
+      else
+        e = 1;
+
+      /* we distrust ldexp a bit and do the 2**-53 scaling by an extra multiply */
+      r = ldexp (x * (0.5 / 0x10000000000000U), e - 1022);
+
+      r = neg ? -r : r;
+    #endif
+
+    return r;
+  }
+
+  /* convert a float to ieee half/binary16 */
+  ecb_function_ ecb_const uint16_t ecb_float_to_binary16 (float x);
+  ecb_function_ ecb_const uint16_t
+  ecb_float_to_binary16 (float x)
+  {
+    return ecb_binary32_to_binary16 (ecb_float_to_binary32 (x));
+  }
+
+  /* convert an ieee half/binary16 to float */
+  ecb_function_ ecb_const float ecb_binary16_to_float (uint16_t x);
+  ecb_function_ ecb_const float
+  ecb_binary16_to_float (uint16_t x)
+  {
+    return ecb_binary32_to_float (ecb_binary16_to_binary32 (x));
+  }
+
+#endif
+
+#endif
+
+/* ECB.H END */
+
+#if ECB_MEMORY_FENCE_NEEDS_PTHREADS
+/* if your architecture doesn't need memory fences, e.g. because it is
+ * single-cpu/core, or if you use libev in a project that doesn't use libev
+ * from multiple threads, then you can define ECB_AVOID_PTHREADS when compiling
+ * libev, in which cases the memory fences become nops.
+ * alternatively, you can remove this #error and link against libpthread,
+ * which will then provide the memory fences.
+ */
+# error "memory fences not defined for your architecture, please report"
+#endif
+
+#ifndef ECB_MEMORY_FENCE
+# define ECB_MEMORY_FENCE do { } while (0)
+# define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE
+# define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
+#endif
+
+#define expect_false(cond) ecb_expect_false (cond)
+#define expect_true(cond)  ecb_expect_true  (cond)
+#define noinline           ecb_noinline
+
+#define inline_size        ecb_inline
 
 #if EV_FEATURE_CODE
-# define inline_speed      static inline
+# define inline_speed      ecb_inline
 #else
 # define inline_speed      static noinline
 #endif
@@ -525,11 +1576,59 @@ static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work?
 
 /*****************************************************************************/
 
+/* define a suitable floor function (only used by periodics atm) */
+
+#if EV_USE_FLOOR
+# include <math.h>
+# define ev_floor(v) floor (v)
+#else
+
+#include <float.h>
+
+/* a floor() replacement function, should be independent of ev_tstamp type */
+static ev_tstamp noinline
+ev_floor (ev_tstamp v)
+{
+  /* the choice of shift factor is not terribly important */
+#if FLT_RADIX != 2 /* assume FLT_RADIX == 10 */
+  const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 10000000000000000000. : 1000000000.;
+#else
+  const ev_tstamp shift = sizeof (unsigned long) >= 8 ? 18446744073709551616. : 4294967296.;
+#endif
+
+  /* argument too large for an unsigned long? */
+  if (expect_false (v >= shift))
+    {
+      ev_tstamp f;
+
+      if (v == v - 1.)
+        return v; /* very large number */
+
+      f = shift * ev_floor (v * (1. / shift));
+      return f + ev_floor (v - f);
+    }
+
+  /* special treatment for negative args? */
+  if (expect_false (v < 0.))
+    {
+      ev_tstamp f = -ev_floor (-v);
+
+      return f - (f == v ? 0 : 1);
+    }
+
+  /* fits into an unsigned long */
+  return (unsigned long)v;
+}
+
+#endif
+
+/*****************************************************************************/
+
 #ifdef __linux
 # include <sys/utsname.h>
 #endif
 
-static unsigned int noinline
+static unsigned int noinline ecb_cold
 ev_linux_version (void)
 {
 #ifdef __linux
@@ -568,22 +1667,22 @@ ev_linux_version (void)
 /*****************************************************************************/
 
 #if EV_AVOID_STDIO
-static void noinline
+static void noinline ecb_cold
 ev_printerr (const char *msg)
 {
   write (STDERR_FILENO, msg, strlen (msg));
 }
 #endif
 
-static void (*syserr_cb)(const char *msg);
+static void (*syserr_cb)(const char *msg) EV_THROW;
 
-void
-ev_set_syserr_cb (void (*cb)(const char *msg))
+void ecb_cold
+ev_set_syserr_cb (void (*cb)(const char *msg) EV_THROW) EV_THROW
 {
   syserr_cb = cb;
 }
 
-static void noinline
+static void noinline ecb_cold
 ev_syserr (const char *msg)
 {
   if (!msg)
@@ -606,14 +1705,13 @@ ev_syserr (const char *msg)
 }
 
 static void *
-ev_realloc_emul (void *ptr, long size)
+ev_realloc_emul (void *ptr, long size) EV_THROW
 {
-#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.
+   * recently, also (at least) fedora and debian started breaking it,
+   * despite documenting it otherwise.
    */
 
   if (size)
@@ -621,13 +1719,12 @@ ev_realloc_emul (void *ptr, long size)
 
   free (ptr);
   return 0;
-#endif
 }
 
-static void *(*alloc)(void *ptr, long size) = ev_realloc_emul;
+static void *(*alloc)(void *ptr, long size) EV_THROW = ev_realloc_emul;
 
-void
-ev_set_allocator (void *(*cb)(void *ptr, long size))
+void ecb_cold
+ev_set_allocator (void *(*cb)(void *ptr, long size) EV_THROW) EV_THROW
 {
   alloc = cb;
 }
@@ -725,11 +1822,11 @@ typedef struct
   #include "ev_wrap.h"
 
   static struct ev_loop default_loop_struct;
-  struct ev_loop *ev_default_loop_ptr;
+  EV_API_DECL struct ev_loop *ev_default_loop_ptr = 0; /* needs to be initialised to make it a definition despite extern */
 
 #else
 
-  ev_tstamp ev_rt_now;
+  EV_API_DECL ev_tstamp ev_rt_now = 0; /* needs to be initialised to make it a definition despite extern */
   #define VAR(name,decl) static decl;
     #include "ev_vars.h"
   #undef VAR
@@ -754,7 +1851,7 @@ typedef struct
 
 #ifndef EV_HAVE_EV_TIME
 ev_tstamp
-ev_time (void)
+ev_time (void) EV_THROW
 {
 #if EV_USE_REALTIME
   if (expect_true (have_realtime))
@@ -788,14 +1885,14 @@ get_clock (void)
 
 #if EV_MULTIPLICITY
 ev_tstamp
-ev_now (EV_P)
+ev_now (EV_P) EV_THROW
 {
   return ev_rt_now;
 }
 #endif
 
 void
-ev_sleep (ev_tstamp delay)
+ev_sleep (ev_tstamp delay) EV_THROW
 {
   if (delay > 0.)
     {
@@ -804,7 +1901,7 @@ ev_sleep (ev_tstamp delay)
 
       EV_TS_SET (ts, delay);
       nanosleep (&ts, 0);
-#elif defined(_WIN32)
+#elif defined _WIN32
       Sleep ((unsigned long)(delay * 1e3));
 #else
       struct timeval tv;
@@ -818,14 +1915,6 @@ ev_sleep (ev_tstamp delay)
     }
 }
 
-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 */
@@ -841,7 +1930,7 @@ array_nextsize (int elem, int cur, int cnt)
     ncur <<= 1;
   while (cnt > ncur);
 
-  /* if size is large, round to MALLOC_ROUND - 4 * longs to accomodate malloc overhead */
+  /* if size is large, round to MALLOC_ROUND - 4 * longs to accommodate malloc overhead */
   if (elem * ncur > MALLOC_ROUND - sizeof (void *) * 4)
     {
       ncur *= elem;
@@ -853,7 +1942,7 @@ array_nextsize (int elem, int cur, int cnt)
   return ncur;
 }
 
-static noinline void *
+static void * noinline ecb_cold
 array_realloc (int elem, void *base, int *cur, int cnt)
 {
   *cur = array_nextsize (elem, *cur, cnt);
@@ -866,7 +1955,7 @@ array_realloc (int elem, void *base, int *cur, int cnt)
 #define array_needsize(type,base,cur,cnt,init)			\
   if (expect_false ((cnt) > (cur)))				\
     {								\
-      int ocur_ = (cur);					\
+      int ecb_unused ocur_ = (cur);					\
       (base) = (type *)array_realloc				\
          (sizeof (type), (base), &(cur), (cnt));		\
       init ((base) + (ocur_), (cur) - ocur_);			\
@@ -894,7 +1983,7 @@ pendingcb (EV_P_ ev_prepare *w, int revents)
 }
 
 void noinline
-ev_feed_event (EV_P_ void *w, int revents)
+ev_feed_event (EV_P_ void *w, int revents) EV_THROW
 {
   W w_ = (W)w;
   int pri = ABSPRI (w_);
@@ -908,6 +1997,8 @@ ev_feed_event (EV_P_ void *w, int revents)
       pendings [pri][w_->pending - 1].w      = w_;
       pendings [pri][w_->pending - 1].events = revents;
     }
+
+  pendingpri = NUMPRI - 1;
 }
 
 inline_speed void
@@ -963,7 +2054,7 @@ fd_event (EV_P_ int fd, int revents)
 }
 
 void
-ev_feed_fd_event (EV_P_ int fd, int revents)
+ev_feed_fd_event (EV_P_ int fd, int revents) EV_THROW
 {
   if (fd >= 0 && fd < anfdmax)
     fd_event_nocheck (EV_A_ fd, revents);
@@ -982,7 +2073,7 @@ fd_reify (EV_P)
       int fd = fdchanges [i];
       ANFD *anfd = anfds + fd;
 
-      if (anfd->reify & EV__IOFDSET)
+      if (anfd->reify & EV__IOFDSET && anfd->head)
         {
           SOCKET handle = EV_FD_TO_WIN32_HANDLE (fd);
 
@@ -1046,7 +2137,7 @@ fd_change (EV_P_ int fd, int flags)
 }
 
 /* the given fd is invalid/unusable, so make sure it doesn't hurt us anymore */
-inline_speed void
+inline_speed void ecb_cold
 fd_kill (EV_P_ int fd)
 {
   ev_io *w;
@@ -1059,7 +2150,7 @@ fd_kill (EV_P_ int fd)
 }
 
 /* check whether the given fd is actually valid, for error recovery */
-inline_size int
+inline_size int ecb_cold
 fd_valid (int fd)
 {
 #ifdef _WIN32
@@ -1070,7 +2161,7 @@ fd_valid (int fd)
 }
 
 /* called on EBADF to verify fds */
-static void noinline
+static void noinline ecb_cold
 fd_ebadf (EV_P)
 {
   int fd;
@@ -1082,7 +2173,7 @@ fd_ebadf (EV_P)
 }
 
 /* called on ENOMEM in select/poll to kill some fds and retry */
-static void noinline
+static void noinline ecb_cold
 fd_enomem (EV_P)
 {
   int fd;
@@ -1287,62 +2378,94 @@ static ANSIG signals [EV_NSIG - 1];
 
 #if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
 
-static void noinline
+static void noinline ecb_cold
 evpipe_init (EV_P)
 {
   if (!ev_is_active (&pipe_w))
     {
+      int fds [2];
+
 # if EV_USE_EVENTFD
-      evfd = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
-      if (evfd < 0 && errno == EINVAL)
-        evfd = eventfd (0, 0);
+      fds [0] = -1;
+      fds [1] = eventfd (0, EFD_NONBLOCK | EFD_CLOEXEC);
+      if (fds [1] < 0 && errno == EINVAL)
+        fds [1] = eventfd (0, 0);
 
-      if (evfd >= 0)
+      if (fds [1] < 0)
+# endif
         {
-          evpipe [0] = -1;
-          fd_intern (evfd); /* doing it twice doesn't hurt */
-          ev_io_set (&pipe_w, evfd, EV_READ);
+          while (pipe (fds))
+            ev_syserr ("(libev) error creating signal/async pipe");
+
+          fd_intern (fds [0]);
         }
+
+      evpipe [0] = fds [0];
+
+      if (evpipe [1] < 0)
+        evpipe [1] = fds [1]; /* first call, set write fd */
       else
-# endif
         {
-          while (pipe (evpipe))
-            ev_syserr ("(libev) error creating signal/async pipe");
+          /* on subsequent calls, do not change evpipe [1] */
+          /* so that evpipe_write can always rely on its value. */
+          /* this branch does not do anything sensible on windows, */
+          /* so must not be executed on windows */
 
-          fd_intern (evpipe [0]);
-          fd_intern (evpipe [1]);
-          ev_io_set (&pipe_w, evpipe [0], EV_READ);
+          dup2 (fds [1], evpipe [1]);
+          close (fds [1]);
         }
 
+      fd_intern (evpipe [1]);
+
+      ev_io_set (&pipe_w, evpipe [0] < 0 ? evpipe [1] : evpipe [0], EV_READ);
       ev_io_start (EV_A_ &pipe_w);
       ev_unref (EV_A); /* watcher should not keep loop alive */
     }
 }
 
-inline_size void
+inline_speed void
 evpipe_write (EV_P_ EV_ATOMIC_T *flag)
 {
-  if (!*flag)
+  ECB_MEMORY_FENCE; /* push out the write before this function was called, acquire flag */
+
+  if (expect_true (*flag))
+    return;
+
+  *flag = 1;
+  ECB_MEMORY_FENCE_RELEASE; /* make sure flag is visible before the wakeup */
+
+  pipe_write_skipped = 1;
+
+  ECB_MEMORY_FENCE; /* make sure pipe_write_skipped is visible before we check pipe_write_wanted */
+
+  if (pipe_write_wanted)
     {
-      int old_errno = errno; /* save errno because write might clobber it */
-      char dummy;
+      int old_errno;
 
-      *flag = 1;
+      pipe_write_skipped = 0;
+      ECB_MEMORY_FENCE_RELEASE;
+
+      old_errno = errno; /* save errno because write will clobber it */
 
 #if EV_USE_EVENTFD
-      if (evfd >= 0)
+      if (evpipe [0] < 0)
         {
           uint64_t counter = 1;
-          write (evfd, &counter, sizeof (uint64_t));
+          write (evpipe [1], &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);
+        {
+#ifdef _WIN32
+          WSABUF buf;
+          DWORD sent;
+          buf.buf = &buf;
+          buf.len = 1;
+          WSASend (EV_FD_TO_WIN32_HANDLE (evpipe [1]), &buf, 1, &sent, 0, 0, 0);
+#else
+          write (evpipe [1], &(evpipe [1]), 1);
+#endif
+        }
 
       errno = old_errno;
     }
@@ -1355,25 +2478,42 @@ pipecb (EV_P_ ev_io *iow, int revents)
 {
   int i;
 
-#if EV_USE_EVENTFD
-  if (evfd >= 0)
+  if (revents & EV_READ)
     {
-      uint64_t counter;
-      read (evfd, &counter, sizeof (uint64_t));
-    }
-  else
+#if EV_USE_EVENTFD
+      if (evpipe [0] < 0)
+        {
+          uint64_t counter;
+          read (evpipe [1], &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);
+        {
+          char dummy[4];
+#ifdef _WIN32
+          WSABUF buf;
+          DWORD recvd;
+          DWORD flags = 0;
+          buf.buf = dummy;
+          buf.len = sizeof (dummy);
+          WSARecv (EV_FD_TO_WIN32_HANDLE (evpipe [0]), &buf, 1, &recvd, &flags, 0, 0);
+#else
+          read (evpipe [0], &dummy, sizeof (dummy));
+#endif
+        }
     }
 
+  pipe_write_skipped = 0;
+
+  ECB_MEMORY_FENCE; /* push out skipped, acquire flags */
+
 #if EV_SIGNAL_ENABLE
   if (sig_pending)
     {
       sig_pending = 0;
 
+      ECB_MEMORY_FENCE;
+
       for (i = EV_NSIG - 1; i--; )
         if (expect_false (signals [i].pending))
           ev_feed_signal_event (EV_A_ i + 1);
@@ -1385,10 +2525,13 @@ pipecb (EV_P_ ev_io *iow, int revents)
     {
       async_pending = 0;
 
+      ECB_MEMORY_FENCE;
+
       for (i = asynccnt; i--; )
         if (asyncs [i]->sent)
           {
             asyncs [i]->sent = 0;
+            ECB_MEMORY_FENCE_RELEASE;
             ev_feed_event (EV_A_ asyncs [i], EV_ASYNC);
           }
     }
@@ -1398,10 +2541,12 @@ pipecb (EV_P_ ev_io *iow, int revents)
 /*****************************************************************************/
 
 void
-ev_feed_signal (int signum)
+ev_feed_signal (int signum) EV_THROW
 {
 #if EV_MULTIPLICITY
-  EV_P = signals [signum - 1].loop;
+  EV_P;
+  ECB_MEMORY_FENCE_ACQUIRE;
+  EV_A = signals [signum - 1].loop;
 
   if (!EV_A)
     return;
@@ -1422,11 +2567,11 @@ ev_sighandler (int signum)
 }
 
 void noinline
-ev_feed_signal_event (EV_P_ int signum)
+ev_feed_signal_event (EV_P_ int signum) EV_THROW
 {
   WL w;
 
-  if (expect_false (signum <= 0 || signum > EV_NSIG))
+  if (expect_false (signum <= 0 || signum >= EV_NSIG))
     return;
 
   --signum;
@@ -1440,6 +2585,7 @@ ev_feed_signal_event (EV_P_ int signum)
 #endif
 
   signals [signum].pending = 0;
+  ECB_MEMORY_FENCE_RELEASE;
 
   for (w = signals [signum].head; w; w = w->next)
     ev_feed_event (EV_A_ (W)w, EV_SIGNAL);
@@ -1547,20 +2693,20 @@ childcb (EV_P_ ev_signal *sw, int revents)
 # include "ev_select.c"
 #endif
 
-int
-ev_version_major (void)
+int ecb_cold
+ev_version_major (void) EV_THROW
 {
   return EV_VERSION_MAJOR;
 }
 
-int
-ev_version_minor (void)
+int ecb_cold
+ev_version_minor (void) EV_THROW
 {
   return EV_VERSION_MINOR;
 }
 
 /* return true if we are running with elevated privileges and should ignore env variables */
-int inline_size
+int inline_size ecb_cold
 enable_secure (void)
 {
 #ifdef _WIN32
@@ -1571,8 +2717,8 @@ enable_secure (void)
 #endif
 }
 
-unsigned int
-ev_supported_backends (void)
+unsigned int ecb_cold
+ev_supported_backends (void) EV_THROW
 {
   unsigned int flags = 0;
 
@@ -1585,8 +2731,8 @@ ev_supported_backends (void)
   return flags;
 }
 
-unsigned int
-ev_recommended_backends (void)
+unsigned int ecb_cold
+ev_recommended_backends (void) EV_THROW
 {
   unsigned int flags = ev_supported_backends ();
 
@@ -1607,8 +2753,8 @@ ev_recommended_backends (void)
   return flags;
 }
 
-unsigned int
-ev_embeddable_backends (void)
+unsigned int ecb_cold
+ev_embeddable_backends (void) EV_THROW
 {
   int flags = EVBACKEND_EPOLL | EVBACKEND_KQUEUE | EVBACKEND_PORT;
 
@@ -1620,54 +2766,56 @@ ev_embeddable_backends (void)
 }
 
 unsigned int
-ev_backend (EV_P)
+ev_backend (EV_P) EV_THROW
 {
   return backend;
 }
 
 #if EV_FEATURE_API
 unsigned int
-ev_iteration (EV_P)
+ev_iteration (EV_P) EV_THROW
 {
   return loop_count;
 }
 
 unsigned int
-ev_depth (EV_P)
+ev_depth (EV_P) EV_THROW
 {
   return loop_depth;
 }
 
 void
-ev_set_io_collect_interval (EV_P_ ev_tstamp interval)
+ev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_THROW
 {
   io_blocktime = interval;
 }
 
 void
-ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval)
+ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_THROW
 {
   timeout_blocktime = interval;
 }
 
 void
-ev_set_userdata (EV_P_ void *data)
+ev_set_userdata (EV_P_ void *data) EV_THROW
 {
   userdata = data;
 }
 
 void *
-ev_userdata (EV_P)
+ev_userdata (EV_P) EV_THROW
 {
   return userdata;
 }
 
-void ev_set_invoke_pending_cb (EV_P_ void (*invoke_pending_cb)(EV_P))
+void
+ev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending_cb) EV_THROW
 {
   invoke_cb = invoke_pending_cb;
 }
 
-void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P))
+void
+ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_THROW, void (*acquire)(EV_P) EV_THROW) EV_THROW
 {
   release_cb = release;
   acquire_cb = acquire;
@@ -1675,8 +2823,8 @@ void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P), void (*acquire)(EV_P))
 #endif
 
 /* initialise a loop structure, must be zero-initialised */
-static void noinline
-loop_init (EV_P_ unsigned int flags)
+static void noinline ecb_cold
+loop_init (EV_P_ unsigned int flags) EV_THROW
 {
   if (!backend)
     {
@@ -1713,27 +2861,31 @@ loop_init (EV_P_ unsigned int flags)
           && 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;
+      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;
+      invoke_cb          = ev_invoke_pending;
 #endif
 
-      io_blocktime      = 0.;
-      timeout_blocktime = 0.;
-      backend           = 0;
-      backend_fd        = -1;
-      sig_pending       = 0;
+      io_blocktime       = 0.;
+      timeout_blocktime  = 0.;
+      backend            = 0;
+      backend_fd         = -1;
+      sig_pending        = 0;
 #if EV_ASYNC_ENABLE
-      async_pending     = 0;
+      async_pending      = 0;
 #endif
+      pipe_write_skipped = 0;
+      pipe_write_wanted  = 0;
+      evpipe [0]         = -1;
+      evpipe [1]         = -1;
 #if EV_USE_INOTIFY
-      fs_fd             = flags & EVFLAG_NOINOTIFY ? -1 : -2;
+      fs_fd              = flags & EVFLAG_NOINOTIFY ? -1 : -2;
 #endif
 #if EV_USE_SIGNALFD
-      sigfd             = flags & EVFLAG_SIGNALFD  ? -2 : -1;
+      sigfd              = flags & EVFLAG_SIGNALFD  ? -2 : -1;
 #endif
 
       if (!(flags & EVBACKEND_MASK))
@@ -1768,7 +2920,7 @@ loop_init (EV_P_ unsigned int flags)
 }
 
 /* free up a loop structure */
-void
+void ecb_cold
 ev_loop_destroy (EV_P)
 {
   int i;
@@ -1789,7 +2941,7 @@ ev_loop_destroy (EV_P)
 #endif
 
 #if EV_CHILD_ENABLE
-  if (ev_is_active (&childev))
+  if (ev_is_default_loop (EV_A) && ev_is_active (&childev))
     {
       ev_ref (EV_A); /* child watcher */
       ev_signal_stop (EV_A_ &childev);
@@ -1801,16 +2953,8 @@ ev_loop_destroy (EV_P)
       /*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 (evpipe [0] >= 0) EV_WIN32_CLOSE_FD (evpipe [0]);
+      if (evpipe [1] >= 0) EV_WIN32_CLOSE_FD (evpipe [1]);
     }
 
 #if EV_USE_SIGNALFD
@@ -1906,43 +3050,30 @@ loop_fork (EV_P)
   infy_fork (EV_A);
 #endif
 
-  if (ev_is_active (&pipe_w))
+#if EV_SIGNAL_ENABLE || EV_ASYNC_ENABLE
+  if (ev_is_active (&pipe_w) && postfork != 2)
     {
-      /* 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
+      /* pipe_write_wanted must be false now, so modifying fd vars should be safe */
 
       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]);
-        }
+        EV_WIN32_CLOSE_FD (evpipe [0]);
 
-#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
+      /* iterate over everything, in case we missed something before */
+      ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
     }
+#endif
 
   postfork = 0;
 }
 
 #if EV_MULTIPLICITY
 
-struct ev_loop *
-ev_loop_new (unsigned int flags)
+struct ev_loop * ecb_cold
+ev_loop_new (unsigned int flags) EV_THROW
 {
   EV_P = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));
 
@@ -1959,7 +3090,7 @@ ev_loop_new (unsigned int flags)
 #endif /* multiplicity */
 
 #if EV_VERIFY
-static void noinline
+static void noinline ecb_cold
 verify_watcher (EV_P_ W w)
 {
   assert (("libev: watcher has invalid priority", ABSPRI (w) >= 0 && ABSPRI (w) < NUMPRI));
@@ -1968,7 +3099,7 @@ verify_watcher (EV_P_ W w)
     assert (("libev: pending watcher not on pending queue", pendings [ABSPRI (w)][w->pending - 1].w == w));
 }
 
-static void noinline
+static void noinline ecb_cold
 verify_heap (EV_P_ ANHE *heap, int N)
 {
   int i;
@@ -1983,7 +3114,7 @@ verify_heap (EV_P_ ANHE *heap, int N)
     }
 }
 
-static void noinline
+static void noinline ecb_cold
 array_verify (EV_P_ W *ws, int cnt)
 {
   while (cnt--)
@@ -1995,12 +3126,12 @@ array_verify (EV_P_ W *ws, int cnt)
 #endif
 
 #if EV_FEATURE_API
-void
-ev_verify (EV_P)
+void ecb_cold
+ev_verify (EV_P) EV_THROW
 {
 #if EV_VERIFY
   int i;
-  WL w;
+  WL w, w2;
 
   assert (activecnt >= -1);
 
@@ -2010,12 +3141,23 @@ ev_verify (EV_P)
 
   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));
-      }
+    {
+      int j = 0;
+
+      for (w = w2 = anfds [i].head; w; w = w->next)
+        {
+          verify_watcher (EV_A_ (W)w);
+
+          if (j++ & 1)
+            {
+              assert (("libev: io watcher list contains a loop", w != w2));
+              w2 = w2->next;
+            }
+
+          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);
@@ -2071,11 +3213,11 @@ ev_verify (EV_P)
 #endif
 
 #if EV_MULTIPLICITY
-struct ev_loop *
+struct ev_loop * ecb_cold
 #else
 int
 #endif
-ev_default_loop (unsigned int flags)
+ev_default_loop (unsigned int flags) EV_THROW
 {
   if (!ev_default_loop_ptr)
     {
@@ -2104,9 +3246,9 @@ ev_default_loop (unsigned int flags)
 }
 
 void
-ev_loop_fork (EV_P)
+ev_loop_fork (EV_P) EV_THROW
 {
-  postfork = 1; /* must be in line with ev_default_fork */
+  postfork = 1;
 }
 
 /*****************************************************************************/
@@ -2118,7 +3260,7 @@ ev_invoke (EV_P_ void *w, int revents)
 }
 
 unsigned int
-ev_pending_count (EV_P)
+ev_pending_count (EV_P) EV_THROW
 {
   int pri;
   unsigned int count = 0;
@@ -2132,17 +3274,21 @@ ev_pending_count (EV_P)
 void noinline
 ev_invoke_pending (EV_P)
 {
-  int pri;
+  pendingpri = NUMPRI;
 
-  for (pri = NUMPRI; pri--; )
-    while (pendingcnt [pri])
-      {
-        ANPENDING *p = pendings [pri] + --pendingcnt [pri];
+  while (pendingpri) /* pendingpri possibly gets modified in the inner loop */
+    {
+      --pendingpri;
 
-        p->w->pending = 0;
-        EV_CB_INVOKE (p->w, p->events);
-        EV_FREQUENT_CHECK;
-      }
+      while (pendingcnt [pendingpri])
+        {
+          ANPENDING *p = pendings [pendingpri] + --pendingcnt [pendingpri];
+
+          p->w->pending = 0;
+          EV_CB_INVOKE (p->w, p->events);
+          EV_FREQUENT_CHECK;
+        }
+    }
 }
 
 #if EV_IDLE_ENABLE
@@ -2210,12 +3356,28 @@ timers_reify (EV_P)
 
 #if EV_PERIODIC_ENABLE
 
-inline_speed void
+static void noinline
 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;
+  ev_tstamp interval = w->interval > MIN_INTERVAL ? w->interval : MIN_INTERVAL;
+  ev_tstamp at = w->offset + interval * ev_floor ((ev_rt_now - w->offset) / interval);
+
+  /* the above almost always errs on the low side */
+  while (at <= ev_rt_now)
+    {
+      ev_tstamp nat = at + w->interval;
+
+      /* when resolution fails us, we use ev_rt_now */
+      if (expect_false (nat == at))
+        {
+          at = ev_rt_now;
+          break;
+        }
+
+      at = nat;
+    }
+
+  ev_at (w) = at;
 }
 
 /* make periodics pending */
@@ -2226,8 +3388,6 @@ periodics_reify (EV_P)
 
   while (periodiccnt && ANHE_at (periodics [HEAP0]) < ev_rt_now)
     {
-      int feed_count = 0;
-
       do
         {
           ev_periodic *w = (ev_periodic *)ANHE_w (periodics [HEAP0]);
@@ -2247,20 +3407,6 @@ periodics_reify (EV_P)
           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);
             }
@@ -2278,7 +3424,7 @@ periodics_reify (EV_P)
 
 /* simply recalculate all periodics */
 /* TODO: maybe ensure that at least one event happens when jumping forward? */
-static void noinline
+static void noinline ecb_cold
 periodics_reschedule (EV_P)
 {
   int i;
@@ -2301,7 +3447,7 @@ periodics_reschedule (EV_P)
 #endif
 
 /* adjust all timers by a given offset */
-static void noinline
+static void noinline ecb_cold
 timers_reschedule (EV_P_ ev_tstamp adjust)
 {
   int i;
@@ -2348,9 +3494,12 @@ time_update (EV_P_ ev_tstamp max_block)
        */
       for (i = 4; --i; )
         {
+          ev_tstamp diff;
           rtmn_diff = ev_rt_now - mn_now;
 
-          if (expect_true (fabs (odiff - rtmn_diff) < MIN_TIMEJUMP))
+          diff = odiff - rtmn_diff;
+
+          if (expect_true ((diff < 0. ? -diff : diff) < MIN_TIMEJUMP))
             return; /* all is well */
 
           ev_rt_now = ev_time ();
@@ -2382,7 +3531,7 @@ time_update (EV_P_ ev_tstamp max_block)
     }
 }
 
-void
+int
 ev_run (EV_P_ int flags)
 {
 #if EV_FEATURE_API
@@ -2450,20 +3599,25 @@ ev_run (EV_P_ int flags)
         /* update time to cancel out callback processing overhead */
         time_update (EV_A_ 1e100);
 
-        if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt)))
+        /* from now on, we want a pipe-wake-up */
+        pipe_write_wanted = 1;
+
+        ECB_MEMORY_FENCE; /* make sure pipe_write_wanted is visible before we check for potential skips */
+
+        if (expect_true (!(flags & EVRUN_NOWAIT || idleall || !activecnt || pipe_write_skipped)))
           {
             waittime = MAX_BLOCKTIME;
 
             if (timercnt)
               {
-                ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now + backend_fudge;
+                ev_tstamp to = ANHE_at (timers [HEAP0]) - mn_now;
                 if (waittime > to) waittime = to;
               }
 
 #if EV_PERIODIC_ENABLE
             if (periodiccnt)
               {
-                ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now + backend_fudge;
+                ev_tstamp to = ANHE_at (periodics [HEAP0]) - ev_rt_now;
                 if (waittime > to) waittime = to;
               }
 #endif
@@ -2472,13 +3626,18 @@ ev_run (EV_P_ int flags)
             if (expect_false (waittime < timeout_blocktime))
               waittime = timeout_blocktime;
 
+            /* at this point, we NEED to wait, so we have to ensure */
+            /* to pass a minimum nonzero value to the backend */
+            if (expect_false (waittime < backend_mintime))
+              waittime = backend_mintime;
+
             /* 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 (sleeptime > waittime - backend_mintime)
+                  sleeptime = waittime - backend_mintime;
 
                 if (expect_true (sleeptime > 0.))
                   {
@@ -2495,6 +3654,16 @@ ev_run (EV_P_ int flags)
         backend_poll (EV_A_ waittime);
         assert ((loop_done = EVBREAK_CANCEL, 1)); /* assert for side effect */
 
+        pipe_write_wanted = 0; /* just an optimisation, no fence needed */
+
+        ECB_MEMORY_FENCE_ACQUIRE;
+        if (pipe_write_skipped)
+          {
+            assert (("libev: pipe_w not active, but pipe not written", ev_is_active (&pipe_w)));
+            ev_feed_event (EV_A_ &pipe_w, EV_CUSTOM);
+          }
+
+
         /* update ev_rt_now, do magic */
         time_update (EV_A_ waittime + sleeptime);
       }
@@ -2530,40 +3699,42 @@ ev_run (EV_P_ int flags)
 #if EV_FEATURE_API
   --loop_depth;
 #endif
+
+  return activecnt;
 }
 
 void
-ev_break (EV_P_ int how)
+ev_break (EV_P_ int how) EV_THROW
 {
   loop_done = how;
 }
 
 void
-ev_ref (EV_P)
+ev_ref (EV_P) EV_THROW
 {
   ++activecnt;
 }
 
 void
-ev_unref (EV_P)
+ev_unref (EV_P) EV_THROW
 {
   --activecnt;
 }
 
 void
-ev_now_update (EV_P)
+ev_now_update (EV_P) EV_THROW
 {
   time_update (EV_A_ 1e100);
 }
 
 void
-ev_suspend (EV_P)
+ev_suspend (EV_P) EV_THROW
 {
   ev_now_update (EV_A);
 }
 
 void
-ev_resume (EV_P)
+ev_resume (EV_P) EV_THROW
 {
   ev_tstamp mn_prev = mn_now;
 
@@ -2612,7 +3783,7 @@ clear_pending (EV_P_ W w)
 }
 
 int
-ev_clear_pending (EV_P_ void *w)
+ev_clear_pending (EV_P_ void *w) EV_THROW
 {
   W w_ = (W)w;
   int pending = w_->pending;
@@ -2655,7 +3826,7 @@ ev_stop (EV_P_ W w)
 /*****************************************************************************/
 
 void noinline
-ev_io_start (EV_P_ ev_io *w)
+ev_io_start (EV_P_ ev_io *w) EV_THROW
 {
   int fd = w->fd;
 
@@ -2671,6 +3842,9 @@ ev_io_start (EV_P_ ev_io *w)
   array_needsize (ANFD, anfds, anfdmax, fd + 1, array_init_zero);
   wlist_add (&anfds[fd].head, (WL)w);
 
+  /* common bug, apparently */
+  assert (("libev: ev_io_start called with corrupted watcher", ((WL)w)->next != (WL)w));
+
   fd_change (EV_A_ fd, w->events & EV__IOFDSET | EV_ANFD_REIFY);
   w->events &= ~EV__IOFDSET;
 
@@ -2678,7 +3852,7 @@ ev_io_start (EV_P_ ev_io *w)
 }
 
 void noinline
-ev_io_stop (EV_P_ ev_io *w)
+ev_io_stop (EV_P_ ev_io *w) EV_THROW
 {
   clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
@@ -2697,7 +3871,7 @@ ev_io_stop (EV_P_ ev_io *w)
 }
 
 void noinline
-ev_timer_start (EV_P_ ev_timer *w)
+ev_timer_start (EV_P_ ev_timer *w) EV_THROW
 {
   if (expect_false (ev_is_active (w)))
     return;
@@ -2721,7 +3895,7 @@ ev_timer_start (EV_P_ ev_timer *w)
 }
 
 void noinline
-ev_timer_stop (EV_P_ ev_timer *w)
+ev_timer_stop (EV_P_ ev_timer *w) EV_THROW
 {
   clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
@@ -2751,10 +3925,12 @@ ev_timer_stop (EV_P_ ev_timer *w)
 }
 
 void noinline
-ev_timer_again (EV_P_ ev_timer *w)
+ev_timer_again (EV_P_ ev_timer *w) EV_THROW
 {
   EV_FREQUENT_CHECK;
 
+  clear_pending (EV_A_ (W)w);
+
   if (ev_is_active (w))
     {
       if (w->repeat)
@@ -2776,14 +3952,14 @@ ev_timer_again (EV_P_ ev_timer *w)
 }
 
 ev_tstamp
-ev_timer_remaining (EV_P_ ev_timer *w)
+ev_timer_remaining (EV_P_ ev_timer *w) EV_THROW
 {
   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)
+ev_periodic_start (EV_P_ ev_periodic *w) EV_THROW
 {
   if (expect_false (ev_is_active (w)))
     return;
@@ -2813,7 +3989,7 @@ ev_periodic_start (EV_P_ ev_periodic *w)
 }
 
 void noinline
-ev_periodic_stop (EV_P_ ev_periodic *w)
+ev_periodic_stop (EV_P_ ev_periodic *w) EV_THROW
 {
   clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
@@ -2841,7 +4017,7 @@ ev_periodic_stop (EV_P_ ev_periodic *w)
 }
 
 void noinline
-ev_periodic_again (EV_P_ ev_periodic *w)
+ev_periodic_again (EV_P_ ev_periodic *w) EV_THROW
 {
   /* TODO: use adjustheap and recalculation */
   ev_periodic_stop (EV_A_ w);
@@ -2856,7 +4032,7 @@ ev_periodic_again (EV_P_ ev_periodic *w)
 #if EV_SIGNAL_ENABLE
 
 void noinline
-ev_signal_start (EV_P_ ev_signal *w)
+ev_signal_start (EV_P_ ev_signal *w) EV_THROW
 {
   if (expect_false (ev_is_active (w)))
     return;
@@ -2868,6 +4044,7 @@ ev_signal_start (EV_P_ ev_signal *w)
            !signals [w->signum - 1].loop || signals [w->signum - 1].loop == loop));
 
   signals [w->signum - 1].loop = EV_A;
+  ECB_MEMORY_FENCE_RELEASE;
 #endif
 
   EV_FREQUENT_CHECK;
@@ -2937,7 +4114,7 @@ ev_signal_start (EV_P_ ev_signal *w)
 }
 
 void noinline
-ev_signal_stop (EV_P_ ev_signal *w)
+ev_signal_stop (EV_P_ ev_signal *w) EV_THROW
 {
   clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
@@ -2978,7 +4155,7 @@ ev_signal_stop (EV_P_ ev_signal *w)
 #if EV_CHILD_ENABLE
 
 void
-ev_child_start (EV_P_ ev_child *w)
+ev_child_start (EV_P_ ev_child *w) EV_THROW
 {
 #if EV_MULTIPLICITY
   assert (("libev: child watchers are only supported in the default loop", loop == ev_default_loop_ptr));
@@ -2995,7 +4172,7 @@ ev_child_start (EV_P_ ev_child *w)
 }
 
 void
-ev_child_stop (EV_P_ ev_child *w)
+ev_child_stop (EV_P_ ev_child *w) EV_THROW
 {
   clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
@@ -3032,7 +4209,10 @@ static void noinline stat_timer_cb (EV_P_ ev_timer *w_, int revents);
 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);
+  w->wd = inotify_add_watch (fs_fd, w->path,
+                             IN_ATTRIB | IN_DELETE_SELF | IN_MOVE_SELF | IN_MODIFY
+                             | IN_CREATE | IN_DELETE | IN_MOVED_FROM | IN_MOVED_TO
+                             | IN_DONT_FOLLOW | IN_MASK_ADD);
 
   if (w->wd >= 0)
     {
@@ -3046,10 +4226,16 @@ infy_add (EV_P_ ev_stat *w)
         w->timer.repeat = w->interval ? w->interval : DEF_STAT_INTERVAL;
       else if (!statfs (w->path, &sfs)
                && (sfs.f_type == 0x1373 /* devfs */
+                   || sfs.f_type == 0x4006 /* fat */
+                   || sfs.f_type == 0x4d44 /* msdos */
                    || sfs.f_type == 0xEF53 /* ext2/3 */
+                   || sfs.f_type == 0x72b6 /* jffs2 */
+                   || sfs.f_type == 0x858458f6 /* ramfs */
+                   || sfs.f_type == 0x5346544e /* ntfs */
                    || sfs.f_type == 0x3153464a /* jfs */
+                   || sfs.f_type == 0x9123683e /* btrfs */
                    || sfs.f_type == 0x52654973 /* reiser3 */
-                   || sfs.f_type == 0x01021994 /* tempfs */
+                   || sfs.f_type == 0x01021994 /* tmpfs */
                    || sfs.f_type == 0x58465342 /* xfs */))
         w->timer.repeat = 0.; /* filesystem is local, kernel new enough */
       else
@@ -3157,7 +4343,7 @@ infy_cb (EV_P_ ev_io *w, int revents)
     }
 }
 
-inline_size void
+inline_size void ecb_cold
 ev_check_2625 (EV_P)
 {
   /* kernels < 2.6.25 are borked
@@ -3172,7 +4358,7 @@ ev_check_2625 (EV_P)
 inline_size int
 infy_newfd (void)
 {
-#if defined (IN_CLOEXEC) && defined (IN_NONBLOCK)
+#if defined IN_CLOEXEC && defined IN_NONBLOCK
   int fd = inotify_init1 (IN_CLOEXEC | IN_NONBLOCK);
   if (fd >= 0)
     return fd;
@@ -3257,7 +4443,7 @@ infy_fork (EV_P)
 #endif
 
 void
-ev_stat_stat (EV_P_ ev_stat *w)
+ev_stat_stat (EV_P_ ev_stat *w) EV_THROW
 {
   if (lstat (w->path, &w->attr) < 0)
     w->attr.st_nlink = 0;
@@ -3306,7 +4492,7 @@ stat_timer_cb (EV_P_ ev_timer *w_, int revents)
 }
 
 void
-ev_stat_start (EV_P_ ev_stat *w)
+ev_stat_start (EV_P_ ev_stat *w) EV_THROW
 {
   if (expect_false (ev_is_active (w)))
     return;
@@ -3337,7 +4523,7 @@ ev_stat_start (EV_P_ ev_stat *w)
 }
 
 void
-ev_stat_stop (EV_P_ ev_stat *w)
+ev_stat_stop (EV_P_ ev_stat *w) EV_THROW
 {
   clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
@@ -3363,7 +4549,7 @@ ev_stat_stop (EV_P_ ev_stat *w)
 
 #if EV_IDLE_ENABLE
 void
-ev_idle_start (EV_P_ ev_idle *w)
+ev_idle_start (EV_P_ ev_idle *w) EV_THROW
 {
   if (expect_false (ev_is_active (w)))
     return;
@@ -3386,7 +4572,7 @@ ev_idle_start (EV_P_ ev_idle *w)
 }
 
 void
-ev_idle_stop (EV_P_ ev_idle *w)
+ev_idle_stop (EV_P_ ev_idle *w) EV_THROW
 {
   clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
@@ -3410,7 +4596,7 @@ ev_idle_stop (EV_P_ ev_idle *w)
 
 #if EV_PREPARE_ENABLE
 void
-ev_prepare_start (EV_P_ ev_prepare *w)
+ev_prepare_start (EV_P_ ev_prepare *w) EV_THROW
 {
   if (expect_false (ev_is_active (w)))
     return;
@@ -3425,7 +4611,7 @@ ev_prepare_start (EV_P_ ev_prepare *w)
 }
 
 void
-ev_prepare_stop (EV_P_ ev_prepare *w)
+ev_prepare_stop (EV_P_ ev_prepare *w) EV_THROW
 {
   clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
@@ -3448,7 +4634,7 @@ ev_prepare_stop (EV_P_ ev_prepare *w)
 
 #if EV_CHECK_ENABLE
 void
-ev_check_start (EV_P_ ev_check *w)
+ev_check_start (EV_P_ ev_check *w) EV_THROW
 {
   if (expect_false (ev_is_active (w)))
     return;
@@ -3463,7 +4649,7 @@ ev_check_start (EV_P_ ev_check *w)
 }
 
 void
-ev_check_stop (EV_P_ ev_check *w)
+ev_check_stop (EV_P_ ev_check *w) EV_THROW
 {
   clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
@@ -3486,7 +4672,7 @@ ev_check_stop (EV_P_ ev_check *w)
 
 #if EV_EMBED_ENABLE
 void noinline
-ev_embed_sweep (EV_P_ ev_embed *w)
+ev_embed_sweep (EV_P_ ev_embed *w) EV_THROW
 {
   ev_run (w->other, EVRUN_NOWAIT);
 }
@@ -3544,7 +4730,7 @@ embed_idle_cb (EV_P_ ev_idle *idle, int revents)
 #endif
 
 void
-ev_embed_start (EV_P_ ev_embed *w)
+ev_embed_start (EV_P_ ev_embed *w) EV_THROW
 {
   if (expect_false (ev_is_active (w)))
     return;
@@ -3575,7 +4761,7 @@ ev_embed_start (EV_P_ ev_embed *w)
 }
 
 void
-ev_embed_stop (EV_P_ ev_embed *w)
+ev_embed_stop (EV_P_ ev_embed *w) EV_THROW
 {
   clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
@@ -3595,7 +4781,7 @@ ev_embed_stop (EV_P_ ev_embed *w)
 
 #if EV_FORK_ENABLE
 void
-ev_fork_start (EV_P_ ev_fork *w)
+ev_fork_start (EV_P_ ev_fork *w) EV_THROW
 {
   if (expect_false (ev_is_active (w)))
     return;
@@ -3610,7 +4796,7 @@ ev_fork_start (EV_P_ ev_fork *w)
 }
 
 void
-ev_fork_stop (EV_P_ ev_fork *w)
+ev_fork_stop (EV_P_ ev_fork *w) EV_THROW
 {
   clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
@@ -3633,7 +4819,7 @@ ev_fork_stop (EV_P_ ev_fork *w)
 
 #if EV_CLEANUP_ENABLE
 void
-ev_cleanup_start (EV_P_ ev_cleanup *w)
+ev_cleanup_start (EV_P_ ev_cleanup *w) EV_THROW
 {
   if (expect_false (ev_is_active (w)))
     return;
@@ -3650,7 +4836,7 @@ ev_cleanup_start (EV_P_ ev_cleanup *w)
 }
 
 void
-ev_cleanup_stop (EV_P_ ev_cleanup *w)
+ev_cleanup_stop (EV_P_ ev_cleanup *w) EV_THROW
 {
   clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
@@ -3674,7 +4860,7 @@ ev_cleanup_stop (EV_P_ ev_cleanup *w)
 
 #if EV_ASYNC_ENABLE
 void
-ev_async_start (EV_P_ ev_async *w)
+ev_async_start (EV_P_ ev_async *w) EV_THROW
 {
   if (expect_false (ev_is_active (w)))
     return;
@@ -3693,7 +4879,7 @@ ev_async_start (EV_P_ ev_async *w)
 }
 
 void
-ev_async_stop (EV_P_ ev_async *w)
+ev_async_stop (EV_P_ ev_async *w) EV_THROW
 {
   clear_pending (EV_A_ (W)w);
   if (expect_false (!ev_is_active (w)))
@@ -3714,7 +4900,7 @@ ev_async_stop (EV_P_ ev_async *w)
 }
 
 void
-ev_async_send (EV_P_ ev_async *w)
+ev_async_send (EV_P_ ev_async *w) EV_THROW
 {
   w->sent = 1;
   evpipe_write (EV_A_ &async_pending);
@@ -3761,7 +4947,7 @@ once_cb_to (EV_P_ ev_timer *w, int revents)
 }
 
 void
-ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg)
+ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_THROW
 {
   struct ev_once *once = (struct ev_once *)ev_malloc (sizeof (struct ev_once));
 
@@ -3792,8 +4978,8 @@ ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, vo
 /*****************************************************************************/
 
 #if EV_WALK_ENABLE
-void
-ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
+void ecb_cold
+ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_THROW
 {
   int i, j;
   ev_watcher_list *wl, *wn;
@@ -3846,7 +5032,7 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
 
 #if EV_IDLE_ENABLE
   if (types & EV_IDLE)
-    for (j = NUMPRI; i--; )
+    for (j = NUMPRI; j--; )
       for (i = idlecnt [j]; i--; )
         cb (EV_A_ EV_IDLE, idles [j][i]);
 #endif
@@ -3909,5 +5095,3 @@ ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w))
   #include "ev_wrap.h"
 #endif
 
-EV_CPP(})
-
diff --git a/src/util/verto/ev.h b/src/util/verto/ev.h
index 27c1778..38f62d8 100644
--- a/src/util/verto/ev.h
+++ b/src/util/verto/ev.h
@@ -1,7 +1,7 @@
 /*
  * libev native API header
  *
- * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev at schmorp.de>
+ * Copyright (c) 2007,2008,2009,2010,2011,2012,2015 Marc Alexander Lehmann <libev at schmorp.de>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modifica-
@@ -42,8 +42,14 @@
 
 #ifdef __cplusplus
 # define EV_CPP(x) x
+# if __cplusplus >= 201103L
+#  define EV_THROW noexcept
+# else
+#  define EV_THROW throw ()
+# endif
 #else
 # define EV_CPP(x)
+# define EV_THROW
 #endif
 
 EV_CPP(extern "C" {)
@@ -56,7 +62,11 @@ EV_CPP(extern "C" {)
 #endif
 
 #ifndef EV_FEATURES
-# define EV_FEATURES 0x7f
+# if defined __OPTIMIZE_SIZE__
+#  define EV_FEATURES 0x7c
+# else
+#  define EV_FEATURES 0x7f
+# endif
 #endif
 
 #define EV_FEATURE_CODE     ((EV_FEATURES) &  1)
@@ -142,6 +152,8 @@ EV_CPP(extern "C" {)
 
 typedef double ev_tstamp;
 
+#include <string.h> /* for memmove */
+
 #ifndef EV_ATOMIC_T
 # include <signal.h>
 # define EV_ATOMIC_T sig_atomic_t volatile
@@ -185,6 +197,12 @@ struct ev_loop;
 # define EV_INLINE static
 #endif
 
+#ifdef EV_API_STATIC
+# define EV_API_DECL static
+#else
+# define EV_API_DECL extern
+#endif
+
 /* EV_PROTOTYPES can be used to switch of prototype declarations */
 #ifndef EV_PROTOTYPES
 # define EV_PROTOTYPES 1
@@ -193,33 +211,33 @@ struct ev_loop;
 /*****************************************************************************/
 
 #define EV_VERSION_MAJOR 4
-#define EV_VERSION_MINOR 4
+#define EV_VERSION_MINOR 22
 
 /* 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 */
+  EV_UNDEF    = (int)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 */
+  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    = (int)0x80000000  /* sent when an error occurs */
 };
 
 /* can be used to add custom fields to all watchers, while losing binary compatibility */
@@ -321,7 +339,7 @@ typedef struct ev_periodic
 
   ev_tstamp offset; /* rw */
   ev_tstamp interval; /* rw */
-  ev_tstamp (*reschedule_cb)(struct ev_periodic *w, ev_tstamp now); /* rw */
+  ev_tstamp (*reschedule_cb)(struct ev_periodic *w, ev_tstamp now) EV_THROW; /* rw */
 } ev_periodic;
 
 /* invoked when the given signal has been received */
@@ -508,15 +526,15 @@ enum {
 };
 
 #if EV_PROTOTYPES
-int ev_version_major (void);
-int ev_version_minor (void);
+EV_API_DECL int ev_version_major (void) EV_THROW;
+EV_API_DECL int ev_version_minor (void) EV_THROW;
 
-unsigned int ev_supported_backends (void);
-unsigned int ev_recommended_backends (void);
-unsigned int ev_embeddable_backends (void);
+EV_API_DECL unsigned int ev_supported_backends (void) EV_THROW;
+EV_API_DECL unsigned int ev_recommended_backends (void) EV_THROW;
+EV_API_DECL unsigned int ev_embeddable_backends (void) EV_THROW;
 
-ev_tstamp ev_time (void);
-void ev_sleep (ev_tstamp delay); /* sleep for a while */
+EV_API_DECL ev_tstamp ev_time (void) EV_THROW;
+EV_API_DECL void ev_sleep (ev_tstamp delay) EV_THROW; /* sleep for a while */
 
 /* Sets the allocation function to use, works like realloc.
  * It is used to allocate and free memory.
@@ -524,22 +542,26 @@ void ev_sleep (ev_tstamp delay); /* sleep for a while */
  * or take some potentially destructive action.
  * The default is your system realloc function.
  */
-void ev_set_allocator (void *(*cb)(void *ptr, long size));
+EV_API_DECL void ev_set_allocator (void *(*cb)(void *ptr, long size) EV_THROW) EV_THROW;
 
 /* 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));
+EV_API_DECL void ev_set_syserr_cb (void (*cb)(const char *msg) EV_THROW) EV_THROW;
 
 #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_API_DECL struct ev_loop *ev_default_loop (unsigned int flags EV_CPP (= 0)) EV_THROW;
+
+#ifdef EV_API_STATIC
+EV_API_DECL struct ev_loop *ev_default_loop_ptr;
+#endif
 
 EV_INLINE struct ev_loop *
-ev_default_loop_uc_ (void)
+ev_default_loop_uc_ (void) EV_THROW
 {
   extern struct ev_loop *ev_default_loop_ptr;
 
@@ -547,31 +569,31 @@ ev_default_loop_uc_ (void)
 }
 
 EV_INLINE int
-ev_is_default_loop (EV_P)
+ev_is_default_loop (EV_P) EV_THROW
 {
   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_API_DECL struct ev_loop *ev_loop_new (unsigned int flags EV_CPP (= 0)) EV_THROW;
 
-ev_tstamp ev_now (EV_P); /* time w.r.t. timers and the eventloop, updated after each poll */
+EV_API_DECL ev_tstamp ev_now (EV_P) EV_THROW; /* 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_API_DECL int ev_default_loop (unsigned int flags EV_CPP (= 0)) EV_THROW; /* returns true when successful */
+
+EV_API_DECL ev_tstamp ev_rt_now;
 
 EV_INLINE ev_tstamp
-ev_now (void)
+ev_now (void) EV_THROW
 {
-  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)
+ev_is_default_loop (void) EV_THROW
 {
   return 1;
 }
@@ -579,23 +601,23 @@ ev_is_default_loop (void)
 #endif /* multiplicity */
 
 /* destroy event loops, also works for the default loop */
-void ev_loop_destroy (EV_P);
+EV_API_DECL 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);
+EV_API_DECL void ev_loop_fork (EV_P) EV_THROW;
 
-unsigned int ev_backend (EV_P); /* backend in use by loop */
+EV_API_DECL unsigned int ev_backend (EV_P) EV_THROW; /* backend in use by loop */
 
-void ev_now_update (EV_P); /* update event loop time */
+EV_API_DECL void ev_now_update (EV_P) EV_THROW; /* 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));
+EV_API_DECL void ev_walk (EV_P_ int types, void (*cb)(EV_P_ int type, void *w)) EV_THROW;
 #endif
 
 #endif /* prototypes */
@@ -614,45 +636,47 @@ enum {
 };
 
 #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 */
+EV_API_DECL int  ev_run (EV_P_ int flags EV_CPP (= 0));
+EV_API_DECL void ev_break (EV_P_ int how EV_CPP (= EVBREAK_ONE)) EV_THROW; /* 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);
+EV_API_DECL void ev_ref   (EV_P) EV_THROW;
+EV_API_DECL void ev_unref (EV_P) EV_THROW;
 
 /*
  * 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);
+EV_API_DECL void ev_once (EV_P_ int fd, int events, ev_tstamp timeout, void (*cb)(int revents, void *arg), void *arg) EV_THROW;
 
 # 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 */
+EV_API_DECL unsigned int ev_iteration (EV_P) EV_THROW; /* number of loop iterations */
+EV_API_DECL unsigned int ev_depth     (EV_P) EV_THROW; /* #ev_loop enters - #ev_loop leaves */
+EV_API_DECL void         ev_verify    (EV_P) EV_THROW; /* 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 */
+EV_API_DECL void ev_set_io_collect_interval (EV_P_ ev_tstamp interval) EV_THROW; /* sleep at least this time, default 0 */
+EV_API_DECL void ev_set_timeout_collect_interval (EV_P_ ev_tstamp interval) EV_THROW; /* 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));
+EV_API_DECL void ev_set_userdata (EV_P_ void *data) EV_THROW;
+EV_API_DECL void *ev_userdata (EV_P) EV_THROW;
+typedef void (*ev_loop_callback)(EV_P);
+EV_API_DECL void ev_set_invoke_pending_cb (EV_P_ ev_loop_callback invoke_pending_cb) EV_THROW;
+/* C++ doesn't allow the use of the ev_loop_callback typedef here, so we need to spell it out */
+EV_API_DECL void ev_set_loop_release_cb (EV_P_ void (*release)(EV_P) EV_THROW, void (*acquire)(EV_P) EV_THROW) EV_THROW;
 
-unsigned int ev_pending_count (EV_P); /* number of pending events, if any */
-void ev_invoke_pending (EV_P); /* invoke all pending watchers */
+EV_API_DECL unsigned int ev_pending_count (EV_P) EV_THROW; /* number of pending events, if any */
+EV_API_DECL 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);
+EV_API_DECL void ev_suspend (EV_P) EV_THROW;
+EV_API_DECL void ev_resume  (EV_P) EV_THROW;
 #endif
 
 #endif
@@ -697,7 +721,8 @@ void ev_resume  (EV_P);
 #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 */
+#define ev_cb_(ev)                           (ev)->cb /* rw */
+#define ev_cb(ev)                            (memmove (&ev_cb_ (ev), &((ev_watcher *)(ev))->cb, sizeof (ev_cb_ (ev))), (ev)->cb)
 
 #if EV_MINPRI == EV_MAXPRI
 # define ev_priority(ev)                     ((ev), EV_MINPRI)
@@ -710,94 +735,94 @@ void ev_resume  (EV_P);
 #define ev_periodic_at(ev)                   (+((ev_watcher_time *)(ev))->at)
 
 #ifndef ev_set_cb
-# define ev_set_cb(ev,cb_)                   ev_cb (ev) = (cb_)
+# define ev_set_cb(ev,cb_)                   (ev_cb_ (ev) = (cb_), memmove (&((ev_watcher *)(ev))->cb, &ev_cb_ (ev), sizeof (ev_cb_ (ev))))
 #endif
 
 /* stopping (enabling, adding) a watcher does nothing if it is already running */
-/* stopping (disabling, deleting) a watcher does nothing unless its already running */
+/* stopping (disabling, deleting) a watcher does nothing unless it's already running */
 #if EV_PROTOTYPES
 
-/* feeds an event into a watcher as if the event actually occured */
+/* feeds an event into a watcher as if the event actually occurred */
 /* 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);
+EV_API_DECL void ev_feed_event     (EV_P_ void *w, int revents) EV_THROW;
+EV_API_DECL void ev_feed_fd_event  (EV_P_ int fd, int revents) EV_THROW;
 #if EV_SIGNAL_ENABLE
-void ev_feed_signal    (int signum);
-void ev_feed_signal_event (EV_P_ int signum);
+EV_API_DECL void ev_feed_signal    (int signum) EV_THROW;
+EV_API_DECL void ev_feed_signal_event (EV_P_ int signum) EV_THROW;
 #endif
-void ev_invoke         (EV_P_ void *w, int revents);
-int  ev_clear_pending  (EV_P_ void *w);
+EV_API_DECL void ev_invoke         (EV_P_ void *w, int revents);
+EV_API_DECL int  ev_clear_pending  (EV_P_ void *w) EV_THROW;
 
-void ev_io_start       (EV_P_ ev_io *w);
-void ev_io_stop        (EV_P_ ev_io *w);
+EV_API_DECL void ev_io_start       (EV_P_ ev_io *w) EV_THROW;
+EV_API_DECL void ev_io_stop        (EV_P_ ev_io *w) EV_THROW;
 
-void ev_timer_start    (EV_P_ ev_timer *w);
-void ev_timer_stop     (EV_P_ ev_timer *w);
+EV_API_DECL void ev_timer_start    (EV_P_ ev_timer *w) EV_THROW;
+EV_API_DECL void ev_timer_stop     (EV_P_ ev_timer *w) EV_THROW;
 /* 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);
+EV_API_DECL void ev_timer_again    (EV_P_ ev_timer *w) EV_THROW;
 /* return remaining time */
-ev_tstamp ev_timer_remaining (EV_P_ ev_timer *w);
+EV_API_DECL ev_tstamp ev_timer_remaining (EV_P_ ev_timer *w) EV_THROW;
 
 #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);
+EV_API_DECL void ev_periodic_start (EV_P_ ev_periodic *w) EV_THROW;
+EV_API_DECL void ev_periodic_stop  (EV_P_ ev_periodic *w) EV_THROW;
+EV_API_DECL void ev_periodic_again (EV_P_ ev_periodic *w) EV_THROW;
 #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);
+EV_API_DECL void ev_signal_start   (EV_P_ ev_signal *w) EV_THROW;
+EV_API_DECL void ev_signal_stop    (EV_P_ ev_signal *w) EV_THROW;
 #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);
+EV_API_DECL void ev_child_start    (EV_P_ ev_child *w) EV_THROW;
+EV_API_DECL void ev_child_stop     (EV_P_ ev_child *w) EV_THROW;
 # 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);
+EV_API_DECL void ev_stat_start     (EV_P_ ev_stat *w) EV_THROW;
+EV_API_DECL void ev_stat_stop      (EV_P_ ev_stat *w) EV_THROW;
+EV_API_DECL void ev_stat_stat      (EV_P_ ev_stat *w) EV_THROW;
 # endif
 
 # if EV_IDLE_ENABLE
-void ev_idle_start     (EV_P_ ev_idle *w);
-void ev_idle_stop      (EV_P_ ev_idle *w);
+EV_API_DECL void ev_idle_start     (EV_P_ ev_idle *w) EV_THROW;
+EV_API_DECL void ev_idle_stop      (EV_P_ ev_idle *w) EV_THROW;
 # endif
 
 #if EV_PREPARE_ENABLE
-void ev_prepare_start  (EV_P_ ev_prepare *w);
-void ev_prepare_stop   (EV_P_ ev_prepare *w);
+EV_API_DECL void ev_prepare_start  (EV_P_ ev_prepare *w) EV_THROW;
+EV_API_DECL void ev_prepare_stop   (EV_P_ ev_prepare *w) EV_THROW;
 #endif
 
 #if EV_CHECK_ENABLE
-void ev_check_start    (EV_P_ ev_check *w);
-void ev_check_stop     (EV_P_ ev_check *w);
+EV_API_DECL void ev_check_start    (EV_P_ ev_check *w) EV_THROW;
+EV_API_DECL void ev_check_stop     (EV_P_ ev_check *w) EV_THROW;
 #endif
 
 # if EV_FORK_ENABLE
-void ev_fork_start     (EV_P_ ev_fork *w);
-void ev_fork_stop      (EV_P_ ev_fork *w);
+EV_API_DECL void ev_fork_start     (EV_P_ ev_fork *w) EV_THROW;
+EV_API_DECL void ev_fork_stop      (EV_P_ ev_fork *w) EV_THROW;
 # endif
 
 # if EV_CLEANUP_ENABLE
-void ev_cleanup_start  (EV_P_ ev_cleanup *w);
-void ev_cleanup_stop   (EV_P_ ev_cleanup *w);
+EV_API_DECL void ev_cleanup_start  (EV_P_ ev_cleanup *w) EV_THROW;
+EV_API_DECL void ev_cleanup_stop   (EV_P_ ev_cleanup *w) EV_THROW;
 # 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);
+EV_API_DECL void ev_embed_start    (EV_P_ ev_embed *w) EV_THROW;
+EV_API_DECL void ev_embed_stop     (EV_P_ ev_embed *w) EV_THROW;
+EV_API_DECL void ev_embed_sweep    (EV_P_ ev_embed *w) EV_THROW;
 # 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);
+EV_API_DECL void ev_async_start    (EV_P_ ev_async *w) EV_THROW;
+EV_API_DECL void ev_async_stop     (EV_P_ ev_async *w) EV_THROW;
+EV_API_DECL void ev_async_send     (EV_P_ ev_async *w) EV_THROW;
 # endif
 
 #if EV_COMPAT3
diff --git a/src/util/verto/ev_poll.c b/src/util/verto/ev_poll.c
index e53ae0d..4832351 100644
--- a/src/util/verto/ev_poll.c
+++ b/src/util/verto/ev_poll.c
@@ -92,7 +92,7 @@ poll_poll (EV_P_ ev_tstamp timeout)
   int res;
   
   EV_RELEASE_CB;
-  res = poll (polls, pollcnt, ev_timeout_to_ms (timeout));
+  res = poll (polls, pollcnt, timeout * 1e3);
   EV_ACQUIRE_CB;
 
   if (expect_false (res < 0))
@@ -129,9 +129,9 @@ poll_poll (EV_P_ ev_tstamp timeout)
 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;
+  backend_mintime = 1e-3;
+  backend_modify  = poll_modify;
+  backend_poll    = poll_poll;
 
   pollidxs = 0; pollidxmax = 0;
   polls    = 0; pollmax    = 0; pollcnt = 0;
diff --git a/src/util/verto/ev_select.c b/src/util/verto/ev_select.c
index 0ea9467..f38d6ca 100644
--- a/src/util/verto/ev_select.c
+++ b/src/util/verto/ev_select.c
@@ -1,7 +1,7 @@
 /*
  * libev select fd activity backend
  *
- * Copyright (c) 2007,2008,2009,2010 Marc Alexander Lehmann <libev at schmorp.de>
+ * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev at schmorp.de>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modifica-
@@ -195,7 +195,12 @@ select_poll (EV_P_ ev_tstamp timeout)
        */
       if (errno == EINVAL)
         {
-          ev_sleep (timeout);
+          if (timeout)
+            {
+              unsigned long ms = timeout * 1e3;
+              Sleep (ms ? ms : 1);
+            }
+
           return;
         }
       #endif
@@ -269,9 +274,9 @@ select_poll (EV_P_ ev_tstamp timeout)
 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;
+  backend_mintime = 1e-6;
+  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);
@@ -307,4 +312,3 @@ select_destroy (EV_P)
   #endif
 }
 
-
diff --git a/src/util/verto/ev_vars.h b/src/util/verto/ev_vars.h
index 5ee3ed1..04d4db1 100644
--- a/src/util/verto/ev_vars.h
+++ b/src/util/verto/ev_vars.h
@@ -1,7 +1,7 @@
 /*
  * loop member variable declarations
  *
- * Copyright (c) 2007,2008,2009,2010,2011 Marc Alexander Lehmann <libev at schmorp.de>
+ * Copyright (c) 2007,2008,2009,2010,2011,2012,2013 Marc Alexander Lehmann <libev at schmorp.de>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without modifica-
@@ -43,6 +43,17 @@ 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 */
 
+/* for reverse feeding of events */
+VARx(W *, rfeeds)
+VARx(int, rfeedmax)
+VARx(int, rfeedcnt)
+
+VAR (pendings, ANPENDING *pendings [NUMPRI])
+VAR (pendingmax, int pendingmax [NUMPRI])
+VAR (pendingcnt, int pendingcnt [NUMPRI])
+VARx(int, pendingpri) /* highest priority currently pending */
+VARx(ev_prepare, pending_w) /* dummy pending watcher */
+
 VARx(ev_tstamp, io_blocktime)
 VARx(ev_tstamp, timeout_blocktime)
 
@@ -51,28 +62,17 @@ 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 */
+VARx(ev_tstamp, backend_mintime) /* 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)
+VARx(EV_ATOMIC_T, pipe_write_wanted)
+VARx(EV_ATOMIC_T, pipe_write_skipped)
 
 #if !defined(_WIN32) || EV_GENWRAP
 VARx(pid_t, curpid)
@@ -108,6 +108,7 @@ VARx(int, epoll_epermmax)
 #endif
 
 #if EV_USE_KQUEUE || EV_GENWRAP
+VARx(pid_t, kqueue_fd_pid)
 VARx(struct kevent *, kqueue_changes)
 VARx(int, kqueue_changemax)
 VARx(int, kqueue_changecnt)
@@ -180,7 +181,6 @@ 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)
@@ -194,9 +194,10 @@ 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))
+/* C++ doesn't support the ev_loop_callback typedef here. stinks. */
+VAR (release_cb, void (*release_cb)(EV_P) EV_THROW)
+VAR (acquire_cb, void (*acquire_cb)(EV_P) EV_THROW)
+VAR (invoke_cb , ev_loop_callback invoke_cb)
 #endif
 
 #undef VARx
diff --git a/src/util/verto/ev_win32.c b/src/util/verto/ev_win32.c
index 338886e..fd67135 100644
--- a/src/util/verto/ev_win32.c
+++ b/src/util/verto/ev_win32.c
@@ -39,15 +39,22 @@
 
 #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;
 
+static SOCKET
+ev_tcp_socket (void)
+{
+#if EV_USE_WSASOCKET
+  return WSASocket (AF_INET, SOCK_STREAM, 0, 0, 0, 0);
+#else
+  return socket (AF_INET, SOCK_STREAM, 0);
+#endif
+}
+
 /* oh, the humanity! */
 static int
 ev_pipe (int filedes [2])
@@ -59,7 +66,7 @@ ev_pipe (int filedes [2])
   SOCKET listener;
   SOCKET sock [2] = { -1, -1 };
 
-  if ((listener = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
+  if ((listener = ev_tcp_socket ()) == INVALID_SOCKET)
     return -1;
 
   addr.sin_family = AF_INET;
@@ -75,12 +82,14 @@ ev_pipe (int filedes [2])
   if (listen (listener, 1))
     goto fail;
 
-  if ((sock [0] = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
+  if ((sock [0] = ev_tcp_socket ()) == INVALID_SOCKET)
     goto fail;
 
   if (connect (sock [0], (struct sockaddr *)&addr, addr_size))
     goto fail;
 
+  /* TODO: returns INVALID_SOCKET on winsock accept, not < 0. fix it */
+  /* when convenient, probably by just removing error checking altogether? */
   if ((sock [1] = accept (listener, 0, 0)) < 0)
     goto fail;
 
@@ -133,7 +142,7 @@ fail:
 
 #undef pipe
 #define pipe(filedes) ev_pipe (filedes)
-  
+
 #define EV_HAVE_EV_TIME 1
 ev_tstamp
 ev_time (void)
diff --git a/src/util/verto/ev_wrap.h b/src/util/verto/ev_wrap.h
index 2c195c5..ad989ea 100644
--- a/src/util/verto/ev_wrap.h
+++ b/src/util/verto/ev_wrap.h
@@ -1,196 +1,200 @@
 /* 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 acquire_cb ((loop)->acquire_cb)
 #define activecnt ((loop)->activecnt)
-#define loop_done ((loop)->loop_done)
+#define anfdmax ((loop)->anfdmax)
+#define anfds ((loop)->anfds)
+#define async_pending ((loop)->async_pending)
+#define asynccnt ((loop)->asynccnt)
+#define asyncmax ((loop)->asyncmax)
+#define asyncs ((loop)->asyncs)
+#define backend ((loop)->backend)
 #define backend_fd ((loop)->backend_fd)
-#define backend_fudge ((loop)->backend_fudge)
+#define backend_mintime ((loop)->backend_mintime)
 #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 checkcnt ((loop)->checkcnt)
+#define checkmax ((loop)->checkmax)
+#define checks ((loop)->checks)
+#define cleanupcnt ((loop)->cleanupcnt)
+#define cleanupmax ((loop)->cleanupmax)
+#define cleanups ((loop)->cleanups)
 #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 epoll_eperms ((loop)->epoll_eperms)
+#define epoll_eventmax ((loop)->epoll_eventmax)
+#define epoll_events ((loop)->epoll_events)
+#define evpipe ((loop)->evpipe)
 #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 fdchangemax ((loop)->fdchangemax)
+#define fdchanges ((loop)->fdchanges)
 #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 forkmax ((loop)->forkmax)
+#define forks ((loop)->forks)
 #define fs_2625 ((loop)->fs_2625)
+#define fs_fd ((loop)->fs_fd)
 #define fs_hash ((loop)->fs_hash)
+#define fs_w ((loop)->fs_w)
+#define idleall ((loop)->idleall)
+#define idlecnt ((loop)->idlecnt)
+#define idlemax ((loop)->idlemax)
+#define idles ((loop)->idles)
+#define invoke_cb ((loop)->invoke_cb)
+#define io_blocktime ((loop)->io_blocktime)
+#define iocp ((loop)->iocp)
+#define kqueue_changecnt ((loop)->kqueue_changecnt)
+#define kqueue_changemax ((loop)->kqueue_changemax)
+#define kqueue_changes ((loop)->kqueue_changes)
+#define kqueue_eventmax ((loop)->kqueue_eventmax)
+#define kqueue_events ((loop)->kqueue_events)
+#define kqueue_fd_pid ((loop)->kqueue_fd_pid)
+#define loop_count ((loop)->loop_count)
+#define loop_depth ((loop)->loop_depth)
+#define loop_done ((loop)->loop_done)
+#define mn_now ((loop)->mn_now)
+#define now_floor ((loop)->now_floor)
+#define origflags ((loop)->origflags)
+#define pending_w ((loop)->pending_w)
+#define pendingcnt ((loop)->pendingcnt)
+#define pendingmax ((loop)->pendingmax)
+#define pendingpri ((loop)->pendingpri)
+#define pendings ((loop)->pendings)
+#define periodiccnt ((loop)->periodiccnt)
+#define periodicmax ((loop)->periodicmax)
+#define periodics ((loop)->periodics)
+#define pipe_w ((loop)->pipe_w)
+#define pipe_write_skipped ((loop)->pipe_write_skipped)
+#define pipe_write_wanted ((loop)->pipe_write_wanted)
+#define pollcnt ((loop)->pollcnt)
+#define pollidxmax ((loop)->pollidxmax)
+#define pollidxs ((loop)->pollidxs)
+#define pollmax ((loop)->pollmax)
+#define polls ((loop)->polls)
+#define port_eventmax ((loop)->port_eventmax)
+#define port_events ((loop)->port_events)
+#define postfork ((loop)->postfork)
+#define preparecnt ((loop)->preparecnt)
+#define preparemax ((loop)->preparemax)
+#define prepares ((loop)->prepares)
+#define release_cb ((loop)->release_cb)
+#define rfeedcnt ((loop)->rfeedcnt)
+#define rfeedmax ((loop)->rfeedmax)
+#define rfeeds ((loop)->rfeeds)
+#define rtmn_diff ((loop)->rtmn_diff)
 #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 sigfd_w ((loop)->sigfd_w)
+#define timeout_blocktime ((loop)->timeout_blocktime)
+#define timercnt ((loop)->timercnt)
+#define timermax ((loop)->timermax)
+#define timers ((loop)->timers)
 #define userdata ((loop)->userdata)
-#define release_cb ((loop)->release_cb)
-#define acquire_cb ((loop)->acquire_cb)
-#define invoke_cb ((loop)->invoke_cb)
+#define vec_eo ((loop)->vec_eo)
+#define vec_max ((loop)->vec_max)
+#define vec_ri ((loop)->vec_ri)
+#define vec_ro ((loop)->vec_ro)
+#define vec_wi ((loop)->vec_wi)
+#define vec_wo ((loop)->vec_wo)
 #else
 #undef EV_WRAP_H
-#undef now_floor
-#undef mn_now
-#undef rtmn_diff
-#undef io_blocktime
-#undef timeout_blocktime
-#undef backend
+#undef acquire_cb
 #undef activecnt
-#undef loop_done
+#undef anfdmax
+#undef anfds
+#undef async_pending
+#undef asynccnt
+#undef asyncmax
+#undef asyncs
+#undef backend
 #undef backend_fd
-#undef backend_fudge
+#undef backend_mintime
 #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 checkcnt
+#undef checkmax
+#undef checks
+#undef cleanupcnt
+#undef cleanupmax
+#undef cleanups
 #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 epoll_eperms
+#undef epoll_eventmax
+#undef epoll_events
+#undef evpipe
 #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 fdchangemax
+#undef fdchanges
 #undef forkcnt
-#undef cleanups
-#undef cleanupmax
-#undef cleanupcnt
-#undef async_pending
-#undef asyncs
-#undef asyncmax
-#undef asynccnt
-#undef fs_fd
-#undef fs_w
+#undef forkmax
+#undef forks
 #undef fs_2625
+#undef fs_fd
 #undef fs_hash
+#undef fs_w
+#undef idleall
+#undef idlecnt
+#undef idlemax
+#undef idles
+#undef invoke_cb
+#undef io_blocktime
+#undef iocp
+#undef kqueue_changecnt
+#undef kqueue_changemax
+#undef kqueue_changes
+#undef kqueue_eventmax
+#undef kqueue_events
+#undef kqueue_fd_pid
+#undef loop_count
+#undef loop_depth
+#undef loop_done
+#undef mn_now
+#undef now_floor
+#undef origflags
+#undef pending_w
+#undef pendingcnt
+#undef pendingmax
+#undef pendingpri
+#undef pendings
+#undef periodiccnt
+#undef periodicmax
+#undef periodics
+#undef pipe_w
+#undef pipe_write_skipped
+#undef pipe_write_wanted
+#undef pollcnt
+#undef pollidxmax
+#undef pollidxs
+#undef pollmax
+#undef polls
+#undef port_eventmax
+#undef port_events
+#undef postfork
+#undef preparecnt
+#undef preparemax
+#undef prepares
+#undef release_cb
+#undef rfeedcnt
+#undef rfeedmax
+#undef rfeeds
+#undef rtmn_diff
 #undef sig_pending
-#undef nosigmask
 #undef sigfd
-#undef sigfd_w
 #undef sigfd_set
-#undef origflags
-#undef loop_count
-#undef loop_depth
+#undef sigfd_w
+#undef timeout_blocktime
+#undef timercnt
+#undef timermax
+#undef timers
 #undef userdata
-#undef release_cb
-#undef acquire_cb
-#undef invoke_cb
+#undef vec_eo
+#undef vec_max
+#undef vec_ri
+#undef vec_ro
+#undef vec_wi
+#undef vec_wo
 #endif
diff --git a/src/util/verto/verto-k5ev.c b/src/util/verto/verto-k5ev.c
index a3a5265..74fa368 100644
--- a/src/util/verto/verto-k5ev.c
+++ b/src/util/verto/verto-k5ev.c
@@ -36,6 +36,7 @@
 #include <verto.h>
 #include <verto-module.h>
 #include "rename.h"
+#define EV_API_STATIC 1
 #define EV_STANDALONE 1
 /* Avoid using clock_gettime, which would create a dependency on librt. */
 #define EV_USE_MONOTONIC 0


More information about the cvs-krb5 mailing list