Home | History | Annotate | Download | only in libevent
      1 /*
      2  * Copyright 2000-2003 Niels Provos <provos (at) citi.umich.edu>
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. The name of the author may not be used to endorse or promote products
     14  *    derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 #ifdef HAVE_CONFIG_H
     28 #include "config.h"
     29 #endif
     30 
     31 #include <stdint.h>
     32 #include <sys/types.h>
     33 #include <sys/resource.h>
     34 #ifdef HAVE_SYS_TIME_H
     35 #include <sys/time.h>
     36 #else
     37 #include <sys/_libevent_time.h>
     38 #endif
     39 #include <sys/queue.h>
     40 #include <sys/epoll.h>
     41 #include <signal.h>
     42 #include <stdio.h>
     43 #include <stdlib.h>
     44 #include <string.h>
     45 #include <unistd.h>
     46 #include <errno.h>
     47 #ifdef HAVE_FCNTL_H
     48 #include <fcntl.h>
     49 #endif
     50 
     51 #include "event.h"
     52 #include "event-internal.h"
     53 #include "evsignal.h"
     54 #include "log.h"
     55 
     56 /* due to limitations in the epoll interface, we need to keep track of
     57  * all file descriptors outself.
     58  */
     59 struct evepoll {
     60 	struct event *evread;
     61 	struct event *evwrite;
     62 };
     63 
     64 struct epollop {
     65 	struct evepoll *fds;
     66 	int nfds;
     67 	struct epoll_event *events;
     68 	int nevents;
     69 	int epfd;
     70 };
     71 
     72 static void *epoll_init	(struct event_base *);
     73 static int epoll_add	(void *, struct event *);
     74 static int epoll_del	(void *, struct event *);
     75 static int epoll_dispatch	(struct event_base *, void *, struct timeval *);
     76 static void epoll_dealloc	(struct event_base *, void *);
     77 
     78 const struct eventop epollops = {
     79 	"epoll",
     80 	epoll_init,
     81 	epoll_add,
     82 	epoll_del,
     83 	epoll_dispatch,
     84 	epoll_dealloc,
     85 	1 /* need reinit */
     86 };
     87 
     88 #ifdef HAVE_SETFD
     89 #define FD_CLOSEONEXEC(x) do { \
     90         if (fcntl(x, F_SETFD, 1) == -1) \
     91                 event_warn("fcntl(%d, F_SETFD)", x); \
     92 } while (0)
     93 #else
     94 #define FD_CLOSEONEXEC(x)
     95 #endif
     96 
     97 /* On Linux kernels at least up to 2.6.24.4, epoll can't handle timeout
     98  * values bigger than (LONG_MAX - 999ULL)/HZ.  HZ in the wild can be
     99  * as big as 1000, and LONG_MAX can be as small as (1<<31)-1, so the
    100  * largest number of msec we can support here is 2147482.  Let's
    101  * round that down by 47 seconds.
    102  */
    103 #define MAX_EPOLL_TIMEOUT_MSEC (35*60*1000)
    104 
    105 #define INITIAL_NFILES 32
    106 #define INITIAL_NEVENTS 32
    107 #define MAX_NEVENTS 4096
    108 
    109 static void *
    110 epoll_init(struct event_base *base)
    111 {
    112 	int epfd;
    113 	struct epollop *epollop;
    114 
    115 	/* Disable epollueue when this environment variable is set */
    116 	if (evutil_getenv("EVENT_NOEPOLL"))
    117 		return (NULL);
    118 
    119 	/* Initalize the kernel queue */
    120 	if ((epfd = epoll_create(32000)) == -1) {
    121 		if (errno != ENOSYS)
    122 			event_warn("epoll_create");
    123 		return (NULL);
    124 	}
    125 
    126 	FD_CLOSEONEXEC(epfd);
    127 
    128 	if (!(epollop = calloc(1, sizeof(struct epollop))))
    129 		return (NULL);
    130 
    131 	epollop->epfd = epfd;
    132 
    133 	/* Initalize fields */
    134 	epollop->events = malloc(INITIAL_NEVENTS * sizeof(struct epoll_event));
    135 	if (epollop->events == NULL) {
    136 		free(epollop);
    137 		return (NULL);
    138 	}
    139 	epollop->nevents = INITIAL_NEVENTS;
    140 
    141 	epollop->fds = calloc(INITIAL_NFILES, sizeof(struct evepoll));
    142 	if (epollop->fds == NULL) {
    143 		free(epollop->events);
    144 		free(epollop);
    145 		return (NULL);
    146 	}
    147 	epollop->nfds = INITIAL_NFILES;
    148 
    149 	evsignal_init(base);
    150 
    151 	return (epollop);
    152 }
    153 
    154 static int
    155 epoll_recalc(struct event_base *base, void *arg, int max)
    156 {
    157 	struct epollop *epollop = arg;
    158 
    159 	if (max >= epollop->nfds) {
    160 		struct evepoll *fds;
    161 		int nfds;
    162 
    163 		nfds = epollop->nfds;
    164 		while (nfds <= max)
    165 			nfds <<= 1;
    166 
    167 		fds = realloc(epollop->fds, nfds * sizeof(struct evepoll));
    168 		if (fds == NULL) {
    169 			event_warn("realloc");
    170 			return (-1);
    171 		}
    172 		epollop->fds = fds;
    173 		memset(fds + epollop->nfds, 0,
    174 		    (nfds - epollop->nfds) * sizeof(struct evepoll));
    175 		epollop->nfds = nfds;
    176 	}
    177 
    178 	return (0);
    179 }
    180 
    181 static int
    182 epoll_dispatch(struct event_base *base, void *arg, struct timeval *tv)
    183 {
    184 	struct epollop *epollop = arg;
    185 	struct epoll_event *events = epollop->events;
    186 	struct evepoll *evep;
    187 	int i, res, timeout = -1;
    188 
    189 	if (tv != NULL)
    190 		timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
    191 
    192 	if (timeout > MAX_EPOLL_TIMEOUT_MSEC) {
    193 		/* Linux kernels can wait forever if the timeout is too big;
    194 		 * see comment on MAX_EPOLL_TIMEOUT_MSEC. */
    195 		timeout = MAX_EPOLL_TIMEOUT_MSEC;
    196 	}
    197 
    198 	res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout);
    199 
    200 	if (res == -1) {
    201 		if (errno != EINTR) {
    202 			event_warn("epoll_wait");
    203 			return (-1);
    204 		}
    205 
    206 		evsignal_process(base);
    207 		return (0);
    208 	} else if (base->sig.evsignal_caught) {
    209 		evsignal_process(base);
    210 	}
    211 
    212 	event_debug(("%s: epoll_wait reports %d", __func__, res));
    213 
    214 	for (i = 0; i < res; i++) {
    215 		int what = events[i].events;
    216 		struct event *evread = NULL, *evwrite = NULL;
    217 		int fd = events[i].data.fd;
    218 
    219 		if (fd < 0 || fd >= epollop->nfds)
    220 			continue;
    221 		evep = &epollop->fds[fd];
    222 
    223 		if (what & (EPOLLHUP|EPOLLERR)) {
    224 			evread = evep->evread;
    225 			evwrite = evep->evwrite;
    226 		} else {
    227 			if (what & EPOLLIN) {
    228 				evread = evep->evread;
    229 			}
    230 
    231 			if (what & EPOLLOUT) {
    232 				evwrite = evep->evwrite;
    233 			}
    234 		}
    235 
    236 		if (!(evread||evwrite))
    237 			continue;
    238 
    239 		if (evread != NULL)
    240 			event_active(evread, EV_READ, 1);
    241 		if (evwrite != NULL)
    242 			event_active(evwrite, EV_WRITE, 1);
    243 	}
    244 
    245 	if (res == epollop->nevents && epollop->nevents < MAX_NEVENTS) {
    246 		/* We used all of the event space this time.  We should
    247 		   be ready for more events next time. */
    248 		int new_nevents = epollop->nevents * 2;
    249 		struct epoll_event *new_events;
    250 
    251 		new_events = realloc(epollop->events,
    252 		    new_nevents * sizeof(struct epoll_event));
    253 		if (new_events) {
    254 			epollop->events = new_events;
    255 			epollop->nevents = new_nevents;
    256 		}
    257 	}
    258 
    259 	return (0);
    260 }
    261 
    262 
    263 static int
    264 epoll_add(void *arg, struct event *ev)
    265 {
    266 	struct epollop *epollop = arg;
    267 	struct epoll_event epev = {0, {0}};
    268 	struct evepoll *evep;
    269 	int fd, op, events;
    270 
    271 	if (ev->ev_events & EV_SIGNAL)
    272 		return (evsignal_add(ev));
    273 
    274 	fd = ev->ev_fd;
    275 	if (fd >= epollop->nfds) {
    276 		/* Extent the file descriptor array as necessary */
    277 		if (epoll_recalc(ev->ev_base, epollop, fd) == -1)
    278 			return (-1);
    279 	}
    280 	evep = &epollop->fds[fd];
    281 	op = EPOLL_CTL_ADD;
    282 	events = 0;
    283 	if (evep->evread != NULL) {
    284 		events |= EPOLLIN;
    285 		op = EPOLL_CTL_MOD;
    286 	}
    287 	if (evep->evwrite != NULL) {
    288 		events |= EPOLLOUT;
    289 		op = EPOLL_CTL_MOD;
    290 	}
    291 
    292 	if (ev->ev_events & EV_READ)
    293 		events |= EPOLLIN;
    294 	if (ev->ev_events & EV_WRITE)
    295 		events |= EPOLLOUT;
    296 
    297 	epev.data.fd = fd;
    298 	epev.events = events;
    299 	if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1)
    300 			return (-1);
    301 
    302 	/* Update events responsible */
    303 	if (ev->ev_events & EV_READ)
    304 		evep->evread = ev;
    305 	if (ev->ev_events & EV_WRITE)
    306 		evep->evwrite = ev;
    307 
    308 	return (0);
    309 }
    310 
    311 static int
    312 epoll_del(void *arg, struct event *ev)
    313 {
    314 	struct epollop *epollop = arg;
    315 	struct epoll_event epev = {0, {0}};
    316 	struct evepoll *evep;
    317 	int fd, events, op;
    318 	int needwritedelete = 1, needreaddelete = 1;
    319 
    320 	if (ev->ev_events & EV_SIGNAL)
    321 		return (evsignal_del(ev));
    322 
    323 	fd = ev->ev_fd;
    324 	if (fd >= epollop->nfds)
    325 		return (0);
    326 	evep = &epollop->fds[fd];
    327 
    328 	op = EPOLL_CTL_DEL;
    329 	events = 0;
    330 
    331 	if (ev->ev_events & EV_READ)
    332 		events |= EPOLLIN;
    333 	if (ev->ev_events & EV_WRITE)
    334 		events |= EPOLLOUT;
    335 
    336 	if ((events & (EPOLLIN|EPOLLOUT)) != (EPOLLIN|EPOLLOUT)) {
    337 		if ((events & EPOLLIN) && evep->evwrite != NULL) {
    338 			needwritedelete = 0;
    339 			events = EPOLLOUT;
    340 			op = EPOLL_CTL_MOD;
    341 		} else if ((events & EPOLLOUT) && evep->evread != NULL) {
    342 			needreaddelete = 0;
    343 			events = EPOLLIN;
    344 			op = EPOLL_CTL_MOD;
    345 		}
    346 	}
    347 
    348 	epev.events = events;
    349 	epev.data.fd = fd;
    350 
    351 	if (needreaddelete)
    352 		evep->evread = NULL;
    353 	if (needwritedelete)
    354 		evep->evwrite = NULL;
    355 
    356 	if (epoll_ctl(epollop->epfd, op, fd, &epev) == -1)
    357 		return (-1);
    358 
    359 	return (0);
    360 }
    361 
    362 static void
    363 epoll_dealloc(struct event_base *base, void *arg)
    364 {
    365 	struct epollop *epollop = arg;
    366 
    367 	evsignal_dealloc(base);
    368 	if (epollop->fds)
    369 		free(epollop->fds);
    370 	if (epollop->events)
    371 		free(epollop->events);
    372 	if (epollop->epfd >= 0)
    373 		close(epollop->epfd);
    374 
    375 	memset(epollop, 0, sizeof(struct epollop));
    376 	free(epollop);
    377 }
    378