32 #include <sys/types.h>
33 #include <sys/resource.h>
34 #ifdef HAVE_SYS_TIME_H
37 #include <sys/_time.h>
39 #include <sys/queue.h>
40 #include <sys/epoll.h>
52 #include "event-internal.h"
61 struct event *evwrite;
67 struct epoll_event *events;
73 static int epoll_add (
void *,
struct event *);
74 static int epoll_del (
void *,
struct event *);
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)
105 #define MAX_EPOLL_TIMEOUT_MSEC (35*60*1000)
110 int epfd, nfiles = NEVENT;
115 if (getenv(
"EVENT_NOEPOLL"))
118 if (getrlimit(RLIMIT_NOFILE, &rl) == 0 &&
119 rl.rlim_cur != RLIM_INFINITY) {
125 nfiles = rl.rlim_cur - 1;
130 if ((epfd = epoll_create(nfiles)) == -1) {
132 event_warn(
"epoll_create");
136 FD_CLOSEONEXEC(epfd);
138 if (!(epollop = calloc(1,
sizeof(
struct epollop))))
141 epollop->epfd = epfd;
144 epollop->events = malloc(nfiles *
sizeof(
struct epoll_event));
145 if (epollop->events == NULL) {
149 epollop->nevents = nfiles;
151 epollop->fds = calloc(nfiles,
sizeof(
struct evepoll));
152 if (epollop->fds == NULL) {
153 free(epollop->events);
157 epollop->nfds = nfiles;
165 epoll_recalc(
struct event_base *base,
void *arg,
int max)
167 struct epollop *epollop = arg;
169 if (max >= epollop->nfds) {
173 nfds = epollop->nfds;
177 fds = realloc(epollop->fds, nfds *
sizeof(
struct evepoll));
179 event_warn(
"realloc");
183 memset(fds + epollop->nfds, 0,
184 (nfds - epollop->nfds) *
sizeof(
struct evepoll));
185 epollop->nfds = nfds;
194 struct epollop *epollop = arg;
195 struct epoll_event *events = epollop->events;
197 int i, res, timeout = -1;
200 timeout = tv->tv_sec * 1000 + (tv->tv_usec + 999) / 1000;
202 if (timeout > MAX_EPOLL_TIMEOUT_MSEC) {
205 timeout = MAX_EPOLL_TIMEOUT_MSEC;
208 res = epoll_wait(epollop->epfd, events, epollop->nevents, timeout);
211 if (errno != EINTR) {
212 event_warn(
"epoll_wait");
216 evsignal_process(base);
218 }
else if (base->sig.evsignal_caught) {
219 evsignal_process(base);
222 event_debug((
"%s: epoll_wait reports %d", __func__, res));
224 for (i = 0; i < res; i++) {
225 int what = events[
i].events;
226 struct event *evread = NULL, *evwrite = NULL;
227 int fd = events[
i].data.fd;
229 if (fd < 0 || fd >= epollop->nfds)
231 evep = &epollop->fds[fd];
233 if (what & (EPOLLHUP|EPOLLERR)) {
234 evread = evep->evread;
235 evwrite = evep->evwrite;
237 if (what & EPOLLIN) {
238 evread = evep->evread;
241 if (what & EPOLLOUT) {
242 evwrite = evep->evwrite;
246 if (!(evread||evwrite))
250 event_active(evread, EV_READ, 1);
252 event_active(evwrite, EV_WRITE, 1);
260 epoll_add(
void *arg,
struct event *ev)
262 struct epollop *epollop = arg;
263 struct epoll_event epev = {0, {0}};
267 if (ev->ev_events & EV_SIGNAL)
268 return (evsignal_add(ev));
271 if (fd >= epollop->nfds) {
273 if (epoll_recalc(ev->ev_base, epollop, fd) == -1)
276 evep = &epollop->fds[fd];
279 if (evep->evread != NULL) {
283 if (evep->evwrite != NULL) {
288 if (ev->ev_events & EV_READ)
290 if (ev->ev_events & EV_WRITE)
294 epev.events = events;
295 if (epoll_ctl(epollop->epfd, op, ev->ev_fd, &epev) == -1)
299 if (ev->ev_events & EV_READ)
301 if (ev->ev_events & EV_WRITE)
308 epoll_del(
void *arg,
struct event *ev)
310 struct epollop *epollop = arg;
311 struct epoll_event epev = {0, {0}};
314 int needwritedelete = 1, needreaddelete = 1;
316 if (ev->ev_events & EV_SIGNAL)
317 return (evsignal_del(ev));
320 if (fd >= epollop->nfds)
322 evep = &epollop->fds[fd];
327 if (ev->ev_events & EV_READ)
329 if (ev->ev_events & EV_WRITE)
332 if ((events & (EPOLLIN|EPOLLOUT)) != (EPOLLIN|EPOLLOUT)) {
333 if ((events & EPOLLIN) && evep->evwrite != NULL) {
337 }
else if ((events & EPOLLOUT) && evep->evread != NULL) {
344 epev.events = events;
350 evep->evwrite = NULL;
352 if (epoll_ctl(epollop->epfd, op, fd, &epev) == -1)
359 epoll_dealloc(
struct event_base *base,
void *arg)
361 struct epollop *epollop = arg;
363 evsignal_dealloc(base);
367 free(epollop->events);
368 if (epollop->epfd >= 0)
369 close(epollop->epfd);
371 memset(epollop, 0,
sizeof(
struct epollop));