|
|
|
/*
|
|
|
|
* libev event processing core, watcher management
|
|
|
|
*
|
|
|
|
* Copyright (c) 2007-2019 Marc Alexander Lehmann <libev@schmorp.de>
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without modifica-
|
|
|
|
* tion, are permitted provided that the following conditions are met:
|
|
|
|
*
|
|
|
|
* 1. Redistributions of source code must retain the above copyright notice,
|
|
|
|
* this list of conditions and the following disclaimer.
|
|
|
|
*
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MER-
|
|
|
|
* CHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
|
|
|
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPE-
|
|
|
|
* CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
|
|
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
|
|
|
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTH-
|
|
|
|
* ERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
|
|
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* the GNU General Public License ("GPL") version 2 or any later version,
|
|
|
|
* in which case the provisions of the GPL are applicable instead of
|
|
|
|
* the above. If you wish to allow the use of your version of this file
|
|
|
|
* only under the terms of the GPL and not to allow others to use your
|
|
|
|
* version of this file under the BSD license, indicate your decision
|
|
|
|
* by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL. If you do not delete the
|
|
|
|
* provisions above, a recipient may use your version of this file under
|
|
|
|
* either the BSD or the GPL.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* this big block deduces configuration from config.h */
|
|
|
|
#ifndef EV_STANDALONE
|
|
|
|
# ifdef EV_CONFIG_H
|
|
|
|
# include EV_CONFIG_H
|
|
|
|
# else
|
|
|
|
# include "config.h"
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if HAVE_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
|
|
|
|
# ifndef EV_USE_REALTIME
|
|
|
|
# define EV_USE_REALTIME 0
|
|
|
|
# endif
|
|
|
|
# ifndef EV_USE_MONOTONIC
|
|
|
|
# define EV_USE_MONOTONIC 1
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
# elif !defined EV_USE_CLOCK_SYSCALL
|
|
|
|
# define EV_USE_CLOCK_SYSCALL 0
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if HAVE_CLOCK_GETTIME
|
|
|
|
# ifndef EV_USE_MONOTONIC
|
|
|
|
# define EV_USE_MONOTONIC 1
|
|
|
|
# endif
|
|
|
|
# ifndef EV_USE_REALTIME
|
|
|
|
# define EV_USE_REALTIME 0
|
|
|
|
# endif
|
|
|
|
# else
|
|
|
|
# ifndef EV_USE_MONOTONIC
|
|
|
|
# define EV_USE_MONOTONIC 0
|
|
|
|
# endif
|
|
|
|
# ifndef EV_USE_REALTIME
|
|
|
|
# define EV_USE_REALTIME 0
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if HAVE_NANOSLEEP
|
|
|
|
# ifndef EV_USE_NANOSLEEP
|
|
|
|
# define EV_USE_NANOSLEEP EV_FEATURE_OS
|
|
|
|
# endif
|
|
|
|
# else
|
|
|
|
# undef EV_USE_NANOSLEEP
|
|
|
|
# define EV_USE_NANOSLEEP 0
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if HAVE_SELECT && HAVE_SYS_SELECT_H
|
|
|
|
# ifndef EV_USE_SELECT
|
|
|
|
# define EV_USE_SELECT EV_FEATURE_BACKENDS
|
|
|
|
# endif
|
|
|
|
# else
|
|
|
|
# undef EV_USE_SELECT
|
|
|
|
# define EV_USE_SELECT 0
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if HAVE_POLL && HAVE_POLL_H
|
|
|
|
# ifndef EV_USE_POLL
|
|
|
|
# define EV_USE_POLL EV_FEATURE_BACKENDS
|
|
|
|
# endif
|
|
|
|
# else
|
|
|
|
# undef EV_USE_POLL
|
|
|
|
# define EV_USE_POLL 0
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if HAVE_EPOLL_CTL && HAVE_SYS_EPOLL_H
|
|
|
|
# ifndef EV_USE_EPOLL
|
|
|
|
# define EV_USE_EPOLL EV_FEATURE_BACKENDS
|
|
|
|
# endif
|
|
|
|
# else
|
|
|
|
# undef EV_USE_EPOLL
|
|
|
|
# define EV_USE_EPOLL 0
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if HAVE_LINUX_AIO_ABI_H
|
|
|
|
# ifndef EV_USE_LINUXAIO
|
|
|
|
# define EV_USE_LINUXAIO EV_FEATURE_BACKENDS
|
|
|
|
# endif
|
|
|
|
# else
|
|
|
|
# undef EV_USE_LINUXAIO
|
|
|
|
# define EV_USE_LINUXAIO 0
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if HAVE_KQUEUE && HAVE_SYS_EVENT_H
|
|
|
|
# ifndef EV_USE_KQUEUE
|
|
|
|
# define EV_USE_KQUEUE EV_FEATURE_BACKENDS
|
|
|
|
# endif
|
|
|
|
# else
|
|
|
|
# undef EV_USE_KQUEUE
|
|
|
|
# define EV_USE_KQUEUE 0
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if HAVE_PORT_H && HAVE_PORT_CREATE
|
|
|
|
# ifndef EV_USE_PORT
|
|
|
|
# define EV_USE_PORT EV_FEATURE_BACKENDS
|
|
|
|
# endif
|
|
|
|
# else
|
|
|
|
# undef EV_USE_PORT
|
|
|
|
# define EV_USE_PORT 0
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if HAVE_INOTIFY_INIT && HAVE_SYS_INOTIFY_H
|
|
|
|
# ifndef EV_USE_INOTIFY
|
|
|
|
# define EV_USE_INOTIFY EV_FEATURE_OS
|
|
|
|
# endif
|
|
|
|
# else
|
|
|
|
# undef EV_USE_INOTIFY
|
|
|
|
# define EV_USE_INOTIFY 0
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if HAVE_SIGNALFD && HAVE_SYS_SIGNALFD_H
|
|
|
|
# ifndef EV_USE_SIGNALFD
|
|
|
|
# define EV_USE_SIGNALFD EV_FEATURE_OS
|
|
|
|
# endif
|
|
|
|
# else
|
|
|
|
# undef EV_USE_SIGNALFD
|
|
|
|
# define EV_USE_SIGNALFD 0
|
|
|
|
# endif
|
|
|
|
|
|
|
|
# if HAVE_EVENTFD
|
|
|
|
# ifndef EV_USE_EVENTFD
|
|
|
|
# define EV_USE_EVENTFD EV_FEATURE_OS
|
|
|
|
# endif
|
|
|
|
# else
|
|
|
|
# undef EV_USE_EVENTFD
|
|
|
|
# define EV_USE_EVENTFD 0
|
|
|
|
# endif
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* OS X, in its infinite idiocy, actually HARDCODES
|
|
|
|
* a limit of 1024 into their select. Where people have brains,
|
|
|
|
* OS X engineers apparently have a vacuum. Or maybe they were
|
|
|
|
* ordered to have a vacuum, or they do anything for money.
|
|
|
|
* This might help. Or not.
|
|
|
|
* Note that this must be defined early, as other include files
|
|
|
|
* will rely on this define as well.
|
|
|
|
*/
|
|
|
|
#define _DARWIN_UNLIMITED_SELECT 1
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <time.h>
|
|
|
|
#include <limits.h>
|
|
|
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
|
|
|
#ifdef EV_H
|
|
|
|
# include EV_H
|
|
|
|
#else
|
|
|
|
# include "ev.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#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>
|
|
|
|
# include <sys/wait.h>
|
|
|
|
# include <unistd.h>
|
|
|
|
#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
|
|
|
|
# endif
|
|
|
|
# undef EV_AVOID_STDIO
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* this block tries to deduce configuration from header-defined symbols and defaults */
|
|
|
|
|
|
|
|
/* try to deduce the maximum number of signals on this platform */
|
|
|
|
#if defined EV_NSIG
|
|
|
|
/* use what's provided */
|
|
|
|
#elif defined NSIG
|
|
|
|
# define EV_NSIG (NSIG)
|
|
|
|
#elif defined _NSIG
|
|
|
|
# define EV_NSIG (_NSIG)
|
|
|
|
#elif defined SIGMAX
|
|
|
|
# define EV_NSIG (SIGMAX+1)
|
|
|
|
#elif defined SIG_MAX
|
|
|
|
# define EV_NSIG (SIG_MAX+1)
|
|
|
|
#elif defined _SIG_MAX
|
|
|
|
# define EV_NSIG (_SIG_MAX+1)
|
|
|
|
#elif defined MAXSIG
|
|
|
|
# define EV_NSIG (MAXSIG+1)
|
|
|
|
#elif defined MAX_SIG
|
|
|
|
# define EV_NSIG (MAX_SIG+1)
|
|
|
|
#elif defined SIGARRAYSIZE
|
|
|
|
# define EV_NSIG (SIGARRAYSIZE) /* Assume ary[SIGARRAYSIZE] */
|
|
|
|
#elif defined _sys_nsig
|
|
|
|
# define EV_NSIG (_sys_nsig) /* Solaris 2.5 */
|
|
|
|
#else
|
|
|
|
# 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 && __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
|
|
|
|
# define EV_USE_MONOTONIC EV_FEATURE_OS
|
|
|
|
# else
|
|
|
|
# define EV_USE_MONOTONIC 0
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_USE_REALTIME
|
|
|
|
# define EV_USE_REALTIME !EV_USE_CLOCK_SYSCALL
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_USE_NANOSLEEP
|
|
|
|
# if _POSIX_C_SOURCE >= 199309L
|
|
|
|
# define EV_USE_NANOSLEEP EV_FEATURE_OS
|
|
|
|
# else
|
|
|
|
# define EV_USE_NANOSLEEP 0
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_USE_SELECT
|
|
|
|
# define EV_USE_SELECT EV_FEATURE_BACKENDS
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_USE_POLL
|
|
|
|
# ifdef _WIN32
|
|
|
|
# define EV_USE_POLL 0
|
|
|
|
# else
|
|
|
|
# define EV_USE_POLL EV_FEATURE_BACKENDS
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_USE_EPOLL
|
|
|
|
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4))
|
|
|
|
# define EV_USE_EPOLL EV_FEATURE_BACKENDS
|
|
|
|
# else
|
|
|
|
# define EV_USE_EPOLL 0
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_USE_KQUEUE
|
|
|
|
# define EV_USE_KQUEUE 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_USE_PORT
|
|
|
|
# define EV_USE_PORT 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_USE_LINUXAIO
|
|
|
|
# define EV_USE_LINUXAIO 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_USE_INOTIFY
|
|
|
|
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4))
|
|
|
|
# define EV_USE_INOTIFY EV_FEATURE_OS
|
|
|
|
# else
|
|
|
|
# define EV_USE_INOTIFY 0
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_PID_HASHSIZE
|
|
|
|
# define EV_PID_HASHSIZE EV_FEATURE_DATA ? 16 : 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_INOTIFY_HASHSIZE
|
|
|
|
# define EV_INOTIFY_HASHSIZE EV_FEATURE_DATA ? 16 : 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_USE_EVENTFD
|
|
|
|
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))
|
|
|
|
# define EV_USE_EVENTFD EV_FEATURE_OS
|
|
|
|
# else
|
|
|
|
# define EV_USE_EVENTFD 0
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_USE_SIGNALFD
|
|
|
|
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))
|
|
|
|
# define EV_USE_SIGNALFD EV_FEATURE_OS
|
|
|
|
# else
|
|
|
|
# define EV_USE_SIGNALFD 0
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if 0 /* debugging */
|
|
|
|
# define EV_VERIFY 3
|
|
|
|
# define EV_USE_4HEAP 1
|
|
|
|
# define EV_HEAP_CACHE_AT 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_VERIFY
|
|
|
|
# define EV_VERIFY (EV_FEATURE_API ? 1 : 0)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_USE_4HEAP
|
|
|
|
# define EV_USE_4HEAP EV_FEATURE_DATA
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef EV_HEAP_CACHE_AT
|
|
|
|
# define EV_HEAP_CACHE_AT EV_FEATURE_DATA
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
|
|
#if EV_USE_LINUXAIO
|
|
|
|
# include <linux/aio_abi.h> /* probably only needed for aio_context_t */
|
|
|
|
#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 <sys/syscall.h>
|
|
|
|
# ifdef SYS_clock_gettime
|
|
|
|
# define clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts))
|
|
|
|
# undef EV_USE_MONOTONIC
|
|
|
|
# define EV_USE_MONOTONIC 1
|
|
|
|
# else
|
|
|
|
# undef EV_USE_CLOCK_SYSCALL
|
|
|
|
# define EV_USE_CLOCK_SYSCALL 0
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* this block fixes any misconfiguration where we know we run into trouble otherwise */
|
|
|
|
|
|
|
|
#ifndef CLOCK_MONOTONIC
|
|
|
|
# undef EV_USE_MONOTONIC
|
|
|
|
# define EV_USE_MONOTONIC 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef CLOCK_REALTIME
|
|
|
|
# undef EV_USE_REALTIME
|
|
|
|
# define EV_USE_REALTIME 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !EV_STAT_ENABLE
|
|
|
|
# undef EV_USE_INOTIFY
|
|
|
|
# define EV_USE_INOTIFY 0
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if !EV_USE_NANOSLEEP
|
|
|
|
/* hp-ux has it in sys/time.h, which we unconditionally include above */
|
|
|
|
# if !defined _WIN32 && !defined __hpux
|
|
|
|
# include <sys/select.h>
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EV_USE_LINUXAIO
|
|
|
|
# include <sys/syscall.h>
|
|
|
|
# if !SYS_io_getevents
|
|
|
|
# undef EV_USE_LINUXAIO
|
|
|
|
# define EV_USE_LINUXAIO 0
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EV_USE_INOTIFY
|
|
|
|
# include <sys/statfs.h>
|
|
|
|
# include <sys/inotify.h>
|
|
|
|
/* some very old inotify.h headers don't have IN_DONT_FOLLOW */
|
|
|
|
# ifndef IN_DONT_FOLLOW
|
|
|
|
# undef EV_USE_INOTIFY
|
|
|
|
# define EV_USE_INOTIFY 0
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EV_USE_EVENTFD
|
|
|
|
/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
|
|
|
|
# include <stdint.h>
|
|
|
|
# ifndef EFD_NONBLOCK
|
|
|
|
# define EFD_NONBLOCK O_NONBLOCK
|
|
|
|
# endif
|
|
|
|
# ifndef EFD_CLOEXEC
|
|
|
|
# ifdef O_CLOEXEC
|
|
|
|
# define EFD_CLOEXEC O_CLOEXEC
|
|
|
|
# else
|
|
|
|
# define EFD_CLOEXEC 02000000
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
EV_CPP(extern "C") int (eventfd) (unsigned int initval, int flags);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if EV_USE_SIGNALFD
|
|
|
|
/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
|
|
|
|
# include <stdint.h>
|
|
|
|
# ifndef SFD_NONBLOCK
|
|
|
|
# define SFD_NONBLOCK O_NONBLOCK
|
|
|
|
# endif
|
|
|
|
# ifndef SFD_CLOEXEC
|
|
|
|
# ifdef O_CLOEXEC
|
|
|
|
# define SFD_CLOEXEC O_CLOEXEC
|
|
|
|
# else
|
|
|
|
# define SFD_CLOEXEC 02000000
|
|
|
|
# endif
|
|
|
|
# endif
|
|
|
|
EV_CPP (extern "C") int signalfd (int fd, const sigset_t *mask, int flags);
|
|
|
|
|
|
|
|
struct signalfd_siginfo
|
|
|
|
{
|
|
|
|
uint32_t ssi_signo;
|
|
|
|
char pad[128 - sizeof (uint32_t)];
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/**/
|
|
|
|
|
|
|
|
#if EV_VERIFY >= 3
|
|
|
|
# define EV_FREQUENT_CHECK ev_verify (EV_A)
|
|
|
|
#else
|
|
|
|
# define EV_FREQUENT_CHECK do { } while (0)
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is used to work around floating point rounding problems.
|
|
|
|
* This value is good at least till the year 4000.
|
|
|
|
*/
|
|
|
|
#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) */
|
|
|
|
|
|
|
|
#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)
|
|
|
|
|
|
|
|
/* 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@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
|
|
|
|
#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)
|
|
|
|
#define ECB_CPP14 (__cplusplus >= 201402L)
|
|
|
|
#define ECB_CPP17 (__cplusplus >= 201703L)
|
|
|
|
|
|
|
|
#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)
|
|
|
|
#define ECB_C17 (ECB_STDC_VERSION >= 201710L)
|
|
|
|
|
|
|
|
#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__ ("" : : : "memory")
|
|
|
|
#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__ ("" : : : "memory")
|
|
|
|
#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__ |