src/event/modules/ngx_epoll_module.c - nginx source code

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 EPOLLERR       0x008
  14. #define EPOLLHUP       0x010
  15. #define EPOLLRDNORM    0x040
  16. #define EPOLLRDBAND    0x080
  17. #define EPOLLWRNORM    0x100
  18. #define EPOLLWRBAND    0x200
  19. #define EPOLLMSG       0x400

  20. #define EPOLLRDHUP     0x2000

  21. #define EPOLLEXCLUSIVE 0x10000000
  22. #define EPOLLONESHOT   0x40000000
  23. #define EPOLLET        0x80000000

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

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

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


  37. int epoll_create(int size);

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


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

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


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

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

  52. #if (NGX_HAVE_EVENTFD)
  53. #define SYS_eventfd       323
  54. #endif

  55. #if (NGX_HAVE_FILE_AIO)

  56. #define SYS_io_setup      245
  57. #define SYS_io_destroy    246
  58. #define SYS_io_getevents  247

  59. typedef u_int  aio_context_t;

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


  66. #endif
  67. #endif /* NGX_TEST_BUILD_EPOLL */


  68. typedef struct {
  69.     ngx_uint_t  events;
  70.     ngx_uint_t  aio_requests;
  71. } ngx_epoll_conf_t;


  72. static ngx_int_t ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer);
  73. #if (NGX_HAVE_EVENTFD)
  74. static ngx_int_t ngx_epoll_notify_init(ngx_log_t *log);
  75. static void ngx_epoll_notify_handler(ngx_event_t *ev);
  76. #endif
  77. #if (NGX_HAVE_EPOLLRDHUP)
  78. static void ngx_epoll_test_rdhup(ngx_cycle_t *cycle);
  79. #endif
  80. static void ngx_epoll_done(ngx_cycle_t *cycle);
  81. static ngx_int_t ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event,
  82.     ngx_uint_t flags);
  83. static ngx_int_t ngx_epoll_del_event(ngx_event_t *ev, ngx_int_t event,
  84.     ngx_uint_t flags);
  85. static ngx_int_t ngx_epoll_add_connection(ngx_connection_t *c);
  86. static ngx_int_t ngx_epoll_del_connection(ngx_connection_t *c,
  87.     ngx_uint_t flags);
  88. #if (NGX_HAVE_EVENTFD)
  89. static ngx_int_t ngx_epoll_notify(ngx_event_handler_pt handler);
  90. #endif
  91. static ngx_int_t ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
  92.     ngx_uint_t flags);

  93. #if (NGX_HAVE_FILE_AIO)
  94. static void ngx_epoll_eventfd_handler(ngx_event_t *ev);
  95. #endif

  96. static void *ngx_epoll_create_conf(ngx_cycle_t *cycle);
  97. static char *ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf);

  98. static int                  ep = -1;
  99. static struct epoll_event  *event_list;
  100. static ngx_uint_t           nevents;

  101. #if (NGX_HAVE_EVENTFD)
  102. static int                  notify_fd = -1;
  103. static ngx_event_t          notify_event;
  104. static ngx_connection_t     notify_conn;
  105. #endif

  106. #if (NGX_HAVE_FILE_AIO)

  107. int                         ngx_eventfd = -1;
  108. aio_context_t               ngx_aio_ctx = 0;

  109. static ngx_event_t          ngx_eventfd_event;
  110. static ngx_connection_t     ngx_eventfd_conn;

  111. #endif

  112. #if (NGX_HAVE_EPOLLRDHUP)
  113. ngx_uint_t                  ngx_use_epoll_rdhup;
  114. #endif

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

  116. static ngx_command_t  ngx_epoll_commands[] = {

  117.     { ngx_string("epoll_events"),
  118.       NGX_EVENT_CONF|NGX_CONF_TAKE1,
  119.       ngx_conf_set_num_slot,
  120.       0,
  121.       offsetof(ngx_epoll_conf_t, events),
  122.       NULL },

  123.     { ngx_string("worker_aio_requests"),
  124.       NGX_EVENT_CONF|NGX_CONF_TAKE1,
  125.       ngx_conf_set_num_slot,
  126.       0,
  127.       offsetof(ngx_epoll_conf_t, aio_requests),
  128.       NULL },

  129.       ngx_null_command
  130. };


  131. static ngx_event_module_t  ngx_epoll_module_ctx = {
  132.     &epoll_name,
  133.     ngx_epoll_create_conf,               /* create configuration */
  134.     ngx_epoll_init_conf,                 /* init configuration */

  135.     {
  136.         ngx_epoll_add_event,             /* add an event */
  137.         ngx_epoll_del_event,             /* delete an event */
  138.         ngx_epoll_add_event,             /* enable an event */
  139.         ngx_epoll_del_event,             /* disable an event */
  140.         ngx_epoll_add_connection,        /* add an connection */
  141.         ngx_epoll_del_connection,        /* delete an connection */
  142. #if (NGX_HAVE_EVENTFD)
  143.         ngx_epoll_notify,                /* trigger a notify */
  144. #else
  145.         NULL,                            /* trigger a notify */
  146. #endif
  147.         ngx_epoll_process_events,        /* process the events */
  148.         ngx_epoll_init,                  /* init the events */
  149.         ngx_epoll_done,                  /* done the events */
  150.     }
  151. };

  152. ngx_module_t  ngx_epoll_module = {
  153.     NGX_MODULE_V1,
  154.     &ngx_epoll_module_ctx,               /* module context */
  155.     ngx_epoll_commands,                  /* module directives */
  156.     NGX_EVENT_MODULE,                    /* module type */
  157.     NULL,                                /* init master */
  158.     NULL,                                /* init module */
  159.     NULL,                                /* init process */
  160.     NULL,                                /* init thread */
  161.     NULL,                                /* exit thread */
  162.     NULL,                                /* exit process */
  163.     NULL,                                /* exit master */
  164.     NGX_MODULE_V1_PADDING
  165. };


  166. #if (NGX_HAVE_FILE_AIO)

  167. /*
  168. * We call io_setup(), io_destroy() io_submit(), and io_getevents() directly
  169. * as syscalls instead of libaio usage, because the library header file
  170. * supports eventfd() since 0.3.107 version only.
  171. */

  172. static int
  173. io_setup(u_int nr_reqs, aio_context_t *ctx)
  174. {
  175.     return syscall(SYS_io_setup, nr_reqs, ctx);
  176. }


  177. static int
  178. io_destroy(aio_context_t ctx)
  179. {
  180.     return syscall(SYS_io_destroy, ctx);
  181. }


  182. static int
  183. io_getevents(aio_context_t ctx, long min_nr, long nr, struct io_event *events,
  184.     struct timespec *tmo)
  185. {
  186.     return syscall(SYS_io_getevents, ctx, min_nr, nr, events, tmo);
  187. }


  188. static void
  189. ngx_epoll_aio_init(ngx_cycle_t *cycle, ngx_epoll_conf_t *epcf)
  190. {
  191.     int                 n;
  192.     struct epoll_event  ee;

  193. #if (NGX_HAVE_SYS_EVENTFD_H)
  194.     ngx_eventfd = eventfd(0, 0);
  195. #else
  196.     ngx_eventfd = syscall(SYS_eventfd, 0);
  197. #endif

  198.     if (ngx_eventfd == -1) {
  199.         ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  200.                       "eventfd() failed");
  201.         ngx_file_aio = 0;
  202.         return;
  203.     }

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

  206.     n = 1;

  207.     if (ioctl(ngx_eventfd, FIONBIO, &n) == -1) {
  208.         ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  209.                       "ioctl(eventfd, FIONBIO) failed");
  210.         goto failed;
  211.     }

  212.     if (io_setup(epcf->aio_requests, &ngx_aio_ctx) == -1) {
  213.         ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  214.                       "io_setup() failed");
  215.         goto failed;
  216.     }

  217.     ngx_eventfd_event.data = &ngx_eventfd_conn;
  218.     ngx_eventfd_event.handler = ngx_epoll_eventfd_handler;
  219.     ngx_eventfd_event.log = cycle->log;
  220.     ngx_eventfd_event.active = 1;
  221.     ngx_eventfd_conn.fd = ngx_eventfd;
  222.     ngx_eventfd_conn.read = &ngx_eventfd_event;
  223.     ngx_eventfd_conn.log = cycle->log;

  224.     ee.events = EPOLLIN|EPOLLET;
  225.     ee.data.ptr = &ngx_eventfd_conn;

  226.     if (epoll_ctl(ep, EPOLL_CTL_ADD, ngx_eventfd, &ee) != -1) {
  227.         return;
  228.     }

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

  231.     if (io_destroy(ngx_aio_ctx) == -1) {
  232.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  233.                       "io_destroy() failed");
  234.     }

  235. failed:

  236.     if (close(ngx_eventfd) == -1) {
  237.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  238.                       "eventfd close() failed");
  239.     }

  240.     ngx_eventfd = -1;
  241.     ngx_aio_ctx = 0;
  242.     ngx_file_aio = 0;
  243. }

  244. #endif


  245. static ngx_int_t
  246. ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
  247. {
  248.     ngx_epoll_conf_t  *epcf;

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

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

  252.         if (ep == -1) {
  253.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  254.                           "epoll_create() failed");
  255.             return NGX_ERROR;
  256.         }

  257. #if (NGX_HAVE_EVENTFD)
  258.         if (ngx_epoll_notify_init(cycle->log) != NGX_OK) {
  259.             ngx_epoll_module_ctx.actions.notify = NULL;
  260.         }
  261. #endif

  262. #if (NGX_HAVE_FILE_AIO)
  263.         ngx_epoll_aio_init(cycle, epcf);
  264. #endif

  265. #if (NGX_HAVE_EPOLLRDHUP)
  266.         ngx_epoll_test_rdhup(cycle);
  267. #endif
  268.     }

  269.     if (nevents < epcf->events) {
  270.         if (event_list) {
  271.             ngx_free(event_list);
  272.         }

  273.         event_list = ngx_alloc(sizeof(struct epoll_event) * epcf->events,
  274.                                cycle->log);
  275.         if (event_list == NULL) {
  276.             return NGX_ERROR;
  277.         }
  278.     }

  279.     nevents = epcf->events;

  280.     ngx_io = ngx_os_io;

  281.     ngx_event_actions = ngx_epoll_module_ctx.actions;

  282. #if (NGX_HAVE_CLEAR_EVENT)
  283.     ngx_event_flags = NGX_USE_CLEAR_EVENT
  284. #else
  285.     ngx_event_flags = NGX_USE_LEVEL_EVENT
  286. #endif
  287.                       |NGX_USE_GREEDY_EVENT
  288.                       |NGX_USE_EPOLL_EVENT;

  289.     return NGX_OK;
  290. }


  291. #if (NGX_HAVE_EVENTFD)

  292. static ngx_int_t
  293. ngx_epoll_notify_init(ngx_log_t *log)
  294. {
  295.     struct epoll_event  ee;

  296. #if (NGX_HAVE_SYS_EVENTFD_H)
  297.     notify_fd = eventfd(0, 0);
  298. #else
  299.     notify_fd = syscall(SYS_eventfd, 0);
  300. #endif

  301.     if (notify_fd == -1) {
  302.         ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "eventfd() failed");
  303.         return NGX_ERROR;
  304.     }

  305.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
  306.                    "notify eventfd: %d", notify_fd);

  307.     notify_event.handler = ngx_epoll_notify_handler;
  308.     notify_event.log = log;
  309.     notify_event.active = 1;

  310.     notify_conn.fd = notify_fd;
  311.     notify_conn.read = &notify_event;
  312.     notify_conn.log = log;

  313.     ee.events = EPOLLIN|EPOLLET;
  314.     ee.data.ptr = &notify_conn;

  315.     if (epoll_ctl(ep, EPOLL_CTL_ADD, notify_fd, &ee) == -1) {
  316.         ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
  317.                       "epoll_ctl(EPOLL_CTL_ADD, eventfd) failed");

  318.         if (close(notify_fd) == -1) {
  319.             ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
  320.                             "eventfd close() failed");
  321.         }

  322.         return NGX_ERROR;
  323.     }

  324.     return NGX_OK;
  325. }


  326. static void
  327. ngx_epoll_notify_handler(ngx_event_t *ev)
  328. {
  329.     ssize_t               n;
  330.     uint64_t              count;
  331.     ngx_err_t             err;
  332.     ngx_event_handler_pt  handler;

  333.     if (++ev->index == NGX_MAX_UINT32_VALUE) {
  334.         ev->index = 0;

  335.         n = read(notify_fd, &count, sizeof(uint64_t));

  336.         err = ngx_errno;

  337.         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  338.                        "read() eventfd %d: %z count:%uL", notify_fd, n, count);

  339.         if ((size_t) n != sizeof(uint64_t)) {
  340.             ngx_log_error(NGX_LOG_ALERT, ev->log, err,
  341.                           "read() eventfd %d failed", notify_fd);
  342.         }
  343.     }

  344.     handler = ev->data;
  345.     handler(ev);
  346. }

  347. #endif


  348. #if (NGX_HAVE_EPOLLRDHUP)

  349. static void
  350. ngx_epoll_test_rdhup(ngx_cycle_t *cycle)
  351. {
  352.     int                 s[2], events;
  353.     struct epoll_event  ee;

  354.     if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == -1) {
  355.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  356.                       "socketpair() failed");
  357.         return;
  358.     }

  359.     ee.events = EPOLLET|EPOLLIN|EPOLLRDHUP;

  360.     if (epoll_ctl(ep, EPOLL_CTL_ADD, s[0], &ee) == -1) {
  361.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  362.                       "epoll_ctl() failed");
  363.         goto failed;
  364.     }

  365.     if (close(s[1]) == -1) {
  366.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  367.                       "close() failed");
  368.         s[1] = -1;
  369.         goto failed;
  370.     }

  371.     s[1] = -1;

  372.     events = epoll_wait(ep, &ee, 1, 5000);

  373.     if (events == -1) {
  374.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  375.                       "epoll_wait() failed");
  376.         goto failed;
  377.     }

  378.     if (events) {
  379.         ngx_use_epoll_rdhup = ee.events & EPOLLRDHUP;

  380.     } else {
  381.         ngx_log_error(NGX_LOG_ALERT, cycle->log, NGX_ETIMEDOUT,
  382.                       "epoll_wait() timed out");
  383.     }

  384.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  385.                    "testing the EPOLLRDHUP flag: %s",
  386.                    ngx_use_epoll_rdhup ? "success" : "fail");

  387. failed:

  388.     if (s[1] != -1 && close(s[1]) == -1) {
  389.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  390.                       "close() failed");
  391.     }

  392.     if (close(s[0]) == -1) {
  393.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  394.                       "close() failed");
  395.     }
  396. }

  397. #endif


  398. static void
  399. ngx_epoll_done(ngx_cycle_t *cycle)
  400. {
  401.     if (close(ep) == -1) {
  402.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  403.                       "epoll close() failed");
  404.     }

  405.     ep = -1;

  406. #if (NGX_HAVE_EVENTFD)

  407.     if (close(notify_fd) == -1) {
  408.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  409.                       "eventfd close() failed");
  410.     }

  411.     notify_fd = -1;

  412. #endif

  413. #if (NGX_HAVE_FILE_AIO)

  414.     if (ngx_eventfd != -1) {

  415.         if (io_destroy(ngx_aio_ctx) == -1) {
  416.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  417.                           "io_destroy() failed");
  418.         }

  419.         if (close(ngx_eventfd) == -1) {
  420.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  421.                           "eventfd close() failed");
  422.         }

  423.         ngx_eventfd = -1;
  424.     }

  425.     ngx_aio_ctx = 0;

  426. #endif

  427.     ngx_free(event_list);

  428.     event_list = NULL;
  429.     nevents = 0;
  430. }


  431. static ngx_int_t
  432. ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
  433. {
  434.     int                  op;
  435.     uint32_t             events, prev;
  436.     ngx_event_t         *e;
  437.     ngx_connection_t    *c;
  438.     struct epoll_event   ee;

  439.     c = ev->data;

  440.     events = (uint32_t) event;

  441.     if (event == NGX_READ_EVENT) {
  442.         e = c->write;
  443.         prev = EPOLLOUT;
  444. #if (NGX_READ_EVENT != EPOLLIN|EPOLLRDHUP)
  445.         events = EPOLLIN|EPOLLRDHUP;
  446. #endif

  447.     } else {
  448.         e = c->read;
  449.         prev = EPOLLIN|EPOLLRDHUP;
  450. #if (NGX_WRITE_EVENT != EPOLLOUT)
  451.         events = EPOLLOUT;
  452. #endif
  453.     }

  454.     if (e->active) {
  455.         op = EPOLL_CTL_MOD;
  456.         events |= prev;

  457.     } else {
  458.         op = EPOLL_CTL_ADD;
  459.     }

  460. #if (NGX_HAVE_EPOLLEXCLUSIVE && NGX_HAVE_EPOLLRDHUP)
  461.     if (flags & NGX_EXCLUSIVE_EVENT) {
  462.         events &= ~EPOLLRDHUP;
  463.     }
  464. #endif

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

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

  470.     if (epoll_ctl(ep, op, c->fd, &ee) == -1) {
  471.         ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
  472.                       "epoll_ctl(%d, %d) failed", op, c->fd);
  473.         return NGX_ERROR;
  474.     }

  475.     ev->active = 1;
  476. #if 0
  477.     ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1 : 0;
  478. #endif

  479.     return NGX_OK;
  480. }


  481. static ngx_int_t
  482. ngx_epoll_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
  483. {
  484.     int                  op;
  485.     uint32_t             prev;
  486.     ngx_event_t         *e;
  487.     ngx_connection_t    *c;
  488.     struct epoll_event   ee;

  489.     /*
  490.      * when the file descriptor is closed, the epoll automatically deletes
  491.      * it from its queue, so we do not need to delete explicitly the event
  492.      * before the closing the file descriptor
  493.      */

  494.     if (flags & NGX_CLOSE_EVENT) {
  495.         ev->active = 0;
  496.         return NGX_OK;
  497.     }

  498.     c = ev->data;

  499.     if (event == NGX_READ_EVENT) {
  500.         e = c->write;
  501.         prev = EPOLLOUT;

  502.     } else {
  503.         e = c->read;
  504.         prev = EPOLLIN|EPOLLRDHUP;
  505.     }

  506.     if (e->active) {
  507.         op = EPOLL_CTL_MOD;
  508.         ee.events = prev | (uint32_t) flags;
  509.         ee.data.ptr = (void *) ((uintptr_t) c | ev->instance);

  510.     } else {
  511.         op = EPOLL_CTL_DEL;
  512.         ee.events = 0;
  513.         ee.data.ptr = NULL;
  514.     }

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

  518.     if (epoll_ctl(ep, op, c->fd, &ee) == -1) {
  519.         ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
  520.                       "epoll_ctl(%d, %d) failed", op, c->fd);
  521.         return NGX_ERROR;
  522.     }

  523.     ev->active = 0;

  524.     return NGX_OK;
  525. }


  526. static ngx_int_t
  527. ngx_epoll_add_connection(ngx_connection_t *c)
  528. {
  529.     struct epoll_event  ee;

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

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

  534.     if (epoll_ctl(ep, EPOLL_CTL_ADD, c->fd, &ee) == -1) {
  535.         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
  536.                       "epoll_ctl(EPOLL_CTL_ADD, %d) failed", c->fd);
  537.         return NGX_ERROR;
  538.     }

  539.     c->read->active = 1;
  540.     c->write->active = 1;

  541.     return NGX_OK;
  542. }


  543. static ngx_int_t
  544. ngx_epoll_del_connection(ngx_connection_t *c, ngx_uint_t flags)
  545. {
  546.     int                 op;
  547.     struct epoll_event  ee;

  548.     /*
  549.      * when the file descriptor is closed the epoll automatically deletes
  550.      * it from its queue so we do not need to delete explicitly the event
  551.      * before the closing the file descriptor
  552.      */

  553.     if (flags & NGX_CLOSE_EVENT) {
  554.         c->read->active = 0;
  555.         c->write->active = 0;
  556.         return NGX_OK;
  557.     }

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

  560.     op = EPOLL_CTL_DEL;
  561.     ee.events = 0;
  562.     ee.data.ptr = NULL;

  563.     if (epoll_ctl(ep, op, c->fd, &ee) == -1) {
  564.         ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
  565.                       "epoll_ctl(%d, %d) failed", op, c->fd);
  566.         return NGX_ERROR;
  567.     }

  568.     c->read->active = 0;
  569.     c->write->active = 0;

  570.     return NGX_OK;
  571. }


  572. #if (NGX_HAVE_EVENTFD)

  573. static ngx_int_t
  574. ngx_epoll_notify(ngx_event_handler_pt handler)
  575. {
  576.     static uint64_t inc = 1;

  577.     notify_event.data = handler;

  578.     if ((size_t) write(notify_fd, &inc, sizeof(uint64_t)) != sizeof(uint64_t)) {
  579.         ngx_log_error(NGX_LOG_ALERT, notify_event.log, ngx_errno,
  580.                       "write() to eventfd %d failed", notify_fd);
  581.         return NGX_ERROR;
  582.     }

  583.     return NGX_OK;
  584. }

  585. #endif


  586. static ngx_int_t
  587. ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
  588. {
  589.     int                events;
  590.     uint32_t           revents;
  591.     ngx_int_t          instance, i;
  592.     ngx_uint_t         level;
  593.     ngx_err_t          err;
  594.     ngx_event_t       *rev, *wev;
  595.     ngx_queue_t       *queue;
  596.     ngx_connection_t  *c;

  597.     /* NGX_TIMER_INFINITE == INFTIM */

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

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

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

  602.     if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
  603.         ngx_time_update();
  604.     }

  605.     if (err) {
  606.         if (err == NGX_EINTR) {

  607.             if (ngx_event_timer_alarm) {
  608.                 ngx_event_timer_alarm = 0;
  609.                 return NGX_OK;
  610.             }

  611.             level = NGX_LOG_INFO;

  612.         } else {
  613.             level = NGX_LOG_ALERT;
  614.         }

  615.         ngx_log_error(level, cycle->log, err, "epoll_wait() failed");
  616.         return NGX_ERROR;
  617.     }

  618.     if (events == 0) {
  619.         if (timer != NGX_TIMER_INFINITE) {
  620.             return NGX_OK;
  621.         }

  622.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  623.                       "epoll_wait() returned no events without timeout");
  624.         return NGX_ERROR;
  625.     }

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

  628.         instance = (uintptr_t) c & 1;
  629.         c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);

  630.         rev = c->read;

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

  632.             /*
  633.              * the stale event from a file descriptor
  634.              * that was just closed in this iteration
  635.              */

  636.             ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  637.                            "epoll: stale event %p", c);
  638.             continue;
  639.         }

  640.         revents = event_list[i].events;

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

  644.         if (revents & (EPOLLERR|EPOLLHUP)) {
  645.             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  646.                            "epoll_wait() error on fd:%d ev:%04XD",
  647.                            c->fd, revents);

  648.             /*
  649.              * if the error events were returned, add EPOLLIN and EPOLLOUT
  650.              * to handle the events at least in one active handler
  651.              */

  652.             revents |= EPOLLIN|EPOLLOUT;
  653.         }

  654. #if 0
  655.         if (revents & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) {
  656.             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  657.                           "strange epoll_wait() events fd:%d ev:%04XD",
  658.                           c->fd, revents);
  659.         }
  660. #endif

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

  662. #if (NGX_HAVE_EPOLLRDHUP)
  663.             if (revents & EPOLLRDHUP) {
  664.                 rev->pending_eof = 1;
  665.             }
  666. #endif

  667.             rev->ready = 1;
  668.             rev->available = -1;

  669.             if (flags & NGX_POST_EVENTS) {
  670.                 queue = rev->accept ? &ngx_posted_accept_events
  671.                                     : &ngx_posted_events;

  672.                 ngx_post_event(rev, queue);

  673.             } else {
  674.                 rev->handler(rev);
  675.             }
  676.         }

  677.         wev = c->write;

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

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

  680.                 /*
  681.                  * the stale event from a file descriptor
  682.                  * that was just closed in this iteration
  683.                  */

  684.                 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  685.                                "epoll: stale event %p", c);
  686.                 continue;
  687.             }

  688.             wev->ready = 1;
  689. #if (NGX_THREADS)
  690.             wev->complete = 1;
  691. #endif

  692.             if (flags & NGX_POST_EVENTS) {
  693.                 ngx_post_event(wev, &ngx_posted_events);

  694.             } else {
  695.                 wev->handler(wev);
  696.             }
  697.         }
  698.     }

  699.     return NGX_OK;
  700. }


  701. #if (NGX_HAVE_FILE_AIO)

  702. static void
  703. ngx_epoll_eventfd_handler(ngx_event_t *ev)
  704. {
  705.     int               n, events;
  706.     long              i;
  707.     uint64_t          ready;
  708.     ngx_err_t         err;
  709.     ngx_event_t      *e;
  710.     ngx_event_aio_t  *aio;
  711.     struct io_event   event[64];
  712.     struct timespec   ts;

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

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

  715.     err = ngx_errno;

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

  717.     if (n != 8) {
  718.         if (n == -1) {
  719.             if (err == NGX_EAGAIN) {
  720.                 return;
  721.             }

  722.             ngx_log_error(NGX_LOG_ALERT, ev->log, err, "read(eventfd) failed");
  723.             return;
  724.         }

  725.         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
  726.                       "read(eventfd) returned only %d bytes", n);
  727.         return;
  728.     }

  729.     ts.tv_sec = 0;
  730.     ts.tv_nsec = 0;

  731.     while (ready) {

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

  733.         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  734.                        "io_getevents: %d", events);

  735.         if (events > 0) {
  736.             ready -= events;

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

  738.                 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  739.                                "io_event: %XL %XL %L %L",
  740.                                 event[i].data, event[i].obj,
  741.                                 event[i].res, event[i].res2);

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

  743.                 e->complete = 1;
  744.                 e->active = 0;
  745.                 e->ready = 1;

  746.                 aio = e->data;
  747.                 aio->res = event[i].res;

  748.                 ngx_post_event(e, &ngx_posted_events);
  749.             }

  750.             continue;
  751.         }

  752.         if (events == 0) {
  753.             return;
  754.         }

  755.         /* events == -1 */
  756.         ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
  757.                       "io_getevents() failed");
  758.         return;
  759.     }
  760. }

  761. #endif


  762. static void *
  763. ngx_epoll_create_conf(ngx_cycle_t *cycle)
  764. {
  765.     ngx_epoll_conf_t  *epcf;

  766.     epcf = ngx_palloc(cycle->pool, sizeof(ngx_epoll_conf_t));
  767.     if (epcf == NULL) {
  768.         return NULL;
  769.     }

  770.     epcf->events = NGX_CONF_UNSET;
  771.     epcf->aio_requests = NGX_CONF_UNSET;

  772.     return epcf;
  773. }


  774. static char *
  775. ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf)
  776. {
  777.     ngx_epoll_conf_t *epcf = conf;

  778.     ngx_conf_init_uint_value(epcf->events, 512);
  779.     ngx_conf_init_uint_value(epcf->aio_requests, 32);

  780.     return NGX_CONF_OK;
  781. }