+int
+ev_version_minor (void)
+{
+ return EV_VERSION_MINOR;
+}
+
+/* return true if we are running with elevated privileges and should ignore env variables */
+int inline_size
+enable_secure (void)
+{
+#ifdef _WIN32
+ return 0;
+#else
+ return getuid () != geteuid ()
+ || getgid () != getegid ();
+#endif
+}
+
+unsigned int
+ev_supported_backends (void)
+{
+ unsigned int flags = 0;
+
+ if (EV_USE_PORT ) flags |= EVBACKEND_PORT;
+ if (EV_USE_KQUEUE) flags |= EVBACKEND_KQUEUE;
+ if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL;
+ if (EV_USE_POLL ) flags |= EVBACKEND_POLL;
+ if (EV_USE_SELECT) flags |= EVBACKEND_SELECT;
+
+ return flags;
+}
+
+unsigned int
+ev_recommended_backends (void)
+{
+ unsigned int flags = ev_supported_backends ();
+
+#ifndef __NetBSD__
+ /* kqueue is borked on everything but netbsd apparently */
+ /* it usually doesn't work correctly on anything but sockets and pipes */
+ flags &= ~EVBACKEND_KQUEUE;
+#endif
+#ifdef __APPLE__
+ // 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)