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));