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