libev/ev.c

3799 lines
83 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
*
2010-01-26 04:19:37 +00:00
* Copyright (c) 2007,2008,2009,2010 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:
*
* 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.
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
#ifdef __cplusplus
extern "C" {
#endif
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
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
2009-06-29 04:41:34 +00:00
# elif !defined(EV_USE_CLOCK_SYSCALL)
# 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 <math.h>
#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
#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
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 */
#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] */
2009-07-19 03:49:04 +00:00
#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! :) */
2009-07-19 06:35:25 +00:00
# define EV_NSIG 65
2009-07-19 03:49:04 +00:00
#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
2008-05-31 03:13:26 +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
# include <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
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
# ifndef _WIN32
# include <sys/select.h>
# endif
#endif
#if EV_USE_INOTIFY
2008-10-13 23:20:12 +00:00
# include <sys/utsname.h>
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
2008-04-06 12:45:58 +00:00
# ifdef __cplusplus
extern "C" {
# endif
int (eventfd) (unsigned int initval, int flags);
2008-04-06 12:45:58 +00:00
# ifdef __cplusplus
}
# endif
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
# ifdef __cplusplus
extern "C" {
# endif
int signalfd (int fd, const sigset_t *mask, int flags);
struct signalfd_siginfo
{
uint32_t ssi_signo;
char pad[128 - sizeof (uint32_t)];
};
# ifdef __cplusplus
}
# endif
2009-07-19 01:36:34 +00:00
#endif
2009-08-26 17:31:20 +00:00
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
/*
* 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.
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
* Better solutions welcome.
*/
#define TIME_EPSILON 0.0001220703125 /* 1/8192 */
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) */
2007-12-14 18:22:30 +00:00
#if __GNUC__ >= 4
2007-11-02 11:02:23 +00:00
# define expect(expr,value) __builtin_expect ((expr),(value))
2007-12-08 14:27:38 +00:00
# define noinline __attribute__ ((noinline))
2007-11-02 11:02:23 +00:00
#else
# define expect(expr,value) (expr)
# define noinline
2008-04-06 14:34:50 +00:00
# if __STDC_VERSION__ < 199901L && __GNUC__ < 2
2007-12-08 14:27:38 +00:00
# define inline
# endif
2007-11-02 11:02:23 +00:00
#endif
#define expect_false(expr) expect ((expr) != 0, 0)
#define expect_true(expr) expect ((expr) != 0, 1)
2007-12-08 14:27:38 +00:00
#define inline_size static inline
2010-03-16 00:20:16 +00:00
#if EV_FEATURE_CODE
2007-12-08 14:27:38 +00:00
# define inline_speed static inline
2010-03-16 00:20:16 +00:00
#else
# define inline_speed static noinline
2007-12-08 14:27:38 +00:00
#endif
2007-11-02 11:02:23 +00:00
2009-07-08 04:29:31 +00:00
#define NUMPRI (EV_MAXPRI - EV_MINPRI + 1)
#if EV_MINPRI == EV_MAXPRI
# define ABSPRI(w) (((W)w), 0)
#else
# define ABSPRI(w) (((W)w)->priority - EV_MINPRI)
#endif
2007-11-02 20:05:05 +00:00
2007-12-07 16:44:10 +00:00
#define EMPTY /* required for microsofts broken pseudo-c compiler */
2007-11-12 20:03:39 +00:00
#define EMPTY2(a,b) /* used to suppress some warnings */
typedef ev_watcher *W;
typedef ev_watcher_list *WL;
typedef ev_watcher_time *WT;
2008-05-02 08:08:45 +00:00
#define ev_active(w) ((W)(w))->active
2008-05-02 08:07:37 +00:00
#define ev_at(w) ((WT)(w))->at
2009-02-06 20:17:43 +00:00
#if EV_USE_REALTIME
2007-12-22 07:03:31 +00:00
/* sig_atomic_t is used to avoid per-thread variables or locking but still */
/* giving it a reasonably high chance of working on typical architetcures */
2009-02-06 20:17:43 +00:00
static EV_ATOMIC_T have_realtime; /* did clock_gettime (CLOCK_REALTIME) work? */
#endif
#if EV_USE_MONOTONIC
2008-01-31 13:10:56 +00:00
static EV_ATOMIC_T have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */
2007-12-23 04:45:51 +00:00
#endif
2007-11-04 00:24:16 +00:00
2009-08-19 23:44:51 +00:00
#ifndef EV_FD_TO_WIN32_HANDLE
# define EV_FD_TO_WIN32_HANDLE(fd) _get_osfhandle (fd)
#endif
#ifndef EV_WIN32_HANDLE_TO_FD
2010-01-07 06:49:31 +00:00
# define EV_WIN32_HANDLE_TO_FD(handle) _open_osfhandle (handle, 0)
2009-08-19 23:44:51 +00:00
#endif
#ifndef EV_WIN32_CLOSE_FD
# define EV_WIN32_CLOSE_FD(fd) close (fd)
#endif
#ifdef _WIN32
2007-11-11 02:05:20 +00:00
# include "ev_win32.c"
#endif
2007-11-05 16:42:15 +00:00
2007-11-03 22:31:11 +00:00
/*****************************************************************************/
2007-11-03 21:58:51 +00:00
2010-03-09 08:55:03 +00:00
#if EV_AVOID_STDIO
static void noinline
ev_printerr (const char *msg)
{
write (STDERR_FILENO, msg, strlen (msg));
}
#endif
2007-11-06 00:52:32 +00:00
static void (*syserr_cb)(const char *msg);
2007-11-06 00:10:04 +00:00
2007-11-26 20:33:58 +00:00
void
ev_set_syserr_cb (void (*cb)(const char *msg))
2007-11-06 00:10:04 +00:00
{
syserr_cb = cb;
}
2007-11-26 20:33:58 +00:00
static void noinline
2008-10-29 06:32:48 +00:00
ev_syserr (const char *msg)
2007-11-06 00:10:04 +00:00
{
2007-11-06 00:52:32 +00:00
if (!msg)
msg = "(libev) system error";
2007-11-06 00:10:04 +00:00
if (syserr_cb)
2007-11-06 00:52:32 +00:00
syserr_cb (msg);
2007-11-06 00:10:04 +00:00
else
{
2010-03-09 08:46:16 +00:00
#if EV_AVOID_STDIO
2010-03-09 08:55:03 +00:00
const char *err = strerror (errno);
ev_printerr (msg);
ev_printerr (": ");
ev_printerr (err);
ev_printerr ("\n");
2010-03-09 08:46:16 +00:00
#else
2007-11-06 00:52:32 +00:00
perror (msg);
2010-03-09 08:46:16 +00:00
#endif
2007-11-06 00:10:04 +00:00
abort ();
}
}
2008-04-09 22:07:50 +00:00
static void *
ev_realloc_emul (void *ptr, long size)
{
2010-03-09 09:00:59 +00:00
#if __GLIBC__
return realloc (ptr, size);
#else
2008-04-09 22:07:50 +00:00
/* some systems, notably openbsd and darwin, fail to properly
2010-03-09 09:02:03 +00:00
* implement realloc (x, 0) (as required by both ansi c-89 and
2008-04-09 22:07:50 +00:00
* the single unix specification, so work around them here.
*/
2010-03-09 08:58:22 +00:00
2008-04-09 22:07:50 +00:00
if (size)
return realloc (ptr, size);
free (ptr);
return 0;
2010-03-09 09:00:59 +00:00
#endif
2008-04-09 22:07:50 +00:00
}
static void *(*alloc)(void *ptr, long size) = ev_realloc_emul;
2007-11-06 00:10:04 +00:00
2007-11-26 20:33:58 +00:00
void
ev_set_allocator (void *(*cb)(void *ptr, long size))
2007-11-06 00:10:04 +00:00
{
alloc = cb;
}
2007-11-27 19:41:52 +00:00
inline_speed void *
ev_realloc (void *ptr, long size)
2007-11-06 00:10:04 +00:00
{
2008-04-09 22:07:50 +00:00
ptr = alloc (ptr, size);
2007-11-06 00:10:04 +00:00
if (!ptr && size)
{
2010-03-09 08:46:16 +00:00
#if EV_AVOID_STDIO
2010-03-09 08:55:03 +00:00
ev_printerr ("libev: memory allocation failed, aborting.\n");
2010-03-09 08:46:16 +00:00
#else
fprintf (stderr, "libev: cannot allocate %ld bytes, aborting.", size);
2010-03-09 08:46:16 +00:00
#endif
2007-11-06 00:10:04 +00:00
abort ();
}
return ptr;
}
#define ev_malloc(size) ev_realloc (0, (size))
#define ev_free(ptr) ev_realloc ((ptr), 0)
/*****************************************************************************/
2009-07-10 19:10:19 +00:00
/* set in reify when reification needed */
#define EV_ANFD_REIFY 1
2009-04-25 14:12:48 +00:00
/* file descriptor info structure */
2007-11-03 22:31:11 +00:00
typedef struct
{
2007-11-05 20:19:00 +00:00
WL head;
2009-04-25 14:12:48 +00:00
unsigned char events; /* the events watched for */
2009-07-10 19:10:19 +00:00
unsigned char reify; /* flag set when this ANFD needs reification (EV_ANFD_REIFY, EV__IOFDSET) */
2009-04-25 14:12:48 +00:00
unsigned char emask; /* the epoll backend stores the actual kernel mask in here */
2008-10-29 06:32:48 +00:00
unsigned char unused;
#if EV_USE_EPOLL
2009-04-25 14:12:48 +00:00
unsigned int egen; /* generation counter to counter epoll bugs */
2008-10-29 06:32:48 +00:00
#endif
#if EV_SELECT_IS_WINSOCKET
SOCKET handle;
#endif
2007-11-03 22:31:11 +00:00
} ANFD;
2007-11-03 21:58:51 +00:00
2009-04-25 14:12:48 +00:00
/* stores the pending event set for a given watcher */
2007-11-03 22:31:11 +00:00
typedef struct
{
W w;
2009-04-25 14:12:48 +00:00
int events; /* the pending event set for the given watcher */
2007-11-03 22:31:11 +00:00
} ANPENDING;
2007-11-03 21:58:51 +00:00
#if EV_USE_INOTIFY
2008-05-09 13:57:00 +00:00
/* hash table entry per inotify-id */
typedef struct
{
WL head;
} ANFS;
#endif
2008-05-09 13:57:00 +00:00
/* Heap Entry */
#if EV_HEAP_CACHE_AT
2009-04-25 14:12:48 +00:00
/* a heap element */
2008-05-09 13:57:00 +00:00
typedef struct {
ev_tstamp at;
2008-05-09 15:52:13 +00:00
WT w;
2008-05-09 13:57:00 +00:00
} ANHE;
2008-05-21 23:25:21 +00:00
#define ANHE_w(he) (he).w /* access watcher, read-write */
#define ANHE_at(he) (he).at /* access cached at, read-only */
#define ANHE_at_cache(he) (he).at = (he).w->at /* update at from watcher */
2008-05-09 13:57:00 +00:00
#else
2009-04-25 14:12:48 +00:00
/* a heap element */
2008-05-09 13:57:00 +00:00
typedef WT ANHE;
2008-05-21 23:25:21 +00:00
#define ANHE_w(he) (he)
#define ANHE_at(he) (he)->at
#define ANHE_at_cache(he)
2008-05-09 13:57:00 +00:00
#endif
#if EV_MULTIPLICITY
2007-11-04 00:24:16 +00:00
2007-11-09 15:30:59 +00:00
struct ev_loop
{
2007-11-10 03:19:21 +00:00
ev_tstamp ev_rt_now;
#define ev_rt_now ((loop)->ev_rt_now)
2007-11-09 15:30:59 +00:00
#define VAR(name,decl) decl;
#include "ev_vars.h"
#undef VAR
};
#include "ev_wrap.h"
2007-11-15 09:19:42 +00:00
static struct ev_loop default_loop_struct;
struct ev_loop *ev_default_loop_ptr;
2007-11-04 00:24:16 +00:00
2007-11-03 22:31:11 +00:00
#else
2007-11-04 00:24:16 +00:00
2007-11-10 03:19:21 +00:00
ev_tstamp ev_rt_now;
2007-11-09 15:30:59 +00:00
#define VAR(name,decl) static decl;
#include "ev_vars.h"
#undef VAR
2007-11-15 09:19:42 +00:00
static int ev_default_loop_ptr;
2007-11-04 00:24:16 +00:00
2007-11-03 21:58:51 +00:00
#endif
2010-03-16 00:20:16 +00:00
#if EV_FEATURE_API
2009-07-10 19:10:19 +00:00
# define EV_RELEASE_CB if (expect_false (release_cb)) release_cb (EV_A)
# define EV_ACQUIRE_CB if (expect_false (acquire_cb)) acquire_cb (EV_A)
2009-07-10 00:36:21 +00:00
# define EV_INVOKE_PENDING invoke_cb (EV_A)
#else
2009-07-10 19:10:19 +00:00
# define EV_RELEASE_CB (void)0
# define EV_ACQUIRE_CB (void)0
2009-07-10 00:36:21 +00:00
# define EV_INVOKE_PENDING ev_invoke_pending (EV_A)
#endif