libev/ev.c

4511 lines
108 KiB
C
Raw Normal View History

2007-10-31 14:44:14 +00:00
/*
2007-11-01 13:11:11 +00:00
* libev event processing core, watcher management
*
2012-04-02 23:14:40 +00:00
* Copyright (c) 2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann <libev@schmorp.de>
2007-10-31 14:44:14 +00:00
* All rights reserved.
*
2007-12-25 07:05:45 +00:00
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
2011-02-16 08:02:49 +00:00
*
2007-12-25 07:05:45 +00:00
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
2011-02-16 08:02:49 +00:00
*
2007-12-25 07:05:45 +00:00
* 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.
2011-02-16 08:02:49 +00:00
*
2007-12-25 07:05:45 +00:00
* 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.
2007-10-31 14:44:14 +00:00
*
2007-12-25 07:05:45 +00:00
* 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.
2007-10-31 14:44:14 +00:00
*/
2007-11-10 03:36:15 +00:00
2008-04-06 09:53:16 +00:00
/* this big block deduces configuration from config.h */
2007-11-04 18:15:16 +00:00
#ifndef EV_STANDALONE
2007-11-23 11:32:21 +00:00
# ifdef EV_CONFIG_H
# include EV_CONFIG_H
# else
# include "config.h"
# endif
2007-11-04 18:29:44 +00:00
2011-02-20 02:56:23 +00:00
#if HAVE_FLOOR
# ifndef EV_USE_FLOOR
# define EV_USE_FLOOR 1
# endif
#endif
2008-11-20 00:35:10 +00:00
# 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
2012-04-02 20:12:16 +00:00
# elif !defined EV_USE_CLOCK_SYSCALL
2009-06-29 04:41:34 +00:00
# define EV_USE_CLOCK_SYSCALL 0
2008-11-20 00:35:10 +00:00
# endif
2007-11-04 18:29:44 +00:00
# if HAVE_CLOCK_GETTIME
# ifndef EV_USE_MONOTONIC
# define EV_USE_MONOTONIC 1
# endif
# ifndef EV_USE_REALTIME
2009-02-06 20:17:43 +00:00
# define EV_USE_REALTIME 0
# endif
2007-11-18 01:25:23 +00:00
# else
# ifndef EV_USE_MONOTONIC
# define EV_USE_MONOTONIC 0
# endif
# ifndef EV_USE_REALTIME
# define EV_USE_REALTIME 0
# endif
2007-11-04 18:29:44 +00:00
# endif
2010-04-02 21:03:45 +00:00
# if HAVE_NANOSLEEP
# ifndef EV_USE_NANOSLEEP
# define EV_USE_NANOSLEEP EV_FEATURE_OS
2007-12-22 05:47:56 +00:00
# endif
2010-04-02 21:03:45 +00:00
# else
# undef EV_USE_NANOSLEEP
# define EV_USE_NANOSLEEP 0
2007-12-22 05:47:56 +00:00
# endif
2010-04-02 21:03:45 +00:00
# if HAVE_SELECT && HAVE_SYS_SELECT_H
# ifndef EV_USE_SELECT
2010-03-16 00:43:22 +00:00
# define EV_USE_SELECT EV_FEATURE_BACKENDS
2007-11-18 02:17:57 +00:00
# endif
2010-04-02 21:03:45 +00:00
# else
# undef EV_USE_SELECT
# define EV_USE_SELECT 0
2007-11-04 18:29:44 +00:00
# endif
2010-04-02 21:03:45 +00:00
# if HAVE_POLL && HAVE_POLL_H
# ifndef EV_USE_POLL
2010-03-16 00:43:22 +00:00
# define EV_USE_POLL EV_FEATURE_BACKENDS
2007-11-18 02:17:57 +00:00
# endif
2010-04-02 21:03:45 +00:00
# else
# undef EV_USE_POLL
# define EV_USE_POLL 0
2007-11-04 18:29:44 +00:00
# endif
2007-11-18 02:17:57 +00:00
2010-04-02 21:03:45 +00:00
# if HAVE_EPOLL_CTL && HAVE_SYS_EPOLL_H
# ifndef EV_USE_EPOLL
2010-03-16 00:43:22 +00:00
# define EV_USE_EPOLL EV_FEATURE_BACKENDS
2007-11-18 02:17:57 +00:00
# endif
2010-04-02 21:03:45 +00:00
# else
# undef EV_USE_EPOLL
# define EV_USE_EPOLL 0
2007-11-04 18:29:44 +00:00
# endif
2007-11-18 02:17:57 +00:00
2010-04-02 21:03:45 +00:00
# if HAVE_KQUEUE && HAVE_SYS_EVENT_H
# ifndef EV_USE_KQUEUE
2010-03-16 00:43:22 +00:00
# define EV_USE_KQUEUE EV_FEATURE_BACKENDS
2007-11-18 02:17:57 +00:00
# endif
2010-04-02 21:03:45 +00:00
# else
# undef EV_USE_KQUEUE
# define EV_USE_KQUEUE 0
2007-11-04 18:29:44 +00:00
# endif
2007-11-18 02:17:57 +00:00
2010-04-02 21:03:45 +00:00
# if HAVE_PORT_H && HAVE_PORT_CREATE
# ifndef EV_USE_PORT
2010-03-16 00:43:22 +00:00
# define EV_USE_PORT EV_FEATURE_BACKENDS
2007-11-18 02:17:57 +00:00
# endif
2010-04-02 21:03:45 +00:00
# else
# undef EV_USE_PORT
# define EV_USE_PORT 0
2007-11-16 01:33:53 +00:00
# endif
2010-04-02 21:03:45 +00:00
# if HAVE_INOTIFY_INIT && HAVE_SYS_INOTIFY_H
# ifndef EV_USE_INOTIFY
2010-03-16 00:43:22 +00:00
# define EV_USE_INOTIFY EV_FEATURE_OS
# endif
2010-04-02 21:03:45 +00:00
# else
# undef EV_USE_INOTIFY
# define EV_USE_INOTIFY 0
# endif
2010-04-02 21:03:45 +00:00
# if HAVE_SIGNALFD && HAVE_SYS_SIGNALFD_H
# ifndef EV_USE_SIGNALFD
2010-03-16 00:43:22 +00:00
# define EV_USE_SIGNALFD EV_FEATURE_OS
2009-07-19 01:36:34 +00:00
# endif
2010-04-02 21:03:45 +00:00
# else
# undef EV_USE_SIGNALFD
# define EV_USE_SIGNALFD 0
2009-07-19 01:36:34 +00:00
# endif
2010-04-02 21:03:45 +00:00
# if HAVE_EVENTFD
# ifndef EV_USE_EVENTFD
2010-03-16 00:43:22 +00:00
# define EV_USE_EVENTFD EV_FEATURE_OS
2008-04-06 09:53:16 +00:00
# endif
2010-04-02 21:03:45 +00:00
# else
# undef EV_USE_EVENTFD
# define EV_USE_EVENTFD 0
2008-04-06 09:53:16 +00:00
# endif
2008-05-22 02:44:57 +00:00
#endif
2007-10-31 14:44:14 +00:00
#include <stdlib.h>
2009-11-18 10:25:22 +00:00
#include <string.h>
2007-10-31 00:24:16 +00:00
#include <fcntl.h>
2007-10-31 13:57:34 +00:00
#include <stddef.h>
#include <stdio.h>
2007-10-30 23:10:33 +00:00
#include <assert.h>
#include <errno.h>
2007-10-31 19:07:43 +00:00
#include <sys/types.h>
#include <time.h>
2010-01-26 04:19:37 +00:00
#include <limits.h>
2007-11-06 16:09:37 +00:00
#include <signal.h>
#ifdef EV_H
# include EV_H
#else
# include "ev.h"
#endif
2012-02-04 17:57:55 +00:00
#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>
2007-11-03 09:19:58 +00:00
# include <sys/wait.h>
# include <unistd.h>
#else
2008-06-19 06:53:49 +00:00
# include <io.h>
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# ifndef EV_SELECT_IS_WINSOCKET
# define EV_SELECT_IS_WINSOCKET 1
# endif
2010-03-09 08:55:03 +00:00
# undef EV_AVOID_STDIO
2007-11-03 09:19:58 +00:00
#endif
2010-07-09 20:55:14 +00:00
/* OS X, in its infinite idiocy, actually HARDCODES
* a limit of 1024 into their select. Where people have brains,
* OS X engineers apparently have a vacuum. Or maybe they were
* ordered to have a vacuum, or they do anything for money.
* This might help. Or not.
*/
#define _DARWIN_UNLIMITED_SELECT 1
2008-04-06 09:53:16 +00:00
/* this block tries to deduce configuration from header-defined symbols and defaults */
2007-11-02 11:02:23 +00:00
2009-07-19 03:49:04 +00:00
/* try to deduce the maximum number of signals on this platform */
2012-04-02 20:12:16 +00:00
#if defined EV_NSIG
2009-07-19 03:49:04 +00:00
/* use what's provided */
2012-04-02 20:12:16 +00:00
#elif defined NSIG
2009-07-19 03:49:04 +00:00
# define EV_NSIG (NSIG)
2012-04-02 20:12:16 +00:00
#elif defined _NSIG
2009-07-19 03:49:04 +00:00
# define EV_NSIG (_NSIG)
2012-04-02 20:12:16 +00:00
#elif defined SIGMAX
2009-07-19 03:49:04 +00:00
# define EV_NSIG (SIGMAX+1)
2012-04-02 20:12:16 +00:00
#elif defined SIG_MAX
2009-07-19 03:49:04 +00:00
# define EV_NSIG (SIG_MAX+1)
2012-04-02 20:12:16 +00:00
#elif defined _SIG_MAX
2009-07-19 03:49:04 +00:00
# define EV_NSIG (_SIG_MAX+1)
2012-04-02 20:12:16 +00:00
#elif defined MAXSIG
2009-07-19 03:49:04 +00:00
# define EV_NSIG (MAXSIG+1)
2012-04-02 20:12:16 +00:00
#elif defined MAX_SIG
2009-07-19 03:49:04 +00:00
# define EV_NSIG (MAX_SIG+1)
2012-04-02 20:12:16 +00:00
#elif defined SIGARRAYSIZE
# define EV_NSIG (SIGARRAYSIZE) /* Assume ary[SIGARRAYSIZE] */
2012-04-02 20:12:16 +00:00
#elif defined _sys_nsig
2009-07-19 03:49:04 +00:00
# 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! :) */
2009-07-19 06:35:25 +00:00
# define EV_NSIG 65
2009-07-19 03:49:04 +00:00
#endif
2011-02-20 02:56:23 +00:00
#ifndef EV_USE_FLOOR
# define EV_USE_FLOOR 0
#endif
2008-11-20 00:35:10 +00:00
#ifndef EV_USE_CLOCK_SYSCALL
# if __linux && __GLIBC__ >= 2
2010-03-16 00:20:16 +00:00
# define EV_USE_CLOCK_SYSCALL EV_FEATURE_OS
2008-11-20 00:35:10 +00:00
# else
# define EV_USE_CLOCK_SYSCALL 0
# endif
#endif
#ifndef EV_USE_MONOTONIC
2012-04-02 20:12:16 +00:00
# if defined _POSIX_MONOTONIC_CLOCK && _POSIX_MONOTONIC_CLOCK >= 0
2010-03-16 00:20:16 +00:00
# define EV_USE_MONOTONIC EV_FEATURE_OS
2008-05-31 03:13:26 +00:00
# else
# define EV_USE_MONOTONIC 0
# endif
2007-11-01 13:33:12 +00:00
#endif
2007-11-16 01:33:53 +00:00
#ifndef EV_USE_REALTIME
2009-02-06 20:17:43 +00:00
# define EV_USE_REALTIME !EV_USE_CLOCK_SYSCALL
2007-11-16 01:33:53 +00:00
#endif
2007-12-22 05:47:56 +00:00
#ifndef EV_USE_NANOSLEEP
2008-05-31 03:13:26 +00:00
# if _POSIX_C_SOURCE >= 199309L
2010-03-16 00:20:16 +00:00
# define EV_USE_NANOSLEEP EV_FEATURE_OS
2008-05-31 03:13:26 +00:00
# else
# define EV_USE_NANOSLEEP 0
# endif
2007-12-22 05:47:56 +00:00
#endif
#ifndef EV_USE_SELECT
2010-03-16 00:20:16 +00:00
# define EV_USE_SELECT EV_FEATURE_BACKENDS
#endif
2007-11-04 18:15:16 +00:00
#ifndef EV_USE_POLL
2007-11-12 00:39:45 +00:00
# ifdef _WIN32
# define EV_USE_POLL 0
# else
2010-03-16 00:20:16 +00:00
# define EV_USE_POLL EV_FEATURE_BACKENDS
2007-11-12 00:39:45 +00:00
# endif
#endif
#ifndef EV_USE_EPOLL
2008-04-06 09:53:16 +00:00
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4))
2010-03-16 00:20:16 +00:00
# define EV_USE_EPOLL EV_FEATURE_BACKENDS
2008-04-06 09:53:16 +00:00
# else
# define EV_USE_EPOLL 0
# endif
#endif
#ifndef EV_USE_KQUEUE
# define EV_USE_KQUEUE 0
#endif
2007-11-16 01:33:53 +00:00
#ifndef EV_USE_PORT
# define EV_USE_PORT 0
2007-11-02 11:02:23 +00:00
#endif
#ifndef EV_USE_INOTIFY
2008-04-06 09:53:16 +00:00
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4))
2010-03-16 00:20:16 +00:00
# define EV_USE_INOTIFY EV_FEATURE_OS
2008-04-06 09:53:16 +00:00
# else
# define EV_USE_INOTIFY 0
# endif
#endif
2007-11-27 19:23:31 +00:00
#ifndef EV_PID_HASHSIZE
2010-03-16 00:20:16 +00:00
# define EV_PID_HASHSIZE EV_FEATURE_DATA ? 16 : 1
2007-11-27 19:23:31 +00:00
#endif
#ifndef EV_INOTIFY_HASHSIZE
2010-03-16 00:20:16 +00:00
# define EV_INOTIFY_HASHSIZE EV_FEATURE_DATA ? 16 : 1
#endif
2008-04-06 09:53:16 +00:00
#ifndef EV_USE_EVENTFD
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))
2010-03-16 00:20:16 +00:00
# define EV_USE_EVENTFD EV_FEATURE_OS
2008-04-06 09:53:16 +00:00
# else
# define EV_USE_EVENTFD 0
# endif
#endif
2009-07-19 01:36:34 +00:00
#ifndef EV_USE_SIGNALFD
2009-08-26 17:31:20 +00:00
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 7))
2010-03-16 00:20:16 +00:00
# define EV_USE_SIGNALFD EV_FEATURE_OS
2009-07-19 01:36:34 +00:00
# else
# define EV_USE_SIGNALFD 0
# endif
#endif
2008-05-21 23:30:52 +00:00
#if 0 /* debugging */
2008-05-22 02:44:57 +00:00
# define EV_VERIFY 3
2008-05-21 23:30:52 +00:00
# define EV_USE_4HEAP 1
# define EV_HEAP_CACHE_AT 1
#endif
2008-05-22 02:44:57 +00:00
#ifndef EV_VERIFY
2010-03-16 00:20:16 +00:00
# define EV_VERIFY (EV_FEATURE_API ? 1 : 0)
2008-05-22 02:44:57 +00:00
#endif
2008-05-09 15:52:13 +00:00
#ifndef EV_USE_4HEAP
2010-03-16 00:20:16 +00:00
# define EV_USE_4HEAP EV_FEATURE_DATA
2008-05-09 15:52:13 +00:00
#endif
#ifndef EV_HEAP_CACHE_AT
2010-03-16 00:20:16 +00:00
# define EV_HEAP_CACHE_AT EV_FEATURE_DATA
2008-05-09 15:52:13 +00:00
#endif
2009-06-29 04:41:34 +00:00
/* 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
2012-04-22 10:14:20 +00:00
# include <sys/syscall.h>
2009-06-29 04:41:34 +00:00
# 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
2008-04-06 09:53:16 +00:00
/* this block fixes any misconfiguration where we know we run into trouble otherwise */
2007-11-02 11:02:23 +00:00
2010-01-24 12:31:55 +00:00
#ifdef _AIX
/* AIX has a completely broken poll.h header */
# undef EV_USE_POLL
# define EV_USE_POLL 0
#endif
2007-11-02 11:02:23 +00:00
#ifndef CLOCK_MONOTONIC
# undef EV_USE_MONOTONIC
# define EV_USE_MONOTONIC 0
#endif
2007-11-01 09:05:33 +00:00
#ifndef CLOCK_REALTIME
2007-11-02 11:02:23 +00:00
# undef EV_USE_REALTIME
2007-11-01 09:05:33 +00:00
# define EV_USE_REALTIME 0
#endif
2007-11-02 11:02:23 +00:00
#if !EV_STAT_ENABLE
2007-12-14 18:22:30 +00:00
# undef EV_USE_INOTIFY
# define EV_USE_INOTIFY 0
#endif
2007-12-22 05:47:56 +00:00
#if !EV_USE_NANOSLEEP
2011-01-30 19:05:40 +00:00
/* hp-ux has it in sys/time.h, which we unconditionally include above */
2012-04-02 20:12:16 +00:00
# if !defined _WIN32 && !defined __hpux
2007-12-22 05:47:56 +00:00
# include <sys/select.h>
# endif
#endif
#if EV_USE_INOTIFY
2008-11-03 14:27:06 +00:00
# include <sys/statfs.h>
# include <sys/inotify.h>
2008-10-01 18:50:03 +00:00
/* 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
2007-12-14 18:22:30 +00:00
#if EV_SELECT_IS_WINSOCKET
# include <winsock.h>
#endif
2008-04-06 09:53:16 +00:00
#if EV_USE_EVENTFD
/* our minimum requirement is glibc 2.7 which has the stub, but not the header */
2008-04-06 12:44:49 +00:00
# include <stdint.h>
2009-07-19 01:36:34 +00:00
# ifndef EFD_NONBLOCK
# define EFD_NONBLOCK O_NONBLOCK
# endif
# ifndef EFD_CLOEXEC
2009-07-29 09:36:05 +00:00
# ifdef O_CLOEXEC
# define EFD_CLOEXEC O_CLOEXEC
# else
# define EFD_CLOEXEC 02000000
# endif
2009-07-19 01:36:34 +00:00
# endif
2010-10-22 09:24:11 +00:00
EV_CPP(extern "C") int (eventfd) (unsigned int initval, int flags);
2008-04-06 09:53:16 +00:00
#endif
2009-07-19 01:36:34 +00:00
#if EV_USE_SIGNALFD
2009-08-26 17:31:20 +00:00
/* 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
2010-10-22 09:24:11 +00:00
EV_CPP (extern "C") int signalfd (int fd, const sigset_t *mask, int flags);
2009-08-26 17:31:20 +00:00
struct signalfd_siginfo
{
uint32_t ssi_signo;
char pad[128 - sizeof (uint32_t)];
};
2009-07-19 01:36:34 +00:00
#endif
2007-11-02 11:02:23 +00:00
/**/
2008-05-22 02:44:57 +00:00
#if EV_VERIFY >= 3
2010-03-16 20:39:29 +00:00
# define EV_FREQUENT_CHECK ev_verify (EV_A)
2008-05-21 23:25:21 +00:00
#else
# define EV_FREQUENT_CHECK do { } while (0)
#endif
2007-12-11 04:31:55 +00:00
/*
2011-02-20 02:56:23 +00:00
* This is used to work around floating point rounding problems.
2007-12-11 15:06:50 +00:00
* This value is good at least till the year 4000.
2007-12-11 04:31:55 +00:00
*/
2011-02-20 02:56:23 +00:00
#define MIN_INTERVAL 0.0001220703125 /* 1/2**13, good till 4000 */
/*#define MIN_INTERVAL 0.00000095367431640625 /* 1/2**20, good till 2200 */
2007-12-11 04:31:55 +00:00
2007-10-30 23:10:33 +00:00
#define MIN_TIMEJUMP 1. /* minimum timejump that gets detected (if monotonic clock available) */
2007-11-16 01:54:25 +00:00
#define MAX_BLOCKTIME 59.743 /* never wait longer than this time (to detect time jumps) */
2010-10-15 22:44:41 +00:00
#define EV_TV_SET(tv,t) do { tv.tv_sec = (long)t; tv.tv_usec = (long)((t - tv.tv_sec) * 1e6); } while (0)
2010-10-15 22:48:25 +00:00
#define EV_TS_SET(ts,t) do { ts.tv_sec = (long)t; ts.tv_nsec = (long)((t - ts.tv_sec) * 1e9); } while (0)
2010-10-15 22:44:41 +00:00
2011-08-04 13:57:16 +00:00
/* 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
*
2012-01-18 12:13:14 +00:00
* Copyright (©) 2009-2012 Marc Alexander Lehmann <libecb@schmorp.de>
2011-08-04 13:57:16 +00:00
* 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.
*/
#ifndef ECB_H
#define ECB_H
#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
#else
#include <inttypes.h>
#endif
2011-06-19 17:55:13 +00:00
/* many compilers define _GNUC_ to some versions but then only implement
* what their idiot authors think are the "more important" extensions,
2011-08-04 13:57:16 +00:00
* causing enormous grief in return for some better fake benchmark numbers.
2011-06-19 17:55:13 +00:00
* 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.
*/
#ifndef ECB_GCC_VERSION
2012-04-02 20:22:30 +00:00
#if !defined __GNUC_MINOR__ || defined __INTEL_COMPILER || defined __SUNPRO_C || defined __SUNPRO_CC || defined __llvm__ || defined __clang__
2011-06-19 17:55:13 +00:00
#define ECB_GCC_VERSION(major,minor) 0
#else
#define ECB_GCC_VERSION(major,minor) (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
#endif
#endif
2011-08-04 13:57:16 +00:00
/*****************************************************************************/
/* 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 */
2012-02-04 17:57:55 +00:00
#if ECB_NO_THREADS
# define ECB_NO_SMP 1
#endif
2011-08-04 13:57:16 +00:00
#if ECB_NO_THREADS || ECB_NO_SMP
2011-08-04 14:47:48 +00:00
#define ECB_MEMORY_FENCE do { } while (0)
2007-11-02 11:02:23 +00:00
#endif
2011-07-20 00:40:14 +00:00
#ifndef ECB_MEMORY_FENCE
2012-04-02 20:22:30 +00:00
#if ECB_GCC_VERSION(2,5) || defined __INTEL_COMPILER || (__llvm__ && __GNUC__) || __SUNPRO_C >= 0x5110 || __SUNPRO_CC >= 0x5110
2012-01-18 12:44:32 +00:00
#if __i386 || __i386__
2011-07-20 00:40:14 +00:00
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("lock; orb $0, -1(%%esp)" : : : "memory")
2011-08-04 13:57:16 +00:00
#define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE /* non-lock xchg might be enough */
#define ECB_MEMORY_FENCE_RELEASE do { } while (0) /* unlikely to change in future cpus */
2012-01-18 12:44:32 +00:00
#elif __amd64 || __amd64__ || __x86_64 || __x86_64__
2011-07-20 00:40:14 +00:00
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("mfence" : : : "memory")
#define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("lfence" : : : "memory")
2011-08-04 13:57:16 +00:00
#define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("sfence") /* play safe - not needed in any current cpu */
2011-08-04 14:37:49 +00:00
#elif __powerpc__ || __ppc__ || __powerpc64__ || __ppc64__
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("sync" : : : "memory")
2012-04-02 20:22:30 +00:00
#elif defined __ARM_ARCH_6__ || defined __ARM_ARCH_6J__ \
|| defined __ARM_ARCH_6K__ || defined __ARM_ARCH_6ZK__
2012-03-30 17:43:55 +00:00
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("mcr p15,0,%0,c7,c10,5" : : "r" (0) : "memory")
2012-04-02 20:22:30 +00:00
#elif defined __ARM_ARCH_7__ || defined __ARM_ARCH_7A__ \
|| defined __ARM_ARCH_7M__ || defined __ARM_ARCH_7R__
2011-08-04 14:49:27 +00:00
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("dmb" : : : "memory")
2012-01-18 12:44:32 +00:00
#elif __sparc || __sparc__
2012-01-18 12:51:41 +00:00
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad | #StoreStore | #StoreLoad | " : : : "memory")
2012-01-27 22:28:49 +00:00
#define ECB_MEMORY_FENCE_ACQUIRE __asm__ __volatile__ ("membar #LoadStore | #LoadLoad" : : : "memory")
2012-01-18 12:51:41 +00:00
#define ECB_MEMORY_FENCE_RELEASE __asm__ __volatile__ ("membar #LoadStore | #StoreStore")
2012-04-02 20:22:30 +00:00
#elif defined __s390__ || defined __s390x__
2012-01-27 22:28:49 +00:00
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("bcr 15,0" : : : "memory")
2012-04-02 20:22:30 +00:00
#elif defined __mips__
2012-02-22 01:53:00 +00:00
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("sync" : : : "memory")
2012-04-12 04:10:15 +00:00
#elif defined __alpha__
#define ECB_MEMORY_FENCE __asm__ __volatile__ ("mb" : : : "memory")
2011-07-20 00:40:14 +00:00
#endif
#endif
#endif
#ifndef ECB_MEMORY_FENCE
2012-04-02 20:22:30 +00:00
#if ECB_GCC_VERSION(4,4) || defined __INTEL_COMPILER || defined __clang__
2011-07-20 00:40:14 +00:00
#define ECB_MEMORY_FENCE __sync_synchronize ()
2011-08-04 14:37:49 +00:00
/*#define ECB_MEMORY_FENCE_ACQUIRE ({ char dummy = 0; __sync_lock_test_and_set (&dummy, 1); }) */
/*#define ECB_MEMORY_FENCE_RELEASE ({ char dummy = 1; __sync_lock_release (&dummy ); }) */
2011-08-03 15:31:23 +00:00
#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 ()
2012-04-02 20:22:30 +00:00
#elif defined _WIN32
2011-07-29 12:17:26 +00:00
#include <WinNT.h>
2011-08-04 13:57:16 +00:00
#define ECB_MEMORY_FENCE MemoryBarrier () /* actually just xchg on x86... scary */
2012-01-18 12:13:14 +00:00
#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 ()
2012-03-23 19:06:08 +00:00
#elif __xlC__
2012-03-24 19:38:51 +00:00
#define ECB_MEMORY_FENCE __sync ()
2011-07-20 00:40:14 +00:00
#endif
#endif
#ifndef ECB_MEMORY_FENCE
2011-08-04 14:37:49 +00:00
#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
2011-07-20 00:40:14 +00:00
2012-04-02 20:22:30 +00:00
#if !defined ECB_MEMORY_FENCE_ACQUIRE && defined ECB_MEMORY_FENCE
2011-07-20 00:40:14 +00:00
#define ECB_MEMORY_FENCE_ACQUIRE ECB_MEMORY_FENCE
2011-08-04 14:37:49 +00:00
#endif
2012-04-02 20:22:30 +00:00
#if !defined ECB_MEMORY_FENCE_RELEASE && defined ECB_MEMORY_FENCE
2011-07-20 00:40:14 +00:00
#define ECB_MEMORY_FENCE_RELEASE ECB_MEMORY_FENCE
#endif
2011-08-04 13:57:16 +00:00
/*****************************************************************************/
#define ECB_C99 (__STDC_VERSION__ >= 199901L)
#if __cplusplus
#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_function_ ecb_inline
2011-06-19 17:55:13 +00:00
#if ECB_GCC_VERSION(3,1)
#define ecb_attribute(attrlist) __attribute__(attrlist)
#define ecb_is_constant(expr) __builtin_constant_p (expr)
#define ecb_expect(expr,value) __builtin_expect ((expr),(value))
#define ecb_prefetch(addr,rw,locality) __builtin_prefetch (addr, rw, locality)
#else
#define ecb_attribute(attrlist)
#define ecb_is_constant(expr) 0
#define ecb_expect(expr,value) (expr)
#define ecb_prefetch(addr,rw,locality)
#endif
2011-08-04 13:57:16 +00:00
/* no emulation for ecb_decltype */
#if ECB_GCC_VERSION(4,5)
#define ecb_decltype(x) __decltype(x)
#elif ECB_GCC_VERSION(3,0)
#define ecb_decltype(x) __typeof(x)
#endif
2011-06-19 17:55:13 +00:00
#define ecb_noinline ecb_attribute ((__noinline__))
#define ecb_noreturn ecb_attribute ((__noreturn__))
#define ecb_unused ecb_attribute ((__unused__))
#define ecb_const ecb_attribute ((__const__))
#define ecb_pure ecb_attribute ((__pure__))
#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)
2011-08-04 13:57:16 +00:00
/* 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)
/* 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_ int ecb_ctz32 (uint32_t x) ecb_const;
ecb_function_ int
ecb_ctz32 (uint32_t x)
{
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