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