libev/ev.c

2346 lines
48 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
*
2007-10-31 14:44:14 +00:00
* Copyright (c) 2007 Marc Alexander Lehmann <libev@schmorp.de>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * 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 COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, 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 OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
2007-11-10 03:36:15 +00:00
#ifdef __cplusplus
extern "C" {
#endif
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
# if HAVE_CLOCK_GETTIME
# ifndef EV_USE_MONOTONIC
# define EV_USE_MONOTONIC 1
# endif
# ifndef EV_USE_REALTIME
# define EV_USE_REALTIME 1
# 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
2007-11-18 02:17:57 +00:00
# ifndef EV_USE_SELECT
# if HAVE_SELECT && HAVE_SYS_SELECT_H
# define EV_USE_SELECT 1
# else
# define EV_USE_SELECT 0
# endif
2007-11-04 18:29:44 +00:00
# endif
2007-11-18 02:17:57 +00:00
# ifndef EV_USE_POLL
# if HAVE_POLL && HAVE_POLL_H
# define EV_USE_POLL 1
# else
# define EV_USE_POLL 0
# endif
2007-11-04 18:29:44 +00:00
# endif
2007-11-18 02:17:57 +00:00
# ifndef EV_USE_EPOLL
# if HAVE_EPOLL_CTL && HAVE_SYS_EPOLL_H
# define EV_USE_EPOLL 1
# else
# define EV_USE_EPOLL 0
# endif
2007-11-04 18:29:44 +00:00
# endif
2007-11-18 02:17:57 +00:00
# ifndef EV_USE_KQUEUE
# if HAVE_KQUEUE && HAVE_SYS_EVENT_H && HAVE_SYS_QUEUE_H
# define EV_USE_KQUEUE 1
# else
# define EV_USE_KQUEUE 0
# endif
2007-11-04 18:29:44 +00:00
# endif
2007-11-18 02:17:57 +00:00
# ifndef EV_USE_PORT
# if HAVE_PORT_H && HAVE_PORT_CREATE
# define EV_USE_PORT 1
# else
# define EV_USE_PORT 0
# endif
2007-11-16 01:33:53 +00:00
# endif
# ifndef EV_USE_INOTIFY
# if HAVE_INOTIFY_INIT && HAVE_SYS_INOTIFY_H
# define EV_USE_INOTIFY 1
# else
# define EV_USE_INOTIFY 0
# endif
# endif
#endif
2007-10-31 14:44:14 +00:00
#include <math.h>
#include <stdlib.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>
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
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# ifndef EV_SELECT_IS_WINSOCKET
# define EV_SELECT_IS_WINSOCKET 1
# endif
2007-11-03 09:19:58 +00:00
#endif
2007-11-02 11:02:23 +00:00
/**/
#ifndef EV_USE_MONOTONIC
2007-11-16 10:37:28 +00:00
# define EV_USE_MONOTONIC 0
2007-11-01 13:33:12 +00:00
#endif
2007-11-16 01:33:53 +00:00
#ifndef EV_USE_REALTIME
2007-11-16 10:37:28 +00:00
# define EV_USE_REALTIME 0
2007-11-16 01:33:53 +00:00
#endif
#ifndef EV_USE_SELECT
# define EV_USE_SELECT 1
#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
# define EV_USE_POLL 1
# endif
#endif
#ifndef EV_USE_EPOLL
# define EV_USE_EPOLL 0
#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
# define EV_USE_INOTIFY 0
#endif
2007-11-27 19:23:31 +00:00
#ifndef EV_PID_HASHSIZE
# if EV_MINIMAL
# define EV_PID_HASHSIZE 1
# else
# define EV_PID_HASHSIZE 16
# endif
#endif
#ifndef EV_INOTIFY_HASHSIZE
# if EV_MINIMAL
# define EV_INOTIFY_HASHSIZE 1
# else
# define EV_INOTIFY_HASHSIZE 16
# endif
#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
#if EV_USE_INOTIFY
# include <sys/inotify.h>
#endif
2007-12-14 18:22:30 +00:00
#if EV_SELECT_IS_WINSOCKET
# include <winsock.h>
#endif
2007-11-02 11:02:23 +00:00
/**/
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-11 04:31:55 +00:00
/*#define CLEANUP_INTERVAL (MAX_BLOCKTIME * 5.) /* how often to try to free memory and re-check fds, TODO */
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
2007-12-08 14:27:38 +00:00
# if __STDC_VERSION__ < 199901L
# 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
#if EV_MINIMAL
# define inline_speed static noinline
#else
# define inline_speed static inline
#endif
2007-11-02 11:02:23 +00:00
2007-11-02 20:05:05 +00:00
#define NUMPRI (EV_MAXPRI - EV_MINPRI + 1)
2007-12-07 16:44:10 +00:00
#define ABSPRI(w) (((W)w)->priority - EV_MINPRI)
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;
2007-11-04 00:24:16 +00:00
static int have_monotonic; /* did clock_gettime (CLOCK_MONOTONIC) work? */
#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
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
2007-11-06 00:52:32 +00:00
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
{
2007-11-06 00:52:32 +00:00
perror (msg);
2007-11-06 00:10:04 +00:00
abort ();
}
}
static void *(*alloc)(void *ptr, long size);
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
{
ptr = alloc ? alloc (ptr, size) : realloc (ptr, size);
2007-11-06 00:10:04 +00:00
if (!ptr && size)
{
fprintf (stderr, "libev: cannot allocate %ld bytes, aborting.", size);
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)
/*****************************************************************************/
2007-11-03 22:31:11 +00:00
typedef struct
{
2007-11-05 20:19:00 +00:00
WL head;
2007-11-03 22:31:11 +00:00
unsigned char events;
unsigned char reify;
#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
2007-11-03 22:31:11 +00:00
typedef struct
{
W w;
int events;
} ANPENDING;
2007-11-03 21:58:51 +00:00
#if EV_USE_INOTIFY
typedef struct
{
WL head;
} ANFS;
#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
2007-10-31 00:32:33 +00:00
/*****************************************************************************/
2007-11-26 20:33:58 +00:00
ev_tstamp
ev_time (void)
{
#if EV_USE_REALTIME
struct timespec ts;
clock_gettime (CLOCK_REALTIME, &ts);
return ts.tv_sec + ts.tv_nsec * 1e-9;
#else
struct timeval tv;
gettimeofday (&tv, 0);
return tv.tv_sec + tv.tv_usec * 1e-6;
#endif
}
ev_tstamp inline_size
get_clock (void)
{
#if EV_USE_MONOTONIC
2007-11-02 11:02:23 +00:00
if (expect_true (have_monotonic))
{
struct timespec ts;
clock_gettime (CLOCK_MONOTONIC, &ts);
return ts.tv_sec + ts.tv_nsec * 1e-9;
}
#endif
return ev_time ();
}
2007-11-10 03:13:50 +00:00
#if EV_MULTIPLICITY
2007-11-03 21:58:51 +00:00
ev_tstamp
ev_now (EV_P)
{
2007-11-10 03:13:50 +00:00
return ev_rt_now;
2007-11-03 21:58:51 +00:00
}
2007-11-10 03:13:50 +00:00
#endif
2007-11-03 21:58:51 +00:00
2007-12-05 13:54:36 +00:00
int inline_size
array_nextsize (int elem, int cur, int cnt)
{
int ncur = cur + 1;
do
ncur <<= 1;
while (cnt > ncur);
/* if size > 4096, round to 4096 - 4 * longs to accomodate malloc overhead */
if (elem * ncur > 4096)
{
ncur *= elem;
ncur = (ncur + elem + 4095 + sizeof (void *) * 4) & ~4095;
ncur = ncur - sizeof (void *) * 4;
ncur /= elem;
}
return ncur;
}
2007-12-09 02:12:43 +00:00
static noinline void *
2007-12-05 13:54:36 +00:00
array_realloc (int elem, void *base, int *cur, int cnt)
{
*cur = array_nextsize (elem, *cur, cnt);
return ev_realloc (base, elem * *cur);
}
2007-11-06 16:51:20 +00:00
#define array_needsize(type,base,cur,cnt,init) \
2007-12-05 13:54:36 +00:00
if (expect_false ((cnt) > (cur))) \
2007-11-06 00:10:04 +00:00
{ \
2007-12-05 13:54:36 +00:00
int ocur_ = (cur); \
(base) = (type *)array_realloc \
(sizeof (type), (base), &(cur), (cnt)); \
init ((base) + (ocur_), (cur) - ocur_); \
}
2007-12-05 13:54:36 +00:00
#if 0
2007-11-06 16:51:20 +00:00
#define array_slim(type,stem) \
2007-11-05 16:42:15 +00:00
if (stem ## max < array_roundsize (stem ## cnt >> 2)) \
{ \
stem ## max = array_roundsize (stem ## cnt >> 1); \
2007-11-06 16:51:20 +00:00
base = (type *)ev_realloc (base, sizeof (type) * (stem ## max));\
2007-11-05 16:42:15 +00:00
fprintf (stderr, "slimmed down " # stem " to %d\n", stem ## max);/*D*/\
}
2007-12-05 13:54:36 +00:00
#endif
2007-11-05 16:42:15 +00:00
2007-11-04 23:29:48 +00:00
#define array_free(stem, idx) \
2007-11-06 00:10:04 +00:00
ev_free (stem ## s idx); stem ## cnt idx = stem ## max idx = 0;
2007-11-04 23:29:48 +00:00
2007-10-31 00:32:33 +00:00
/*****************************************************************************/
void noinline
2007-11-08 21:08:56 +00:00
ev_feed_event (EV_P_ void *w, int revents)
{
2007-11-08 21:08:56 +00:00
W w_ = (W)w;
2007-12-09 02:12:43 +00:00
int pri = ABSPRI (w_);
2007-11-08 21:08:56 +00:00
2007-11-17 02:23:54 +00:00
if (expect_false (w_->pending))
2007-12-09 02:12:43 +00:00
pendings [pri][w_->pending - 1].events |= revents;
else
2007-11-01 09:21:51 +00:00
{
2007-12-09 02:12:43 +00:00
w_->pending = ++pendingcnt [pri];
array_needsize (ANPENDING, pendings [pri], pendingmax [pri], w_->pending, EMPTY2);
pendings [pri][w_->pending - 1].w = w_;
pendings [pri][w_->pending - 1].events = revents;
2007-11-01 09:21:51 +00:00
}
}
2007-12-11 21:04:40 +00:00
void inline_speed
2007-11-03 21:58:51 +00:00
queue_events (EV_P_ W *events, int eventcnt, int type)
2007-10-31 22:16:36 +00:00
{
int i;
for (i = 0; i < eventcnt; ++i)
2007-11-08 21:08:56 +00:00
ev_feed_event (EV_A_ events [i], type);
2007-10-31 22:16:36 +00:00
}
2007-11-26 20:33:58 +00:00
/*****************************************************************************/
void inline_size
anfds_init (ANFD *base, int count)
{
while (count--)
{
base->head = 0;
base->events = EV_NONE;
base->reify = 0;
++base;
}
}
void inline_speed
2007-11-09 15:15:20 +00:00
fd_event (EV_P_ int fd, int revents)
{
ANFD *anfd = anfds + fd;
ev_io *w;
for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next)
{
2007-11-09 15:15:20 +00:00
int ev = w->events & revents;
if (ev)
2007-11-08 21:08:56 +00:00
ev_feed_event (EV_A_ (W)w, ev);
}
}
2007-11-09 15:15:20 +00:00
void
ev_feed_fd_event (EV_P_ int fd, int revents)
{
2007-12-08 14:12:07 +00:00
if (fd >= 0 && fd < anfdmax)
fd_event (EV_A_ fd, revents);
2007-11-09 15:15:20 +00:00
}
void inline_size
2007-11-03 21:58:51 +00:00
fd_reify (EV_P)
{
int i;
2007-10-31 22:16:36 +00:00
for (i = 0; i < fdchangecnt; ++i)
{
int fd = fdchanges [i];
ANFD *anfd = anfds + fd;
ev_io *w;
2007-10-31 22:16:36 +00:00
unsigned char events = 0;
2007-10-31 22:16:36 +00:00
for (w = (ev_io *)anfd->head; w; w = (ev_io *)((WL)w)->next)
events |= (unsigned char)w->events;
2007-10-31 22:16:36 +00:00
#if EV_SELECT_IS_WINSOCKET
if (events)
{
unsigned long argp;
anfd->handle = _get_osfhandle (fd);
assert (("libev only supports socket fds in this configuration", ioctlsocket (anfd->handle, FIONREAD, &argp) == 0));
}
#endif
{
unsigned char o_events = anfd->events;
unsigned char o_reify = anfd->reify;
anfd->reify = 0;
anfd->events = events;
2007-10-31 22:16:36 +00:00
if (o_events != events || o_reify & EV_IOFDSET)
backend_modify (EV_A_ fd, o_events, events);
}
2007-10-31 22:16:36 +00:00
}
fdchangecnt = 0;
}
void inline_size
2007-12-12 05:11:56 +00:00
fd_change (EV_P_ int fd, int flags)
2007-10-31 22:16:36 +00:00
{
2007-12-12 05:11:56 +00:00
unsigned char reify = anfds [fd].reify;
anfds [fd].reify |= flags;
2007-10-31 22:16:36 +00:00
2007-12-12 05:11:56 +00:00
if (expect_true (!reify))
{
++fdchangecnt;
array_needsize (int, fdchanges, fdchangemax, fdchangecnt, EMPTY2);
fdchanges [fdchangecnt - 1] = fd;
}
}
void inline_speed
2007-11-03 21:58:51 +00:00
fd_kill (EV_P_ int fd)
{
ev_io *w;
while ((w = (ev_io *)anfds [fd].head))
{
2007-11-03 21:58:51 +00:00
ev_io_stop (EV_A_ w);
2007-11-08 21:08:56 +00:00
ev_feed_event (EV_A_ (W)w, EV_ERROR | EV_READ | EV_WRITE);
}
}
int inline_size
fd_valid (int fd)
{
#ifdef _WIN32
return _get_osfhandle (fd) != -1;
#else
return fcntl (fd, F_GETFD) != -1;
#endif
}
2007-10-31 17:55:55 +00:00
/* called on EBADF to verify fds */
static void noinline
2007-11-03 21:58:51 +00:00
fd_ebadf (EV_P)
2007-10-31 17:55:55 +00:00
{
int fd;
for (fd = 0; fd < anfdmax; ++fd)
2007-10-31 22:16:36 +00:00
if (anfds [fd].events)
if (!fd_valid (fd) == -1 && errno == EBADF)
2007-11-03 21:58:51 +00:00
fd_kill (EV_A_ fd);
}
/* called on ENOMEM in select/poll to kill some fds and retry */
static void noinline
2007-11-03 21:58:51 +00:00
fd_enomem (EV_P)
{
int fd;
for (fd = anfdmax; fd--; )
if (anfds [fd].events)
{
2007-11-03 21:58:51 +00:00
fd_kill (EV_A_ fd);
return;
}
2007-10-31 17:55:55 +00:00
}
/* usually called after fork if backend needs to re-arm all fds from scratch */
static void noinline
fd_rearm_all (EV_P)
{
int fd;
for (fd = 0; fd < anfdmax; ++fd)
if (anfds [fd].events)
{
anfds [fd].events = 0;
fd_change (EV_A_ fd, EV_IOFDSET | 1);
}
}
2007-10-31 00:32:33 +00:00
/*****************************************************************************/
void inline_speed
2007-11-04 00:24:16 +00:00
upheap (WT *heap, int k)
{
2007-11-04 00:24:16 +00:00
WT w = heap [k];
2007-12-11 21:04:40 +00:00
while (k)
{
2007-12-11 21:04:40 +00:00
int p = (k - 1) >> 1;
if (heap [p]->at <= w->at)
break;
heap [k] = heap [p];
((W)heap [k])->active = k + 1;
2007-12-11 21:04:40 +00:00
k = p;
}
2007-11-04 00:24:16 +00:00
heap [k] = w;
((W)heap [k])->active = k + 1;
}
void inline_speed
2007-11-04 00:24:16 +00:00
downheap (WT *heap, int N, int k)
{
2007-11-04 00:24:16 +00:00
WT w = heap [k];
2007-12-11 21:04:40 +00:00
for (;;)
{
2007-12-11 21:04:40 +00:00
int c = (k << 1) + 1;
if (c >= N)
break;
2007-12-11 21:04:40 +00:00
c += c + 1 < N && heap [c]->at > heap [c + 1]->at
? 1 : 0;
2007-12-11 21:04:40 +00:00
if (w->at <= heap [c]->at)
break;
2007-12-11 21:04:40 +00:00
heap [k] = heap [c];
((W)heap [k])->active = k + 1;
2007-12-11 21:04:40 +00:00
k = c;
}
2007-11-04 00:24:16 +00:00
heap [k] = w;
((W)heap [k])->active = k + 1;
}
void inline_size
adjustheap (WT *heap, int N, int k)
2007-11-09 23:04:35 +00:00
{
upheap (heap, k);
downheap (heap, N, k);
2007-11-09 23:04:35 +00:00
}
2007-10-31 00:32:33 +00:00
/*****************************************************************************/
2007-10-31 00:24:16 +00:00
typedef struct
{
2007-11-05 20:19:00 +00:00
WL head;
2007-11-01 11:43:11 +00:00
sig_atomic_t volatile gotsig;
2007-10-31 00:24:16 +00:00
} ANSIG;
static ANSIG *signals;
2007-10-30 23:10:33 +00:00
static int signalmax;
2007-10-31 00:24:16 +00:00
static int sigpipe [2];
2007-11-01 11:43:11 +00:00
static sig_atomic_t volatile gotsig;
static ev_io sigev;
2007-10-31 00:24:16 +00:00
void inline_size
2007-10-31 00:24:16 +00:00
signals_init (ANSIG *base, int count)