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