Home | History | Annotate | Line # | Download | only in libevent
epoll.c revision 1.2
      1  1.1  christos /*	$NetBSD: epoll.c,v 1.2 2014/12/19 20:43:18 christos Exp $	*/
      2  1.1  christos 
      3  1.1  christos /*
      4  1.1  christos  * Copyright 2000-2007 Niels Provos <provos (at) citi.umich.edu>
      5  1.1  christos  * Copyright 2007-2012 Niels Provos, Nick Mathewson
      6  1.1  christos  *
      7  1.1  christos  * Redistribution and use in source and binary forms, with or without
      8  1.1  christos  * modification, are permitted provided that the following conditions
      9  1.1  christos  * are met:
     10  1.1  christos  * 1. Redistributions of source code must retain the above copyright
     11  1.1  christos  *    notice, this list of conditions and the following disclaimer.
     12  1.1  christos  * 2. Redistributions in binary form must reproduce the above copyright
     13  1.1  christos  *    notice, this list of conditions and the following disclaimer in the
     14  1.1  christos  *    documentation and/or other materials provided with the distribution.
     15  1.1  christos  * 3. The name of the author may not be used to endorse or promote products
     16  1.1  christos  *    derived from this software without specific prior written permission.
     17  1.1  christos  *
     18  1.1  christos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  1.1  christos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20  1.1  christos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21  1.1  christos  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     22  1.1  christos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     23  1.1  christos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     24  1.1  christos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     25  1.1  christos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     26  1.1  christos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     27  1.1  christos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     28  1.1  christos  */
     29  1.1  christos #include "event2/event-config.h"
     30  1.1  christos #include "evconfig-private.h"
     31  1.1  christos 
     32  1.1  christos #ifdef EVENT__HAVE_EPOLL
     33  1.1  christos 
     34  1.1  christos #include <stdint.h>
     35  1.1  christos #include <sys/types.h>
     36  1.1  christos #include <sys/resource.h>
     37  1.1  christos #ifdef EVENT__HAVE_SYS_TIME_H
     38  1.1  christos #include <sys/time.h>
     39  1.1  christos #endif
     40  1.1  christos #include <sys/queue.h>
     41  1.1  christos #include <sys/epoll.h>
     42  1.1  christos #include <signal.h>
     43  1.1  christos #include <limits.h>
     44  1.1  christos #include <stdio.h>
     45  1.1  christos #include <stdlib.h>
     46  1.1  christos #include <string.h>
     47  1.1  christos #include <unistd.h>
     48  1.1  christos #include <errno.h>
     49  1.1  christos #ifdef EVENT__HAVE_FCNTL_H
     50  1.1  christos #include <fcntl.h>
     51  1.1  christos #endif
     52  1.1  christos #ifdef EVENT__HAVE_SYS_TIMERFD_H
     53  1.1  christos #include <sys/timerfd.h>
     54  1.1  christos #endif
     55  1.1  christos 
     56  1.1  christos #include "event-internal.h"
     57  1.1  christos #include "evsignal-internal.h"
     58  1.1  christos #include "event2/thread.h"
     59  1.1  christos #include "evthread-internal.h"
     60  1.1  christos #include "log-internal.h"
     61  1.1  christos #include "evmap-internal.h"
     62  1.1  christos #include "changelist-internal.h"
     63  1.1  christos #include "time-internal.h"
     64  1.1  christos 
     65  1.2  christos /* Since Linux 2.6.17, epoll is able to report about peer half-closed connection
     66  1.2  christos    using special EPOLLRDHUP flag on a read event.
     67  1.2  christos */
     68  1.2  christos #if !defined(EPOLLRDHUP)
     69  1.2  christos #define EPOLLRDHUP 0
     70  1.2  christos #define EARLY_CLOSE_IF_HAVE_RDHUP 0
     71  1.2  christos #else
     72  1.2  christos #define EARLY_CLOSE_IF_HAVE_RDHUP EV_FEATURE_EARLY_CLOSE
     73  1.2  christos #endif
     74  1.2  christos 
     75  1.2  christos #include "epolltable-internal.h"
     76  1.2  christos 
     77  1.1  christos #if defined(EVENT__HAVE_SYS_TIMERFD_H) &&			  \
     78  1.1  christos 	defined(EVENT__HAVE_TIMERFD_CREATE) &&			  \
     79  1.1  christos 	defined(HAVE_POSIX_MONOTONIC) && defined(TFD_NONBLOCK) && \
     80  1.1  christos 	defined(TFD_CLOEXEC)
     81  1.1  christos /* Note that we only use timerfd if TFD_NONBLOCK and TFD_CLOEXEC are available
     82  1.1  christos    and working.  This means that we can't support it on 2.6.25 (where timerfd
     83  1.1  christos    was introduced) or 2.6.26, since 2.6.27 introduced those flags.
     84  1.1  christos  */
     85  1.1  christos #define USING_TIMERFD
     86  1.1  christos #endif
     87  1.1  christos 
     88  1.1  christos struct epollop {
     89  1.1  christos 	struct epoll_event *events;
     90  1.1  christos 	int nevents;
     91  1.1  christos 	int epfd;
     92  1.1  christos #ifdef USING_TIMERFD
     93  1.1  christos 	int timerfd;
     94  1.1  christos #endif
     95  1.1  christos };
     96  1.1  christos 
     97  1.1  christos static void *epoll_init(struct event_base *);
     98  1.1  christos static int epoll_dispatch(struct event_base *, struct timeval *);
     99  1.1  christos static void epoll_dealloc(struct event_base *);
    100  1.1  christos 
    101  1.1  christos static const struct eventop epollops_changelist = {
    102  1.1  christos 	"epoll (with changelist)",
    103  1.1  christos 	epoll_init,
    104  1.1  christos 	event_changelist_add_,
    105  1.1  christos 	event_changelist_del_,
    106  1.1  christos 	epoll_dispatch,
    107  1.1  christos 	epoll_dealloc,
    108  1.1  christos 	1, /* need reinit */
    109  1.2  christos 	EV_FEATURE_ET|EV_FEATURE_O1| EARLY_CLOSE_IF_HAVE_RDHUP,
    110  1.1  christos 	EVENT_CHANGELIST_FDINFO_SIZE
    111  1.1  christos };
    112  1.1  christos 
    113  1.1  christos 
    114  1.1  christos static int epoll_nochangelist_add(struct event_base *base, evutil_socket_t fd,
    115  1.1  christos     short old, short events, void *p);
    116  1.1  christos static int epoll_nochangelist_del(struct event_base *base, evutil_socket_t fd,
    117  1.1  christos     short old, short events, void *p);
    118  1.1  christos 
    119  1.1  christos const struct eventop epollops = {
    120  1.1  christos 	"epoll",
    121  1.1  christos 	epoll_init,
    122  1.1  christos 	epoll_nochangelist_add,
    123  1.1  christos 	epoll_nochangelist_del,
    124  1.1  christos 	epoll_dispatch,
    125  1.1  christos 	epoll_dealloc,
    126  1.1  christos 	1, /* need reinit */
    127  1.2  christos 	EV_FEATURE_ET|EV_FEATURE_O1|EV_FEATURE_EARLY_CLOSE,
    128  1.1  christos 	0
    129  1.1  christos };
    130  1.1  christos 
    131  1.1  christos #define INITIAL_NEVENT 32
    132  1.1  christos #define MAX_NEVENT 4096
    133  1.1  christos 
    134  1.1  christos /* On Linux kernels at least up to 2.6.24.4, epoll can't handle timeout
    135  1.1  christos  * values bigger than (LONG_MAX - 999ULL)/HZ.  HZ in the wild can be
    136  1.1  christos  * as big as 1000, and LONG_MAX can be as small as (1<<31)-1, so the
    137  1.1  christos  * largest number of msec we can support here is 2147482.  Let's
    138  1.1  christos  * round that down by 47 seconds.
    139  1.1  christos  */
    140  1.1  christos #define MAX_EPOLL_TIMEOUT_MSEC (35*60*1000)
    141  1.1  christos 
    142  1.1  christos static void *
    143  1.1  christos epoll_init(struct event_base *base)
    144  1.1  christos {
    145  1.1  christos 	int epfd = -1;
    146  1.1  christos 	struct epollop *epollop;
    147  1.1  christos 
    148  1.1  christos #ifdef EVENT__HAVE_EPOLL_CREATE1
    149  1.1  christos 	/* First, try the shiny new epoll_create1 interface, if we have it. */
    150  1.1  christos 	epfd = epoll_create1(EPOLL_CLOEXEC);
    151  1.1  christos #endif
    152  1.1  christos 	if (epfd == -1) {
    153  1.1  christos 		/* Initialize the kernel queue using the old interface.  (The
    154  1.1  christos 		size field is ignored   since 2.6.8.) */
    155  1.1  christos 		if ((epfd = epoll_create(32000)) == -1) {
    156  1.1  christos 			if (errno != ENOSYS)
    157  1.1  christos 				event_warn("epoll_create");
    158  1.1  christos 			return (NULL);
    159  1.1  christos 		}
    160  1.1  christos 		evutil_make_socket_closeonexec(epfd);
    161  1.1  christos 	}
    162  1.1  christos 
    163  1.1  christos 	if (!(epollop = mm_calloc(1, sizeof(struct epollop)))) {
    164  1.1  christos 		close(epfd);
    165  1.1  christos 		return (NULL);
    166  1.1  christos 	}
    167  1.1  christos 
    168  1.1  christos 	epollop->epfd = epfd;
    169  1.1  christos 
    170  1.1  christos 	/* Initialize fields */
    171  1.1  christos 	epollop->events = mm_calloc(INITIAL_NEVENT, sizeof(struct epoll_event));
    172  1.1  christos 	if (epollop->events == NULL) {
    173  1.1  christos 		mm_free(epollop);
    174  1.1  christos 		close(epfd);
    175  1.1  christos 		return (NULL);
    176  1.1  christos 	}
    177  1.1  christos 	epollop->nevents = INITIAL_NEVENT;
    178  1.1  christos 
    179  1.1  christos 	if ((base->flags & EVENT_BASE_FLAG_EPOLL_USE_CHANGELIST) != 0 ||
    180  1.1  christos 	    ((base->flags & EVENT_BASE_FLAG_IGNORE_ENV) == 0 &&
    181  1.1  christos 		evutil_getenv_("EVENT_EPOLL_USE_CHANGELIST") != NULL)) {
    182  1.1  christos 
    183  1.1  christos 		base->evsel = &epollops_changelist;
    184  1.1  christos 	}
    185  1.1  christos 
    186  1.1  christos #ifdef USING_TIMERFD
    187  1.1  christos 	/*
    188  1.1  christos 	  The epoll interface ordinarily gives us one-millisecond precision,
    189  1.1  christos 	  so on Linux it makes perfect sense to use the CLOCK_MONOTONIC_COARSE
    190  1.1  christos 	  timer.  But when the user has set the new PRECISE_TIMER flag for an
    191  1.1  christos 	  event_base, we can try to use timerfd to give them finer granularity.
    192  1.1  christos 	*/
    193  1.1  christos 	if ((base->flags & EVENT_BASE_FLAG_PRECISE_TIMER) &&
    194  1.1  christos 	    base->monotonic_timer.monotonic_clock == CLOCK_MONOTONIC) {
    195  1.1  christos 		int fd;
    196  1.1  christos 		fd = epollop->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC);
    197  1.1  christos 		if (epollop->timerfd >= 0) {
    198  1.1  christos 			struct epoll_event epev;
    199  1.1  christos 			memset(&epev, 0, sizeof(epev));
    200  1.1  christos 			epev.data.fd = epollop->timerfd;
    201  1.1  christos 			epev.events = EPOLLIN;
    202  1.1  christos 			if (epoll_ctl(epollop->epfd, EPOLL_CTL_ADD, fd, &epev) < 0) {
    203  1.1  christos 				event_warn("epoll_ctl(timerfd)");
    204  1.1  christos 				close(fd);
    205  1.1  christos 				epollop->timerfd = -1;
    206  1.1  christos 			}
    207  1.1  christos 		} else {
    208  1.1  christos 			if (errno != EINVAL && errno != ENOSYS) {
    209  1.1  christos 				/* These errors probably mean that we were
    210  1.1  christos 				 * compiled with timerfd/TFD_* support, but
    211  1.1  christos 				 * we're running on a kernel that lacks those.
    212  1.1  christos 				 */
    213  1.1  christos 				event_warn("timerfd_create");
    214  1.1  christos 			}
    215  1.1  christos 			epollop->timerfd = -1;
    216  1.1  christos 		}
    217  1.1  christos 	} else {
    218  1.1  christos 		epollop->timerfd = -1;
    219  1.1  christos 	}
    220  1.1  christos #endif
    221  1.1  christos 
    222  1.1  christos 	evsig_init_(base);
    223  1.1  christos 
    224  1.1  christos 	return (epollop);
    225  1.1  christos }
    226  1.1  christos 
    227  1.1  christos static const char *
    228  1.1  christos change_to_string(int change)
    229  1.1  christos {
    230  1.1  christos 	change &= (EV_CHANGE_ADD|EV_CHANGE_DEL);
    231  1.1  christos 	if (change == EV_CHANGE_ADD) {
    232  1.1  christos 		return "add";
    233  1.1  christos 	} else if (change == EV_CHANGE_DEL) {
    234  1.1  christos 		return "del";
    235  1.1  christos 	} else if (change == 0) {
    236  1.1  christos 		return "none";
    237  1.1  christos 	} else {
    238  1.1  christos 		return "???";
    239  1.1  christos 	}
    240  1.1  christos }
    241  1.1  christos 
    242  1.1  christos static const char *
    243  1.1  christos epoll_op_to_string(int op)
    244  1.1  christos {
    245  1.1  christos 	return op == EPOLL_CTL_ADD?"ADD":
    246  1.1  christos 	    op == EPOLL_CTL_DEL?"DEL":
    247  1.1  christos 	    op == EPOLL_CTL_MOD?"MOD":
    248  1.1  christos 	    "???";
    249  1.1  christos }
    250  1.1  christos 
    251  1.1  christos static int
    252  1.1  christos epoll_apply_one_change(struct event_base *base,
    253  1.1  christos     struct epollop *epollop,
    254  1.1  christos     const struct event_change *ch)
    255  1.1  christos {
    256  1.1  christos 	struct epoll_event epev;
    257  1.1  christos 	int op, events = 0;
    258  1.1  christos 	int idx;
    259  1.1  christos 
    260  1.2  christos 	idx = EPOLL_OP_TABLE_INDEX(ch);
    261  1.2  christos 	op = epoll_op_table[idx].op;
    262  1.2  christos 	events = epoll_op_table[idx].events;
    263  1.1  christos 
    264  1.1  christos 	if (!events) {
    265  1.1  christos 		EVUTIL_ASSERT(op == 0);
    266  1.1  christos 		return 0;
    267  1.1  christos 	}
    268  1.1  christos 
    269  1.1  christos 	if ((ch->read_change|ch->write_change) & EV_CHANGE_ET)
    270  1.1  christos 		events |= EPOLLET;
    271  1.1  christos 
    272  1.1  christos 	memset(&epev, 0, sizeof(epev));
    273  1.1  christos 	epev.data.fd = ch->fd;
    274  1.1  christos 	epev.events = events;
    275  1.1  christos 	if (epoll_ctl(epollop->epfd, op, ch->fd, &epev) == 0) {
    276  1.2  christos 		event_debug(("Epoll %s(%d) on fd %d okay. [old events were %d; read change was %d; write change was %d; close change was %d]",
    277  1.1  christos 			epoll_op_to_string(op),
    278  1.1  christos 			(int)epev.events,
    279  1.1  christos 			(int)ch->fd,
    280  1.1  christos 			ch->old_events,
    281  1.1  christos 			ch->read_change,
    282  1.2  christos 			ch->write_change,
    283  1.2  christos 			ch->close_change));
    284  1.1  christos 		return 0;
    285  1.1  christos 	}
    286  1.1  christos 
    287  1.1  christos 	switch (op) {
    288  1.1  christos 	case EPOLL_CTL_MOD:
    289  1.1  christos 		if (errno == ENOENT) {
    290  1.1  christos 			/* If a MOD operation fails with ENOENT, the
    291  1.1  christos 			 * fd was probably closed and re-opened.  We
    292  1.1  christos 			 * should retry the operation as an ADD.
    293  1.1  christos 			 */
    294  1.1  christos 			if (epoll_ctl(epollop->epfd, EPOLL_CTL_ADD, ch->fd, &epev) == -1) {
    295  1.1  christos 				event_warn("Epoll MOD(%d) on %d retried as ADD; that failed too",
    296  1.1  christos 				    (int)epev.events, ch->fd);
    297  1.1  christos 				return -1;
    298  1.1  christos 			} else {
    299  1.1  christos 				event_debug(("Epoll MOD(%d) on %d retried as ADD; succeeded.",
    300  1.1  christos 					(int)epev.events,
    301  1.1  christos 					ch->fd));
    302  1.1  christos 				return 0;
    303  1.1  christos 			}
    304  1.1  christos 		}
    305  1.1  christos 		break;
    306  1.1  christos 	case EPOLL_CTL_ADD:
    307  1.1  christos 		if (errno == EEXIST) {
    308  1.1  christos 			/* If an ADD operation fails with EEXIST,
    309  1.1  christos 			 * either the operation was redundant (as with a
    310  1.1  christos 			 * precautionary add), or we ran into a fun
    311  1.1  christos 			 * kernel bug where using dup*() to duplicate the
    312  1.1  christos 			 * same file into the same fd gives you the same epitem
    313  1.1  christos 			 * rather than a fresh one.  For the second case,
    314  1.1  christos 			 * we must retry with MOD. */
    315  1.1  christos 			if (epoll_ctl(epollop->epfd, EPOLL_CTL_MOD, ch->fd, &epev) == -1) {
    316  1.1  christos 				event_warn("Epoll ADD(%d) on %d retried as MOD; that failed too",
    317  1.1  christos 				    (int)epev.events, ch->fd);
    318  1.1  christos 				return -1;
    319  1.1  christos 			} else {
    320  1.1  christos 				event_debug(("Epoll ADD(%d) on %d retried as MOD; succeeded.",
    321  1.1  christos 					(int)epev.events,
    322  1.1  christos 					ch->fd));
    323  1.1  christos 				return 0;
    324  1.1  christos 			}
    325  1.1  christos 		}
    326  1.1  christos 		break;
    327  1.1  christos 	case EPOLL_CTL_DEL:
    328  1.1  christos 		if (errno == ENOENT || errno == EBADF || errno == EPERM) {
    329  1.1  christos 			/* If a delete fails with one of these errors,
    330  1.1  christos 			 * that's fine too: we closed the fd before we
    331  1.1  christos 			 * got around to calling epoll_dispatch. */
    332  1.1  christos 			event_debug(("Epoll DEL(%d) on fd %d gave %s: DEL was unnecessary.",
    333  1.1  christos 				(int)epev.events,
    334  1.1  christos 				ch->fd,
    335  1.1  christos 				strerror(errno)));
    336  1.1  christos 			return 0;
    337  1.1  christos 		}
    338  1.1  christos 		break;
    339  1.1  christos 	default:
    340  1.1  christos 		break;
    341  1.1  christos 	}
    342  1.1  christos 
    343  1.2  christos 	event_warn("Epoll %s(%d) on fd %d failed.  Old events were %d; read change was %d (%s); write change was %d (%s); close change was %d (%s)",
    344  1.1  christos 	    epoll_op_to_string(op),
    345  1.1  christos 	    (int)epev.events,
    346  1.1  christos 	    ch->fd,
    347  1.1  christos 	    ch->old_events,
    348  1.1  christos 	    ch->read_change,
    349  1.1  christos 	    change_to_string(ch->read_change),
    350  1.1  christos 	    ch->write_change,
    351  1.2  christos 	    change_to_string(ch->write_change),
    352  1.2  christos 	    ch->close_change,
    353  1.2  christos 	    change_to_string(ch->close_change));
    354  1.1  christos 
    355  1.1  christos 	return -1;
    356  1.1  christos }
    357  1.1  christos 
    358  1.1  christos static int
    359  1.1  christos epoll_apply_changes(struct event_base *base)
    360  1.1  christos {
    361  1.1  christos 	struct event_changelist *changelist = &base->changelist;
    362  1.1  christos 	struct epollop *epollop = base->evbase;
    363  1.1  christos 	struct event_change *ch;
    364  1.1  christos 
    365  1.1  christos 	int r = 0;
    366  1.1  christos 	int i;
    367  1.1  christos 
    368  1.1  christos 	for (i = 0; i < changelist->n_changes; ++i) {
    369  1.1  christos 		ch = &changelist->changes[i];
    370  1.1  christos 		if (epoll_apply_one_change(base, epollop, ch) < 0)
    371  1.1  christos 			r = -1;
    372  1.1  christos 	}
    373  1.1  christos 
    374  1.1  christos 	return (r);
    375  1.1  christos }
    376  1.1  christos 
    377  1.1  christos static int
    378  1.1  christos epoll_nochangelist_add(struct event_base *base, evutil_socket_t fd,
    379  1.1  christos     short old, short events, void *p)
    380  1.1  christos {
    381  1.1  christos 	struct event_change ch;
    382  1.1  christos 	ch.fd = fd;
    383  1.1  christos 	ch.old_events = old;
    384  1.2  christos 	ch.read_change = ch.write_change = ch.close_change = 0;
    385  1.1  christos 	if (events & EV_WRITE)
    386  1.1  christos 		ch.write_change = EV_CHANGE_ADD |
    387  1.1  christos 		    (events & EV_ET);
    388  1.1  christos 	if (events & EV_READ)
    389  1.1  christos 		ch.read_change = EV_CHANGE_ADD |
    390  1.1  christos 		    (events & EV_ET);
    391  1.2  christos 	if (events & EV_CLOSED)
    392  1.2  christos 		ch.close_change = EV_CHANGE_ADD |
    393  1.2  christos 		    (events & EV_ET);
    394  1.1  christos 
    395  1.1  christos 	return epoll_apply_one_change(base, base->evbase, &ch);
    396  1.1  christos }
    397  1.1  christos 
    398  1.1  christos static int
    399  1.1  christos epoll_nochangelist_del(struct event_base *base, evutil_socket_t fd,
    400  1.1  christos     short old, short events, void *p)
    401  1.1  christos {
    402  1.1  christos 	struct event_change ch;
    403  1.1  christos 	ch.fd = fd;
    404  1.1  christos 	ch.old_events = old;
    405  1.2  christos 	ch.read_change = ch.write_change = ch.close_change = 0;
    406  1.1  christos 	if (events & EV_WRITE)
    407  1.1  christos 		ch.write_change = EV_CHANGE_DEL;
    408  1.1  christos 	if (events & EV_READ)
    409  1.1  christos 		ch.read_change = EV_CHANGE_DEL;
    410  1.2  christos 	if (events & EV_CLOSED)
    411  1.2  christos 		ch.close_change = EV_CHANGE_DEL;
    412  1.1  christos 
    413  1.1  christos 	return epoll_apply_one_change(base, base->evbase, &ch);
    414  1.1  christos }
    415  1.1  christos 
    416  1.1  christos static int
    417  1.1  christos epoll_dispatch(struct event_base *base, struct timeval *tv)
    418  1.1  christos {
    419  1.1  christos 	struct epollop *epollop = base->evbase;
    420  1.1  christos 	struct epoll_event *events = epollop->events;
    421  1.1  christos 	int i, res;
    422  1.1  christos 	long timeout = -1;
    423  1.1  christos 
    424  1.1  christos #ifdef USING_TIMERFD
    425  1.1  christos 	if (epollop->timerfd >= 0) {
    426  1.1  christos 		struct itimerspec is;
    427  1.1  christos 		is.it_interval.tv_sec = 0;
    428  1.1  christos 		is.it_interval.tv_nsec = 0;
    429  1.1  christos 		if (tv == NULL) {
    430  1.1  christos 			/* No timeout; disarm the timer. */
    431  1.1  christos 			is.it_value.tv_sec = 0;
    432  1.1  christos 			is.it_value.tv_nsec = 0;
    433  1.1  christos 		} else {
    434  1.1  christos 			if (tv->tv_sec == 0 && tv->tv_usec == 0) {
    435  1.1  christos 				/* we need to exit immediately; timerfd can't
    436  1.1  christos 				 * do that. */
    437  1.1  christos 				timeout = 0;
    438  1.1  christos 			}
    439  1.1  christos 			is.it_value.tv_sec = tv->tv_sec;
    440  1.1  christos 			is.it_value.tv_nsec = tv->tv_usec * 1000;
    441  1.1  christos 		}
    442  1.1  christos 		/* TODO: we could avoid unnecessary syscalls here by only
    443  1.1  christos 		   calling timerfd_settime when the top timeout changes, or
    444  1.1  christos 		   when we're called with a different timeval.
    445  1.1  christos 		*/
    446  1.1  christos 		if (timerfd_settime(epollop->timerfd, 0, &is, NULL) < 0) {
    447  1.1  christos 			event_warn("timerfd_settime");
    448  1.1  christos 		}
    449  1.1  christos 	} else
    450  1.1  christos #endif
    451  1.1  christos 	if (tv != NULL) {
    452  1.1  christos 		timeout = evutil_tv_to_msec_(tv);
    453  1.1  christos 		if (timeout < 0 || timeout > MAX_EPOLL_TIMEOUT_MSEC) {
    454  1.1  christos 			/* Linux kernels can wait forever if the timeout is
    455  1.1  christos 			 * too big; see comment on MAX_EPOLL_TIMEOUT_MSEC. */
    456  1.1  christos 			timeout = MAX_EPOLL_TIMEOUT_MSEC;
    457  1.1  christos 		}
    458  1.1  christos 	}
    459  1.1  christos 
    460  1.1  christos 	epoll_apply_changes(base);
    461  1.1  christos 	event_changelist_remove_all_(&base->changelist, base);
    462  1.1  christos 
    463  1.1  christos 	EVBASE_RELEASE_LOCK(base, th_base_lock);
    464  1.1  christos 
    465  1.1  christos 	res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout);
    466  1.1  christos 
    467  1.1  christos 	EVBASE_ACQUIRE_LOCK(base, th_base_lock);
    468  1.1  christos 
    469  1.1  christos 	if (res == -1) {
    470  1.1  christos 		if (errno != EINTR) {
    471  1.1  christos 			event_warn("epoll_wait");
    472  1.1  christos 			return (-1);
    473  1.1  christos 		}
    474  1.1  christos 
    475  1.1  christos 		return (0);
    476  1.1  christos 	}
    477  1.1  christos 
    478  1.1  christos 	event_debug(("%s: epoll_wait reports %d", __func__, res));
    479  1.1  christos 	EVUTIL_ASSERT(res <= epollop->nevents);
    480  1.1  christos 
    481  1.1  christos 	for (i = 0; i < res; i++) {
    482  1.1  christos 		int what = events[i].events;
    483  1.1  christos 		short ev = 0;
    484  1.1  christos #ifdef USING_TIMERFD
    485  1.1  christos 		if (events[i].data.fd == epollop->timerfd)
    486  1.1  christos 			continue;
    487  1.1  christos #endif
    488  1.1  christos 
    489  1.1  christos 		if (what & (EPOLLHUP|EPOLLERR)) {
    490  1.1  christos 			ev = EV_READ | EV_WRITE;
    491  1.1  christos 		} else {
    492  1.1  christos 			if (what & EPOLLIN)
    493  1.1  christos 				ev |= EV_READ;
    494  1.1  christos 			if (what & EPOLLOUT)
    495  1.1  christos 				ev |= EV_WRITE;
    496  1.2  christos 			if (what & EPOLLRDHUP)
    497  1.2  christos 				ev |= EV_CLOSED;
    498  1.1  christos 		}
    499  1.1  christos 
    500  1.1  christos 		if (!ev)
    501  1.1  christos 			continue;
    502  1.1  christos 
    503  1.1  christos 		evmap_io_active_(base, events[i].data.fd, ev | EV_ET);
    504  1.1  christos 	}
    505  1.1  christos 
    506  1.1  christos 	if (res == epollop->nevents && epollop->nevents < MAX_NEVENT) {
    507  1.1  christos 		/* We used all of the event space this time.  We should
    508  1.1  christos 		   be ready for more events next time. */
    509  1.1  christos 		int new_nevents = epollop->nevents * 2;
    510  1.1  christos 		struct epoll_event *new_events;
    511  1.1  christos 
    512  1.1  christos 		new_events = mm_realloc(epollop->events,
    513  1.1  christos 		    new_nevents * sizeof(struct epoll_event));
    514  1.1  christos 		if (new_events) {
    515  1.1  christos 			epollop->events = new_events;
    516  1.1  christos 			epollop->nevents = new_nevents;
    517  1.1  christos 		}
    518  1.1  christos 	}
    519  1.1  christos 
    520  1.1  christos 	return (0);
    521  1.1  christos }
    522  1.1  christos 
    523  1.1  christos 
    524  1.1  christos static void
    525  1.1  christos epoll_dealloc(struct event_base *base)
    526  1.1  christos {
    527  1.1  christos 	struct epollop *epollop = base->evbase;
    528  1.1  christos 
    529  1.1  christos 	evsig_dealloc_(base);
    530  1.1  christos 	if (epollop->events)
    531  1.1  christos 		mm_free(epollop->events);
    532  1.1  christos 	if (epollop->epfd >= 0)
    533  1.1  christos 		close(epollop->epfd);
    534  1.1  christos #ifdef USING_TIMERFD
    535  1.1  christos 	if (epollop->timerfd >= 0)
    536  1.1  christos 		close(epollop->timerfd);
    537  1.1  christos #endif
    538  1.1  christos 
    539  1.1  christos 	memset(epollop, 0, sizeof(struct epollop));
    540  1.1  christos 	mm_free(epollop);
    541  1.1  christos }
    542  1.1  christos 
    543  1.1  christos #endif /* EVENT__HAVE_EPOLL */
    544