2 * Copyright 2000-2003 Niels Provos <provos@citi.umich.edu>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
32 #include <sys/types.h>
33 #include <sys/resource.h>
34 #ifdef HAVE_SYS_TIME_H
37 #include <sys/_libevent_time.h>
39 #include <sys/queue.h>
40 #include <sys/epoll.h>
52 #include "event-internal.h"
56 /* due to limitations in the epoll interface, we need to keep track of
57 * all file descriptors outself.
61 struct event
*evwrite
;
67 struct epoll_event
*events
;
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 *);
78 const struct eventop epollops
= {
89 #define FD_CLOSEONEXEC(x) do { \
90 if (fcntl(x, F_SETFD, 1) == -1) \
91 event_warn("fcntl(%d, F_SETFD)", x); \
94 #define FD_CLOSEONEXEC(x)
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.
103 #define MAX_EPOLL_TIMEOUT_MSEC (35*60*1000)
105 #define INITIAL_NFILES 32
106 #define INITIAL_NEVENTS 32
107 #define MAX_NEVENTS 4096
110 epoll_init(struct event_base
*base
)
113 struct epollop
*epollop
;
115 /* Disable epollueue when this environment variable is set */
116 if (evutil_getenv("EVENT_NOEPOLL"))
119 /* Initalize the kernel queue */
120 if ((epfd
= epoll_create(32000)) == -1) {
122 event_warn("epoll_create");
126 FD_CLOSEONEXEC(epfd
);
128 if (!(epollop
= calloc(1, sizeof(struct epollop
))))
131 epollop
->epfd
= epfd
;
133 /* Initalize fields */
134 epollop
->events
= malloc(INITIAL_NEVENTS
* sizeof(struct epoll_event
));
135 if (epollop
->events
== NULL
) {
139 epollop
->nevents
= INITIAL_NEVENTS
;
141 epollop
->fds
= calloc(INITIAL_NFILES
, sizeof(struct evepoll
));
142 if (epollop
->fds
== NULL
) {
143 free(epollop
->events
);
147 epollop
->nfds
= INITIAL_NFILES
;
155 epoll_recalc(struct event_base
*base
, void *arg
, int max
)
157 struct epollop
*epollop
= arg
;
159 if (max
>= epollop
->nfds
) {
163 nfds
= epollop
->nfds
;
167 fds
= realloc(epollop
->fds
, nfds
* sizeof(struct evepoll
));
169 event_warn("realloc");
173 memset(fds
+ epollop
->nfds
, 0,
174 (nfds
- epollop
->nfds
) * sizeof(struct evepoll
));
175 epollop
->nfds
= nfds
;
182 epoll_dispatch(struct event_base
*base
, void *arg
, struct timeval
*tv
)
184 struct epollop
*epollop
= arg
;
185 struct epoll_event
*events
= epollop
->events
;
186 struct evepoll
*evep
;
187 int i
, res
, timeout
= -1;
190 timeout
= tv
->tv_sec
* 1000 + (tv
->tv_usec
+ 999) / 1000;
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
;
198 res
= epoll_wait(epollop
->epfd
, events
, epollop
->nevents
, timeout
);
201 if (errno
!= EINTR
) {
202 event_warn("epoll_wait");
206 evsignal_process(base
);
208 } else if (base
->sig
.evsignal_caught
) {
209 evsignal_process(base
);
212 event_debug(("%s: epoll_wait reports %d", __func__
, res
));
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
;
219 if (fd
< 0 || fd
>= epollop
->nfds
)
221 evep
= &epollop
->fds
[fd
];
223 if (what
& (EPOLLHUP
|EPOLLERR
)) {
224 evread
= evep
->evread
;
225 evwrite
= evep
->evwrite
;
227 if (what
& EPOLLIN
) {
228 evread
= evep
->evread
;
231 if (what
& EPOLLOUT
) {
232 evwrite
= evep
->evwrite
;
236 if (!(evread
||evwrite
))
240 event_active(evread
, EV_READ
, 1);
242 event_active(evwrite
, EV_WRITE
, 1);
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
;
251 new_events
= realloc(epollop
->events
,
252 new_nevents
* sizeof(struct epoll_event
));
254 epollop
->events
= new_events
;
255 epollop
->nevents
= new_nevents
;
264 epoll_add(void *arg
, struct event
*ev
)
266 struct epollop
*epollop
= arg
;
267 struct epoll_event epev
= {0, {0}};
268 struct evepoll
*evep
;
271 if (ev
->ev_events
& EV_SIGNAL
)
272 return (evsignal_add(ev
));
275 if (fd
>= epollop
->nfds
) {
276 /* Extent the file descriptor array as necessary */
277 if (epoll_recalc(ev
->ev_base
, epollop
, fd
) == -1)
280 evep
= &epollop
->fds
[fd
];
283 if (evep
->evread
!= NULL
) {
287 if (evep
->evwrite
!= NULL
) {
292 if (ev
->ev_events
& EV_READ
)
294 if (ev
->ev_events
& EV_WRITE
)
298 epev
.events
= events
;
299 if (epoll_ctl(epollop
->epfd
, op
, ev
->ev_fd
, &epev
) == -1)
302 /* Update events responsible */
303 if (ev
->ev_events
& EV_READ
)
305 if (ev
->ev_events
& EV_WRITE
)
312 epoll_del(void *arg
, struct event
*ev
)
314 struct epollop
*epollop
= arg
;
315 struct epoll_event epev
= {0, {0}};
316 struct evepoll
*evep
;
318 int needwritedelete
= 1, needreaddelete
= 1;
320 if (ev
->ev_events
& EV_SIGNAL
)
321 return (evsignal_del(ev
));
324 if (fd
>= epollop
->nfds
)
326 evep
= &epollop
->fds
[fd
];
331 if (ev
->ev_events
& EV_READ
)
333 if (ev
->ev_events
& EV_WRITE
)
336 if ((events
& (EPOLLIN
|EPOLLOUT
)) != (EPOLLIN
|EPOLLOUT
)) {
337 if ((events
& EPOLLIN
) && evep
->evwrite
!= NULL
) {
341 } else if ((events
& EPOLLOUT
) && evep
->evread
!= NULL
) {
348 epev
.events
= events
;
354 evep
->evwrite
= NULL
;
356 if (epoll_ctl(epollop
->epfd
, op
, fd
, &epev
) == -1)
363 epoll_dealloc(struct event_base
*base
, void *arg
)
365 struct epollop
*epollop
= arg
;
367 evsignal_dealloc(base
);
371 free(epollop
->events
);
372 if (epollop
->epfd
>= 0)
373 close(epollop
->epfd
);
375 memset(epollop
, 0, sizeof(struct epollop
));