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