+/* return true if we are running with elevated privileges and should ignore env variables */
+int inline_size
+enable_secure (void)
+{
+#ifdef _WIN32
+ return 0;
+#else
+ return getuid () != geteuid ()
+ || getgid () != getegid ();
+#endif
+}
+
+unsigned int
+ev_supported_backends (void)
+{
+ unsigned int flags = 0;
+
+ if (EV_USE_PORT ) flags |= EVBACKEND_PORT;
+ if (EV_USE_KQUEUE) flags |= EVBACKEND_KQUEUE;
+ if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL;
+ if (EV_USE_POLL ) flags |= EVBACKEND_POLL;
+ if (EV_USE_SELECT) flags |= EVBACKEND_SELECT;
+
+ return flags;
+}
+
+unsigned int
+ev_recommended_backends (void)
+{
+ unsigned int flags = ev_supported_backends ();
+
+#ifndef __NetBSD__
+ /* kqueue is borked on everything but netbsd apparently */
+ /* it usually doesn't work correctly on anything but sockets and pipes */
+ flags &= ~EVBACKEND_KQUEUE;
+#endif
+#ifdef __APPLE__
+ // flags &= ~EVBACKEND_KQUEUE; for documentation
+ flags &= ~EVBACKEND_POLL;
+#endif
+
+ return flags;
+}
+
+unsigned int
+ev_embeddable_backends (void)
+{
+ return EVBACKEND_EPOLL
+ | EVBACKEND_KQUEUE
+ | EVBACKEND_PORT;
+}
+
+unsigned int
+ev_backend (EV_P)
+{
+ return backend;
+}
+
+static void
+loop_init (EV_P_ unsigned int flags)
+{
+ if (!backend)
+ {
+#if EV_USE_MONOTONIC
+ {
+ struct timespec ts;
+ if (!clock_gettime (CLOCK_MONOTONIC, &ts))
+ have_monotonic = 1;
+ }
+#endif
+
+ ev_rt_now = ev_time ();
+ mn_now = get_clock ();
+ now_floor = mn_now;
+ rtmn_diff = ev_rt_now - mn_now;
+
+ if (!(flags & EVFLAG_NOENV)
+ && !enable_secure ()
+ && getenv ("LIBEV_FLAGS"))
+ flags = atoi (getenv ("LIBEV_FLAGS"));
+
+ if (!(flags & 0x0000ffffUL))
+ flags |= ev_recommended_backends ();
+
+ backend = 0;
+#if EV_USE_PORT
+ if (!backend && (flags & EVBACKEND_PORT )) backend = port_init (EV_A_ flags);
+#endif
+#if EV_USE_KQUEUE
+ if (!backend && (flags & EVBACKEND_KQUEUE)) backend = kqueue_init (EV_A_ flags);
+#endif
+#if EV_USE_EPOLL
+ if (!backend && (flags & EVBACKEND_EPOLL )) backend = epoll_init (EV_A_ flags);
+#endif
+#if EV_USE_POLL
+ if (!backend && (flags & EVBACKEND_POLL )) backend = poll_init (EV_A_ flags);
+#endif
+#if EV_USE_SELECT
+ if (!backend && (flags & EVBACKEND_SELECT)) backend = select_init (EV_A_ flags);
+#endif
+
+ ev_init (&sigev, sigcb);
+ ev_set_priority (&sigev, EV_MAXPRI);
+ }
+}
+
+static void
+loop_destroy (EV_P)
+{
+ int i;
+
+#if EV_USE_PORT
+ if (backend == EVBACKEND_PORT ) port_destroy (EV_A);
+#endif
+#if EV_USE_KQUEUE
+ if (backend == EVBACKEND_KQUEUE) kqueue_destroy (EV_A);
+#endif
+#if EV_USE_EPOLL
+ if (backend == EVBACKEND_EPOLL ) epoll_destroy (EV_A);
+#endif
+#if EV_USE_POLL
+ if (backend == EVBACKEND_POLL ) poll_destroy (EV_A);
+#endif
+#if EV_USE_SELECT
+ if (backend == EVBACKEND_SELECT) select_destroy (EV_A);
+#endif
+
+ for (i = NUMPRI; i--; )
+ array_free (pending, [i]);
+
+ /* have to use the microsoft-never-gets-it-right macro */
+ array_free (fdchange, EMPTY0);
+ array_free (timer, EMPTY0);
+#if EV_PERIODIC_ENABLE
+ array_free (periodic, EMPTY0);
+#endif
+ array_free (idle, EMPTY0);
+ array_free (prepare, EMPTY0);
+ array_free (check, EMPTY0);
+
+ backend = 0;
+}
+
+static void
+loop_fork (EV_P)
+{
+#if EV_USE_PORT
+ if (backend == EVBACKEND_PORT ) port_fork (EV_A);
+#endif
+#if EV_USE_KQUEUE
+ if (backend == EVBACKEND_KQUEUE) kqueue_fork (EV_A);
+#endif
+#if EV_USE_EPOLL
+ if (backend == EVBACKEND_EPOLL ) epoll_fork (EV_A);
+#endif
+
+ if (ev_is_active (&sigev))
+ {
+ /* default loop */
+
+ ev_ref (EV_A);
+ ev_io_stop (EV_A_ &sigev);
+ close (sigpipe [0]);
+ close (sigpipe [1]);
+
+ while (pipe (sigpipe))
+ syserr ("(libev) error creating pipe");
+
+ siginit (EV_A);
+ }
+
+ postfork = 0;
+}
+
+#if EV_MULTIPLICITY
+struct ev_loop *
+ev_loop_new (unsigned int flags)
+{
+ struct ev_loop *loop = (struct ev_loop *)ev_malloc (sizeof (struct ev_loop));
+
+ memset (loop, 0, sizeof (struct ev_loop));
+
+ loop_init (EV_A_ flags);
+
+ if (ev_backend (EV_A))
+ return loop;
+
+ return 0;
+}
+
+void
+ev_loop_destroy (EV_P)
+{
+ loop_destroy (EV_A);
+ ev_free (loop);
+}
+
+void
+ev_loop_fork (EV_P)
+{
+ postfork = 1;
+}
+
+#endif
+
+#if EV_MULTIPLICITY
+struct ev_loop *
+ev_default_loop_init (unsigned int flags)
+#else
+int
+ev_default_loop (unsigned int flags)
+#endif
+{
+ if (sigpipe [0] == sigpipe [1])
+ if (pipe (sigpipe))
+ return 0;
+
+ if (!ev_default_loop_ptr)
+ {
+#if EV_MULTIPLICITY
+ struct ev_loop *loop = ev_default_loop_ptr = &default_loop_struct;
+#else
+ ev_default_loop_ptr = 1;
+#endif
+
+ loop_init (EV_A_ flags);
+
+ if (ev_backend (EV_A))
+ {
+ siginit (EV_A);
+
+#ifndef _WIN32
+ ev_signal_init (&childev, childcb, SIGCHLD);
+ ev_set_priority (&childev, EV_MAXPRI);
+ ev_signal_start (EV_A_ &childev);
+ ev_unref (EV_A); /* child watcher should not keep loop alive */
+#endif
+ }
+ else
+ ev_default_loop_ptr = 0;
+ }
+
+ return ev_default_loop_ptr;
+}
+
+void
+ev_default_destroy (void)
+{
+#if EV_MULTIPLICITY
+ struct ev_loop *loop = ev_default_loop_ptr;
+#endif
+
+#ifndef _WIN32
+ ev_ref (EV_A); /* child watcher */
+ ev_signal_stop (EV_A_ &childev);
+#endif
+
+ ev_ref (EV_A); /* signal watcher */
+ ev_io_stop (EV_A_ &sigev);
+
+ close (sigpipe [0]); sigpipe [0] = 0;
+ close (sigpipe [1]); sigpipe [1] = 0;
+
+ loop_destroy (EV_A);
+}
+
+void
+ev_default_fork (void)
+{
+#if EV_MULTIPLICITY
+ struct ev_loop *loop = ev_default_loop_ptr;
+#endif
+
+ if (backend)
+ postfork = 1;
+}
+
+/*****************************************************************************/
+
+int inline_size
+any_pending (EV_P)
+{
+ int pri;
+
+ for (pri = NUMPRI; pri--; )
+ if (pendingcnt [pri])
+ return 1;
+
+ return 0;
+}
+
+void inline_speed
+call_pending (EV_P)
+{
+ int pri;
+
+ for (pri = NUMPRI; pri--; )
+ while (pendingcnt [pri])
+ {
+ ANPENDING *p = pendings [pri] + --pendingcnt [pri];
+
+ if (expect_true (p->w))
+ {
+ assert (("non-pending watcher on pending list", p->w->pending));
+
+ p->w->pending = 0;
+ EV_CB_INVOKE (p->w, p->events);
+ }
+ }
+}
+
+void inline_size
+timers_reify (EV_P)
+{
+ while (timercnt && ((WT)timers [0])->at <= mn_now)
+ {
+ ev_timer *w = timers [0];
+
+ assert (("inactive timer on timer heap detected", ev_is_active (w)));
+
+ /* first reschedule or stop timer */