src/event/modules/ngx_epoll_module.c - nginx-1.7.10

Global variables defined

Data types defined

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>
  7. #include <ngx_event.h>


  8. #if (NGX_TEST_BUILD_EPOLL)

  9. /* epoll declarations */

  10. #define EPOLLIN        0x001
  11. #define EPOLLPRI       0x002
  12. #define EPOLLOUT       0x004
  13. #define EPOLLRDNORM    0x040
  14. #define EPOLLRDBAND    0x080
  15. #define EPOLLWRNORM    0x100
  16. #define EPOLLWRBAND    0x200
  17. #define EPOLLMSG       0x400
  18. #define EPOLLERR       0x008
  19. #define EPOLLHUP       0x010

  20. #define EPOLLRDHUP     0x2000

  21. #define EPOLLET        0x80000000
  22. #define EPOLLONESHOT   0x40000000

  23. #define EPOLL_CTL_ADD  1
  24. #define EPOLL_CTL_DEL  2
  25. #define EPOLL_CTL_MOD  3

  26. typedef union epoll_data {
  27.     void         *ptr;
  28.     int           fd;
  29.     uint32_t      u32;
  30.     uint64_t      u64;
  31. } epoll_data_t;

  32. struct epoll_event {
  33.     uint32_t      events;
  34.     epoll_data_t  data;
  35. };


  36. int epoll_create(int size);

  37. int epoll_create(int size)
  38. {
  39.     return -1;
  40. }


  41. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

  42. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
  43. {
  44.     return -1;
  45. }


  46. int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout);

  47. int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout)
  48. {
  49.     return -1;
  50. }

  51. #if (NGX_HAVE_FILE_AIO)

  52. #define SYS_io_setup      245
  53. #define SYS_io_destroy    246
  54. #define SYS_io_getevents  247
  55. #define SYS_eventfd       323

  56. typedef u_int  aio_context_t;

  57. struct io_event {
  58.     uint64_t  data;  /* the data field from the iocb */
  59.     uint64_t  obj;   /* what iocb this event came from */
  60.     int64_t   res;   /* result code for this event */
  61.     int64_t   res2;  /* secondary result */
  62. };


  63. #endif
  64. #endif


  65. typedef struct {
  66.     ngx_uint_t  events;
  67.     ngx_uint_t  aio_requests;
  68. } ngx_epoll_conf_t;


  69. static ngx_int_t ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer);
  70. static void ngx_epoll_done(ngx_cycle_t *cycle);
  71. static ngx_int_t ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event,
  72.     ngx_uint_t flags);
  73. static ngx_int_t ngx_epoll_del_event(ngx_event_t *ev, ngx_int_t event,
  74.     ngx_uint_t flags);
  75. static ngx_int_t ngx_epoll_add_connection(ngx_connection_t *c);
  76. static ngx_int_t ngx_epoll_del_connection(ngx_connection_t *c,
  77.     ngx_uint_t flags);
  78. static ngx_int_t ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
  79.     ngx_uint_t flags);

  80. #if (NGX_HAVE_FILE_AIO)
  81. static void ngx_epoll_eventfd_handler(ngx_event_t *ev);
  82. #endif

  83. static void *ngx_epoll_create_conf(ngx_cycle_t *cycle);
  84. static char *ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf);

  85. static int                  ep = -1;
  86. static struct epoll_event  *event_list;
  87. static ngx_uint_t           nevents;

  88. #if (NGX_HAVE_FILE_AIO)

  89. int                         ngx_eventfd = -1;
  90. aio_context_t               ngx_aio_ctx = 0;

  91. static ngx_event_t          ngx_eventfd_event;
  92. static ngx_connection_t     ngx_eventfd_conn;

  93. #endif

  94. static ngx_str_t      epoll_name = ngx_string("epoll");

  95. static ngx_command_t  ngx_epoll_commands[] = {

  96.     { ngx_string("epoll_events"),
  97.       NGX_EVENT_CONF|NGX_CONF_TAKE1,
  98.       ngx_conf_set_num_slot,
  99.       0,
  100.       offsetof(ngx_epoll_conf_t, events),
  101.       NULL },

  102.     { ngx_string("worker_aio_requests"),
  103.       NGX_EVENT_CONF|NGX_CONF_TAKE1,
  104.       ngx_conf_set_num_slot,
  105.       0,
  106.       offsetof(ngx_epoll_conf_t, aio_requests),
  107.       NULL },

  108.       ngx_null_command
  109. };


  110. ngx_event_module_t  ngx_epoll_module_ctx = {
  111.     &epoll_name,
  112.     ngx_epoll_create_conf,               /* create configuration */
  113.     ngx_epoll_init_conf,                 /* init configuration */

  114.     {
  115.         ngx_epoll_add_event,             /* add an event */
  116.         ngx_epoll_del_event,             /* delete an event */
  117.         ngx_epoll_add_event,             /* enable an event */
  118.         ngx_epoll_del_event,             /* disable an event */
  119.         ngx_epoll_add_connection,        /* add an connection */
  120.         ngx_epoll_del_connection,        /* delete an connection */
  121.         NULL,                            /* process the changes */
  122.         ngx_epoll_process_events,        /* process the events */
  123.         ngx_epoll_init,                  /* init the events */
  124.         ngx_epoll_done,                  /* done the events */
  125.     }
  126. };

  127. ngx_module_t  ngx_epoll_module = {
  128.     NGX_MODULE_V1,
  129.     &ngx_epoll_module_ctx,               /* module context */
  130.     ngx_epoll_commands,                  /* module directives */
  131.     NGX_EVENT_MODULE,                    /* module type */
  132.     NULL,                                /* init master */
  133.     NULL,                                /* init module */
  134.     NULL,                                /* init process */
  135.     NULL,                                /* init thread */
  136.     NULL,                                /* exit thread */
  137.     NULL,                                /* exit process */
  138.     NULL,                                /* exit master */
  139.     NGX_MODULE_V1_PADDING
  140. };


  141. #if (NGX_HAVE_FILE_AIO)

  142. /*
  143. * We call io_setup(), io_destroy() io_submit(), and io_getevents() directly
  144. * as syscalls instead of libaio usage, because the library header file
  145. * supports eventfd() since 0.3.107 version only.
  146. */

  147. static int
  148. io_setup(u_int nr_reqs, aio_context_t *ctx)
  149. {
  150.     return syscall(SYS_io_setup, nr_reqs, ctx);
  151. }


  152. static int
  153. io_destroy(aio_context_t ctx)
  154. {
  155.     return syscall(SYS_io_destroy, ctx);
  156. }


  157. static int
  158. io_getevents(aio_context_t ctx, long min_nr, long nr, struct io_event *events,
  159.     struct timespec *tmo)
  160. {
  161.     return syscall(SYS_io_getevents, ctx, min_nr, nr, events, tmo);
  162. }


  163. static void
  164. ngx_epoll_aio_init(ngx_cycle_t *cycle, ngx_epoll_conf_t *epcf)
  165. {
  166.     int                 n;
  167.     struct epoll_event  ee;

  168. #if (NGX_HAVE_SYS_EVENTFD_H)
  169.     ngx_eventfd = eventfd(0, 0);
  170. #else
  171.     ngx_eventfd = syscall(SYS_eventfd, 0);
  172. #endif

  173.     if (ngx_eventfd == -1) {
  174.         ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  175.                       "eventfd() failed");
  176.         ngx_file_aio = 0;
  177.         return;
  178.     }

  179.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  180.                    "eventfd: %d", ngx_eventfd);

  181.     n = 1;

  182.     if (ioctl(ngx_eventfd, FIONBIO, &n) == -1) {
  183.         ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  184.                       "ioctl(eventfd, FIONBIO) failed");
  185.         goto failed;
  186.     }

  187.     if (io_setup(epcf->aio_requests, &ngx_aio_ctx) == -1) {
  188.         ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  189.                       "io_setup() failed");
  190.         goto failed;
  191.     }

  192.     ngx_eventfd_event.data = &ngx_eventfd_conn;
  193.     ngx_eventfd_event.handler = ngx_epoll_eventfd_handler;
  194.     ngx_eventfd_event.log = cycle->log;
  195.     ngx_eventfd_event.active = 1;
  196.     ngx_eventfd_conn.fd = ngx_eventfd;
  197.     ngx_eventfd_conn.read = &ngx_eventfd_event;
  198.     ngx_eventfd_conn.log = cycle->log;

  199.     ee.events = EPOLLIN|EPOLLET;
  200.     ee.data.ptr = &ngx_eventfd_conn;

  201.     if (epoll_ctl(ep, EPOLL_CTL_ADD, ngx_eventfd, &ee) != -1) {
  202.         return;
  203.     }

  204.     ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  205.                   "epoll_ctl(EPOLL_CTL_ADD, eventfd) failed");

  206.     if (io_destroy(ngx_aio_ctx) == -1) {
  207.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  208.                       "io_destroy() failed");
  209.     }

  210. failed:

  211.     if (close(ngx_eventfd) == -1) {
  212.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  213.                       "eventfd close() failed");
  214.     }

  215.     ngx_eventfd = -1;
  216.     ngx_aio_ctx = 0;
  217.     ngx_file_aio = 0;
  218. }

  219. #endif


  220. static ngx_int_t
  221. ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
  222. {
  223.     ngx_epoll_conf_t  *epcf;

  224.     epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);

  225.     if (ep == -1) {
  226.         ep = epoll_create(cycle->connection_n / 2);

  227.         if (ep == -1) {
  228.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  229.                           "epoll_create() failed");
  230.             return NGX_ERROR;
  231.         }

  232. #if (NGX_HAVE_FILE_AIO)

  233.         ngx_epoll_aio_init(cycle, epcf);

  234. #endif
  235.     }

  236.     if (nevents < epcf->events) {
  237.         if (event_list) {
  238.             ngx_free(event_list);
  239.         }

  240.         event_list = ngx_alloc(sizeof(struct epoll_event) * epcf->events,
  241.                                cycle->log);
  242.         if (event_list == NULL) {
  243.             return NGX_ERROR;
  244.         }
  245.     }

  246.     nevents = epcf->events;

  247.     ngx_io = ngx_os_io;

  248.     ngx_event_actions = ngx_epoll_module_ctx.actions;

  249. #if (NGX_HAVE_CLEAR_EVENT)
  250.     ngx_event_flags = NGX_USE_CLEAR_EVENT
  251. #else
  252.     ngx_event_flags = NGX_USE_LEVEL_EVENT
  253. #endif
  254.                       |NGX_USE_GREEDY_EVENT
  255.                       |NGX_USE_EPOLL_EVENT;

  256.     return NGX_OK;
  257. }


  258. static void
  259. ngx_epoll_done(ngx_cycle_t *cycle)
  260. {
  261.     if (close(ep) == -1) {
  262.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  263.                       "epoll close() failed");
  264.     }

  265.     ep = -1;

  266. #if (NGX_HAVE_FILE_AIO)

  267.     if (ngx_eventfd != -1) {

  268.         if (io_destroy(ngx_aio_ctx) == -1) {
  269.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  270.                           "io_destroy() failed");
  271.         }

  272.         if (close(ngx_eventfd) == -1) {
  273.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  274.                           "eventfd close() failed");
  275.         }

  276.         ngx_eventfd = -1;
  277.     }

  278.     ngx_aio_ctx = 0;

  279. #endif

  280.     ngx_free(event_list);

  281.     event_list = NULL;
  282.     nevents = 0;
  283. }


  284. static ngx_int_t
  285. ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
  286. {
  287.     int                  op;
  288.     uint32_t             events, prev;
  289.     ngx_event_t         *e;
  290.     ngx_connection_t    *c;
  291.     struct epoll_event   ee;

  292.     c = ev->data;

  293.     events = (uint32_t) event;

  294.     if (event == NGX_READ_EVENT) {
  295.         e = c->write;
  296.         prev = EPOLLOUT;
  297. #if (NGX_READ_EVENT != EPOLLIN|EPOLLRDHUP)
  298.         events = EPOLLIN|EPOLLRDHUP;
  299. #endif

  300.     } else {
  301.         e = c->read;
  302.         prev = EPOLLIN|EPOLLRDHUP;
  303. #if (NGX_WRITE_EVENT != EPOLLOUT)
  304.         events = EPOLLOUT;
  305. #endif
  306.     }

  307.     if (e->active) {
  308.         op = EPOLL_CTL_MOD;
  309.         events |= prev;

  310.     } else {
  311.         op = EPOLL_CTL_ADD;
  312.     }

  313.     ee.events = events | (uint32_t) flags;
  314.     ee.data.ptr = (void *) ((uintptr_t) c | ev->instance);

  315.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  316.                    "epoll add event: fd:%d op:%d ev:%08XD",
  317.                    c->fd, op, ee.events);

  318.     if (epoll_ctl(ep, op, c->fd, &ee) == -1) {
  319.         ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
  320.                       "epoll_ctl(%d, %d) failed", op, c->fd);
  321.         return NGX_ERROR;
  322.     }

  323.     ev->active = 1;
  324. #if 0
  325.     ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1 : 0;
  326. #endif

  327.     return NGX_OK;
  328. }


  329. static ngx_int_t
  330. ngx_epoll_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
  331. {
  332.     int                  op;
  333.     uint32_t             prev;
  334.     ngx_event_t         *e;
  335.     ngx_connection_t    *c;
  336.     struct epoll_event   ee;

  337.     /*
  338.      * when the file descriptor is closed, the epoll automatically deletes
  339.      * it from its queue, so we do not need to delete explicitly the event
  340.      * before the closing the file descriptor
  341.      */

  342.     if (flags & NGX_CLOSE_EVENT) {
  343.         ev->active = 0;
  344.         return NGX_OK;
  345.     }

  346.     c = ev->data;

  347.     if (event == NGX_READ_EVENT) {
  348.         e = c->write;
  349.         prev = EPOLLOUT;

  350.     } else {
  351.         e = c->read;
  352.         prev = EPOLLIN|EPOLLRDHUP;
  353.     }

  354.     if (e->active) {
  355.         op = EPOLL_CTL_MOD;
  356.         ee.events = prev | (uint32_t) flags;
  357.         ee.data.ptr = (void *) ((uintptr_t) c | ev->instance);

  358.     } else {
  359.         op = EPOLL_CTL_DEL;
  360.         ee.events = 0;
  361.         ee.data.ptr = NULL;
  362.     }

  363.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  364.                    "epoll del event: fd:%d op:%d ev:%08XD",
  365.                    c->fd, op, ee.events);

  366.     if (epoll_ctl(ep, op, c->fd, &ee) == -1) {
  367.         ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
  368.                       "epoll_ctl(%d, %d) failed", op, c->fd);
  369.         return NGX_ERROR;
  370.     }

  371.     ev->active = 0;

  372.     return NGX_OK;
  373. }


  374. static ngx_int_t
  375. ngx_epoll_add_connection(ngx_connection_t *c)
  376. {
  377.     struct epoll_event  ee;

  378.     ee.events = EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP;
  379.     ee.data.ptr = (void *) ((uintptr_t) c | c->read->instance);

  380.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
  381.                    "epoll add connection: fd:%d ev:%08XD", c->fd, ee.events);

  382.     if (epoll_ctl(ep, EPOLL_CTL_ADD, c->fd, &ee) == -1) {
  383.         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
  384.                       "epoll_ctl(EPOLL_CTL_ADD, %d) failed", c->fd);
  385.         return NGX_ERROR;
  386.     }

  387.     c->read->active = 1;
  388.     c->write->active = 1;

  389.     return NGX_OK;
  390. }


  391. static ngx_int_t
  392. ngx_epoll_del_connection(ngx_connection_t *c, ngx_uint_t flags)
  393. {
  394.     int                 op;
  395.     struct epoll_event  ee;

  396.     /*
  397.      * when the file descriptor is closed the epoll automatically deletes
  398.      * it from its queue so we do not need to delete explicitly the event
  399.      * before the closing the file descriptor
  400.      */

  401.     if (flags & NGX_CLOSE_EVENT) {
  402.         c->read->active = 0;
  403.         c->write->active = 0;
  404.         return NGX_OK;
  405.     }

  406.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
  407.                    "epoll del connection: fd:%d", c->fd);

  408.     op = EPOLL_CTL_DEL;
  409.     ee.events = 0;
  410.     ee.data.ptr = NULL;

  411.     if (epoll_ctl(ep, op, c->fd, &ee) == -1) {
  412.         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
  413.                       "epoll_ctl(%d, %d) failed", op, c->fd);
  414.         return NGX_ERROR;
  415.     }

  416.     c->read->active = 0;
  417.     c->write->active = 0;

  418.     return NGX_OK;
  419. }


  420. static ngx_int_t
  421. ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
  422. {
  423.     int                events;
  424.     uint32_t           revents;
  425.     ngx_int_t          instance, i;
  426.     ngx_uint_t         level;
  427.     ngx_err_t          err;
  428.     ngx_event_t       *rev, *wev;
  429.     ngx_queue_t       *queue;
  430.     ngx_connection_t  *c;

  431.     /* NGX_TIMER_INFINITE == INFTIM */

  432.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  433.                    "epoll timer: %M", timer);

  434.     events = epoll_wait(ep, event_list, (int) nevents, timer);

  435.     err = (events == -1) ? ngx_errno : 0;

  436.     if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
  437.         ngx_time_update();
  438.     }

  439.     if (err) {
  440.         if (err == NGX_EINTR) {

  441.             if (ngx_event_timer_alarm) {
  442.                 ngx_event_timer_alarm = 0;
  443.                 return NGX_OK;
  444.             }

  445.             level = NGX_LOG_INFO;

  446.         } else {
  447.             level = NGX_LOG_ALERT;
  448.         }

  449.         ngx_log_error(level, cycle->log, err, "epoll_wait() failed");
  450.         return NGX_ERROR;
  451.     }

  452.     if (events == 0) {
  453.         if (timer != NGX_TIMER_INFINITE) {
  454.             return NGX_OK;
  455.         }

  456.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  457.                       "epoll_wait() returned no events without timeout");
  458.         return NGX_ERROR;
  459.     }

  460.     for (i = 0; i < events; i++) {
  461.         c = event_list[i].data.ptr;

  462.         instance = (uintptr_t) c & 1;
  463.         c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);

  464.         rev = c->read;

  465.         if (c->fd == -1 || rev->instance != instance) {

  466.             /*
  467.              * the stale event from a file descriptor
  468.              * that was just closed in this iteration
  469.              */

  470.             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  471.                            "epoll: stale event %p", c);
  472.             continue;
  473.         }

  474.         revents = event_list[i].events;

  475.         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  476.                        "epoll: fd:%d ev:%04XD d:%p",
  477.                        c->fd, revents, event_list[i].data.ptr);

  478.         if (revents & (EPOLLERR|EPOLLHUP)) {
  479.             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  480.                            "epoll_wait() error on fd:%d ev:%04XD",
  481.                            c->fd, revents);
  482.         }

  483. #if 0
  484.         if (revents & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) {
  485.             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  486.                           "strange epoll_wait() events fd:%d ev:%04XD",
  487.                           c->fd, revents);
  488.         }
  489. #endif

  490.         if ((revents & (EPOLLERR|EPOLLHUP))
  491.              && (revents & (EPOLLIN|EPOLLOUT)) == 0)
  492.         {
  493.             /*
  494.              * if the error events were returned without EPOLLIN or EPOLLOUT,
  495.              * then add these flags to handle the events at least in one
  496.              * active handler
  497.              */

  498.             revents |= EPOLLIN|EPOLLOUT;
  499.         }

  500.         if ((revents & EPOLLIN) && rev->active) {

  501. #if (NGX_HAVE_EPOLLRDHUP)
  502.             if (revents & EPOLLRDHUP) {
  503.                 rev->pending_eof = 1;
  504.             }
  505. #endif

  506.             rev->ready = 1;

  507.             if (flags & NGX_POST_EVENTS) {
  508.                 queue = rev->accept ? &ngx_posted_accept_events
  509.                                     : &ngx_posted_events;

  510.                 ngx_post_event(rev, queue);

  511.             } else {
  512.                 rev->handler(rev);
  513.             }
  514.         }

  515.         wev = c->write;

  516.         if ((revents & EPOLLOUT) && wev->active) {

  517.             if (c->fd == -1 || wev->instance != instance) {

  518.                 /*
  519.                  * the stale event from a file descriptor
  520.                  * that was just closed in this iteration
  521.                  */

  522.                 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  523.                                "epoll: stale event %p", c);
  524.                 continue;
  525.             }

  526.             wev->ready = 1;

  527.             if (flags & NGX_POST_EVENTS) {
  528.                 ngx_post_event(wev, &ngx_posted_events);

  529.             } else {
  530.                 wev->handler(wev);
  531.             }
  532.         }
  533.     }

  534.     return NGX_OK;
  535. }


  536. #if (NGX_HAVE_FILE_AIO)

  537. static void
  538. ngx_epoll_eventfd_handler(ngx_event_t *ev)
  539. {
  540.     int               n, events;
  541.     long              i;
  542.     uint64_t          ready;
  543.     ngx_err_t         err;
  544.     ngx_event_t      *e;
  545.     ngx_event_aio_t  *aio;
  546.     struct io_event   event[64];
  547.     struct timespec   ts;

  548.     ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "eventfd handler");

  549.     n = read(ngx_eventfd, &ready, 8);

  550.     err = ngx_errno;

  551.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, "eventfd: %d", n);

  552.     if (n != 8) {
  553.         if (n == -1) {
  554.             if (err == NGX_EAGAIN) {
  555.                 return;
  556.             }

  557.             ngx_log_error(NGX_LOG_ALERT, ev->log, err, "read(eventfd) failed");
  558.             return;
  559.         }

  560.         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
  561.                       "read(eventfd) returned only %d bytes", n);
  562.         return;
  563.     }

  564.     ts.tv_sec = 0;
  565.     ts.tv_nsec = 0;

  566.     while (ready) {

  567.         events = io_getevents(ngx_aio_ctx, 1, 64, event, &ts);

  568.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  569.                        "io_getevents: %l", events);

  570.         if (events > 0) {
  571.             ready -= events;

  572.             for (i = 0; i < events; i++) {

  573.                 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  574.                                "io_event: %uXL %uXL %L %L",
  575.                                 event[i].data, event[i].obj,
  576.                                 event[i].res, event[i].res2);

  577.                 e = (ngx_event_t *) (uintptr_t) event[i].data;

  578.                 e->complete = 1;
  579.                 e->active = 0;
  580.                 e->ready = 1;

  581.                 aio = e->data;
  582.                 aio->res = event[i].res;

  583.                 ngx_post_event(e, &ngx_posted_events);
  584.             }

  585.             continue;
  586.         }

  587.         if (events == 0) {
  588.             return;
  589.         }

  590.         /* events == -1 */
  591.         ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
  592.                       "io_getevents() failed");
  593.         return;
  594.     }
  595. }

  596. #endif


  597. static void *
  598. ngx_epoll_create_conf(ngx_cycle_t *cycle)
  599. {
  600.     ngx_epoll_conf_t  *epcf;

  601.     epcf = ngx_palloc(cycle->pool, sizeof(ngx_epoll_conf_t));
  602.     if (epcf == NULL) {
  603.         return NULL;
  604.     }

  605.     epcf->events = NGX_CONF_UNSET;
  606.     epcf->aio_requests = NGX_CONF_UNSET;

  607.     return epcf;
  608. }


  609. static char *
  610. ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf)
  611. {
  612.     ngx_epoll_conf_t *epcf = conf;

  613.     ngx_conf_init_uint_value(epcf->events, 512);
  614.     ngx_conf_init_uint_value(epcf->aio_requests, 32);

  615.     return NGX_CONF_OK;
  616. }