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