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

Global variables defined

Data types defined

Functions 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. typedef struct {
  9.     ngx_uint_t  changes;
  10.     ngx_uint_t  events;
  11. } ngx_kqueue_conf_t;


  12. static ngx_int_t ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer);
  13. static void ngx_kqueue_done(ngx_cycle_t *cycle);
  14. static ngx_int_t ngx_kqueue_add_event(ngx_event_t *ev, ngx_int_t event,
  15.     ngx_uint_t flags);
  16. static ngx_int_t ngx_kqueue_del_event(ngx_event_t *ev, ngx_int_t event,
  17.     ngx_uint_t flags);
  18. static ngx_int_t ngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter,
  19.     ngx_uint_t flags);
  20. static ngx_int_t ngx_kqueue_process_changes(ngx_cycle_t *cycle, ngx_uint_t try);
  21. static ngx_int_t ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
  22.     ngx_uint_t flags);
  23. static ngx_inline void ngx_kqueue_dump_event(ngx_log_t *log,
  24.     struct kevent *kev);

  25. static void *ngx_kqueue_create_conf(ngx_cycle_t *cycle);
  26. static char *ngx_kqueue_init_conf(ngx_cycle_t *cycle, void *conf);


  27. int                    ngx_kqueue = -1;

  28. /*
  29. * The "change_list" should be declared as ngx_thread_volatile.
  30. * However, the use of the change_list is localized in kqueue functions and
  31. * is protected by the mutex so even the "icc -ipo" should not build the code
  32. * with the race condition.  Thus we avoid the declaration to make a more
  33. * readable code.
  34. */

  35. static struct kevent  *change_list, *change_list0, *change_list1;
  36. static struct kevent  *event_list;
  37. static ngx_uint_t      max_changes, nchanges, nevents;

  38. #if (NGX_THREADS)
  39. static ngx_mutex_t    *list_mutex;
  40. static ngx_mutex_t    *kevent_mutex;
  41. #endif



  42. static ngx_str_t      kqueue_name = ngx_string("kqueue");

  43. static ngx_command_t  ngx_kqueue_commands[] = {

  44.     { ngx_string("kqueue_changes"),
  45.       NGX_EVENT_CONF|NGX_CONF_TAKE1,
  46.       ngx_conf_set_num_slot,
  47.       0,
  48.       offsetof(ngx_kqueue_conf_t, changes),
  49.       NULL },

  50.     { ngx_string("kqueue_events"),
  51.       NGX_EVENT_CONF|NGX_CONF_TAKE1,
  52.       ngx_conf_set_num_slot,
  53.       0,
  54.       offsetof(ngx_kqueue_conf_t, events),
  55.       NULL },

  56.       ngx_null_command
  57. };


  58. ngx_event_module_t  ngx_kqueue_module_ctx = {
  59.     &kqueue_name,
  60.     ngx_kqueue_create_conf,                /* create configuration */
  61.     ngx_kqueue_init_conf,                  /* init configuration */

  62.     {
  63.         ngx_kqueue_add_event,              /* add an event */
  64.         ngx_kqueue_del_event,              /* delete an event */
  65.         ngx_kqueue_add_event,              /* enable an event */
  66.         ngx_kqueue_del_event,              /* disable an event */
  67.         NULL,                              /* add an connection */
  68.         NULL,                              /* delete an connection */
  69.         ngx_kqueue_process_changes,        /* process the changes */
  70.         ngx_kqueue_process_events,         /* process the events */
  71.         ngx_kqueue_init,                   /* init the events */
  72.         ngx_kqueue_done                    /* done the events */
  73.     }

  74. };

  75. ngx_module_t  ngx_kqueue_module = {
  76.     NGX_MODULE_V1,
  77.     &ngx_kqueue_module_ctx,                /* module context */
  78.     ngx_kqueue_commands,                   /* module directives */
  79.     NGX_EVENT_MODULE,                      /* module type */
  80.     NULL,                                  /* init master */
  81.     NULL,                                  /* init module */
  82.     NULL,                                  /* init process */
  83.     NULL,                                  /* init thread */
  84.     NULL,                                  /* exit thread */
  85.     NULL,                                  /* exit process */
  86.     NULL,                                  /* exit master */
  87.     NGX_MODULE_V1_PADDING
  88. };


  89. static ngx_int_t
  90. ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer)
  91. {
  92.     ngx_kqueue_conf_t  *kcf;
  93.     struct timespec     ts;
  94. #if (NGX_HAVE_TIMER_EVENT)
  95.     struct kevent       kev;
  96. #endif

  97.     kcf = ngx_event_get_conf(cycle->conf_ctx, ngx_kqueue_module);

  98.     if (ngx_kqueue == -1) {
  99.         ngx_kqueue = kqueue();

  100.         if (ngx_kqueue == -1) {
  101.             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
  102.                           "kqueue() failed");
  103.             return NGX_ERROR;
  104.         }

  105. #if (NGX_THREADS)

  106.         list_mutex = ngx_mutex_init(cycle->log, 0);
  107.         if (list_mutex == NULL) {
  108.             return NGX_ERROR;
  109.         }

  110.         kevent_mutex = ngx_mutex_init(cycle->log, 0);
  111.         if (kevent_mutex == NULL) {
  112.             return NGX_ERROR;
  113.         }

  114. #endif
  115.     }

  116.     if (max_changes < kcf->changes) {
  117.         if (nchanges) {
  118.             ts.tv_sec = 0;
  119.             ts.tv_nsec = 0;

  120.             if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)
  121.                 == -1)
  122.             {
  123.                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  124.                               "kevent() failed");
  125.                 return NGX_ERROR;
  126.             }
  127.             nchanges = 0;
  128.         }

  129.         if (change_list0) {
  130.             ngx_free(change_list0);
  131.         }

  132.         change_list0 = ngx_alloc(kcf->changes * sizeof(struct kevent),
  133.                                  cycle->log);
  134.         if (change_list0 == NULL) {
  135.             return NGX_ERROR;
  136.         }

  137.         if (change_list1) {
  138.             ngx_free(change_list1);
  139.         }

  140.         change_list1 = ngx_alloc(kcf->changes * sizeof(struct kevent),
  141.                                  cycle->log);
  142.         if (change_list1 == NULL) {
  143.             return NGX_ERROR;
  144.         }

  145.         change_list = change_list0;
  146.     }

  147.     max_changes = kcf->changes;

  148.     if (nevents < kcf->events) {
  149.         if (event_list) {
  150.             ngx_free(event_list);
  151.         }

  152.         event_list = ngx_alloc(kcf->events * sizeof(struct kevent), cycle->log);
  153.         if (event_list == NULL) {
  154.             return NGX_ERROR;
  155.         }
  156.     }

  157.     ngx_event_flags = NGX_USE_ONESHOT_EVENT
  158.                       |NGX_USE_KQUEUE_EVENT
  159.                       |NGX_USE_VNODE_EVENT;

  160. #if (NGX_HAVE_TIMER_EVENT)

  161.     if (timer) {
  162.         kev.ident = 0;
  163.         kev.filter = EVFILT_TIMER;
  164.         kev.flags = EV_ADD|EV_ENABLE;
  165.         kev.fflags = 0;
  166.         kev.data = timer;
  167.         kev.udata = 0;

  168.         ts.tv_sec = 0;
  169.         ts.tv_nsec = 0;

  170.         if (kevent(ngx_kqueue, &kev, 1, NULL, 0, &ts) == -1) {
  171.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  172.                           "kevent(EVFILT_TIMER) failed");
  173.             return NGX_ERROR;
  174.         }

  175.         ngx_event_flags |= NGX_USE_TIMER_EVENT;
  176.     }

  177. #endif

  178. #if (NGX_HAVE_CLEAR_EVENT)
  179.     ngx_event_flags |= NGX_USE_CLEAR_EVENT;
  180. #else
  181.     ngx_event_flags |= NGX_USE_LEVEL_EVENT;
  182. #endif

  183. #if (NGX_HAVE_LOWAT_EVENT)
  184.     ngx_event_flags |= NGX_USE_LOWAT_EVENT;
  185. #endif

  186.     nevents = kcf->events;

  187.     ngx_io = ngx_os_io;

  188.     ngx_event_actions = ngx_kqueue_module_ctx.actions;

  189.     return NGX_OK;
  190. }


  191. static void
  192. ngx_kqueue_done(ngx_cycle_t *cycle)
  193. {
  194.     if (close(ngx_kqueue) == -1) {
  195.         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
  196.                       "kqueue close() failed");
  197.     }

  198.     ngx_kqueue = -1;

  199. #if (NGX_THREADS)
  200.     ngx_mutex_destroy(kevent_mutex);
  201.     ngx_mutex_destroy(list_mutex);
  202. #endif

  203.     ngx_free(change_list1);
  204.     ngx_free(change_list0);
  205.     ngx_free(event_list);

  206.     change_list1 = NULL;
  207.     change_list0 = NULL;
  208.     change_list = NULL;
  209.     event_list = NULL;
  210.     max_changes = 0;
  211.     nchanges = 0;
  212.     nevents = 0;
  213. }


  214. static ngx_int_t
  215. ngx_kqueue_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
  216. {
  217.     ngx_int_t          rc;
  218. #if 0
  219.     ngx_event_t       *e;
  220.     ngx_connection_t  *c;
  221. #endif

  222.     ev->active = 1;
  223.     ev->disabled = 0;
  224.     ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1 : 0;

  225.     ngx_mutex_lock(list_mutex);

  226. #if 0

  227.     if (ev->index < nchanges
  228.         && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1)
  229.             == (uintptr_t) ev)
  230.     {
  231.         if (change_list[ev->index].flags == EV_DISABLE) {

  232.             /*
  233.              * if the EV_DISABLE is still not passed to a kernel
  234.              * we will not pass it
  235.              */

  236.             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  237.                            "kevent activated: %d: ft:%i",
  238.                            ngx_event_ident(ev->data), event);

  239.             if (ev->index < --nchanges) {
  240.                 e = (ngx_event_t *)
  241.                     ((uintptr_t) change_list[nchanges].udata & (uintptr_t) ~1);
  242.                 change_list[ev->index] = change_list[nchanges];
  243.                 e->index = ev->index;
  244.             }

  245.             ngx_mutex_unlock(list_mutex);

  246.             return NGX_OK;
  247.         }

  248.         c = ev->data;

  249.         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
  250.                       "previous event on #%d were not passed in kernel", c->fd);

  251.         ngx_mutex_unlock(list_mutex);

  252.         return NGX_ERROR;
  253.     }

  254. #endif

  255.     rc = ngx_kqueue_set_event(ev, event, EV_ADD|EV_ENABLE|flags);

  256.     ngx_mutex_unlock(list_mutex);

  257.     return rc;
  258. }


  259. static ngx_int_t
  260. ngx_kqueue_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
  261. {
  262.     ngx_int_t     rc;
  263.     ngx_event_t  *e;

  264.     ev->active = 0;
  265.     ev->disabled = 0;

  266.     ngx_mutex_lock(list_mutex);

  267.     if (ev->index < nchanges
  268.         && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1)
  269.             == (uintptr_t) ev)
  270.     {
  271.         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  272.                        "kevent deleted: %d: ft:%i",
  273.                        ngx_event_ident(ev->data), event);

  274.         /* if the event is still not passed to a kernel we will not pass it */

  275.         nchanges--;

  276.         if (ev->index < nchanges) {
  277.             e = (ngx_event_t *)
  278.                     ((uintptr_t) change_list[nchanges].udata & (uintptr_t) ~1);
  279.             change_list[ev->index] = change_list[nchanges];
  280.             e->index = ev->index;
  281.         }

  282.         ngx_mutex_unlock(list_mutex);

  283.         return NGX_OK;
  284.     }

  285.     /*
  286.      * when the file descriptor is closed the kqueue automatically deletes
  287.      * its filters so we do not need to delete explicitly the event
  288.      * before the closing the file descriptor.
  289.      */

  290.     if (flags & NGX_CLOSE_EVENT) {
  291.         ngx_mutex_unlock(list_mutex);
  292.         return NGX_OK;
  293.     }

  294.     if (flags & NGX_DISABLE_EVENT) {
  295.         ev->disabled = 1;

  296.     } else {
  297.         flags |= EV_DELETE;
  298.     }

  299.     rc = ngx_kqueue_set_event(ev, event, flags);

  300.     ngx_mutex_unlock(list_mutex);

  301.     return rc;
  302. }


  303. static ngx_int_t
  304. ngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter, ngx_uint_t flags)
  305. {
  306.     struct kevent     *kev;
  307.     struct timespec    ts;
  308.     ngx_connection_t  *c;

  309.     c = ev->data;

  310.     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
  311.                    "kevent set event: %d: ft:%i fl:%04Xi",
  312.                    c->fd, filter, flags);

  313.     if (nchanges >= max_changes) {
  314.         ngx_log_error(NGX_LOG_WARN, ev->log, 0,
  315.                       "kqueue change list is filled up");

  316.         ts.tv_sec = 0;
  317.         ts.tv_nsec = 0;

  318.         if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)
  319.             == -1)
  320.         {
  321.             ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent() failed");
  322.             return NGX_ERROR;
  323.         }

  324.         nchanges = 0;
  325.     }

  326.     kev = &change_list[nchanges];

  327.     kev->ident = c->fd;
  328.     kev->filter = (short) filter;
  329.     kev->flags = (u_short) flags;
  330.     kev->udata = NGX_KQUEUE_UDATA_T ((uintptr_t) ev | ev->instance);

  331.     if (filter == EVFILT_VNODE) {
  332.         kev->fflags = NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND
  333.                                  |NOTE_ATTRIB|NOTE_RENAME
  334. #if (__FreeBSD__ == 4 && __FreeBSD_version >= 430000) \
  335.     || __FreeBSD_version >= 500018
  336.                                  |NOTE_REVOKE
  337. #endif
  338.                       ;
  339.         kev->data = 0;

  340.     } else {
  341. #if (NGX_HAVE_LOWAT_EVENT)
  342.         if (flags & NGX_LOWAT_EVENT) {
  343.             kev->fflags = NOTE_LOWAT;
  344.             kev->data = ev->available;

  345.         } else {
  346.             kev->fflags = 0;
  347.             kev->data = 0;
  348.         }
  349. #else
  350.         kev->fflags = 0;
  351.         kev->data = 0;
  352. #endif
  353.     }

  354.     ev->index = nchanges;
  355.     nchanges++;

  356.     if (flags & NGX_FLUSH_EVENT) {
  357.         ts.tv_sec = 0;
  358.         ts.tv_nsec = 0;

  359.         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "kevent flush");

  360.         if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)
  361.             == -1)
  362.         {
  363.             ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent() failed");
  364.             return NGX_ERROR;
  365.         }

  366.         nchanges = 0;
  367.     }

  368.     return NGX_OK;
  369. }


  370. static ngx_int_t
  371. ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
  372.     ngx_uint_t flags)
  373. {
  374.     int               events, n;
  375.     ngx_int_t         i, instance;
  376.     ngx_uint_t        level;
  377.     ngx_err_t         err;
  378.     ngx_event_t      *ev;
  379.     ngx_queue_t      *queue;
  380.     struct timespec   ts, *tp;

  381.     if (ngx_threaded) {
  382.         if (ngx_kqueue_process_changes(cycle, 0) == NGX_ERROR) {
  383.             return NGX_ERROR;
  384.         }

  385.         n = 0;

  386.     } else {
  387.         n = (int) nchanges;
  388.         nchanges = 0;
  389.     }

  390.     if (timer == NGX_TIMER_INFINITE) {
  391.         tp = NULL;

  392.     } else {

  393.         ts.tv_sec = timer / 1000;
  394.         ts.tv_nsec = (timer % 1000) * 1000000;

  395.         /*
  396.          * 64-bit Darwin kernel has the bug: kernel level ts.tv_nsec is
  397.          * the int32_t while user level ts.tv_nsec is the long (64-bit),
  398.          * so on the big endian PowerPC all nanoseconds are lost.
  399.          */

  400. #if (NGX_DARWIN_KEVENT_BUG)
  401.         ts.tv_nsec <<= 32;
  402. #endif

  403.         tp = &ts;
  404.     }

  405.     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  406.                    "kevent timer: %M, changes: %d", timer, n);

  407.     events = kevent(ngx_kqueue, change_list, n, event_list, (int) nevents, tp);

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

  409.     if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
  410.         ngx_time_update();
  411.     }

  412.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  413.                    "kevent events: %d", events);

  414.     if (err) {
  415.         if (err == NGX_EINTR) {

  416.             if (ngx_event_timer_alarm) {
  417.                 ngx_event_timer_alarm = 0;
  418.                 return NGX_OK;
  419.             }

  420.             level = NGX_LOG_INFO;

  421.         } else {
  422.             level = NGX_LOG_ALERT;
  423.         }

  424.         ngx_log_error(level, cycle->log, err, "kevent() failed");
  425.         return NGX_ERROR;
  426.     }

  427.     if (events == 0) {
  428.         if (timer != NGX_TIMER_INFINITE) {
  429.             return NGX_OK;
  430.         }

  431.         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  432.                       "kevent() returned no events without timeout");
  433.         return NGX_ERROR;
  434.     }

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

  436.         ngx_kqueue_dump_event(cycle->log, &event_list[i]);

  437.         if (event_list[i].flags & EV_ERROR) {
  438.             ngx_log_error(NGX_LOG_ALERT, cycle->log, event_list[i].data,
  439.                           "kevent() error on %d filter:%d flags:%04Xd",
  440.                           event_list[i].ident, event_list[i].filter,
  441.                           event_list[i].flags);
  442.             continue;
  443.         }

  444. #if (NGX_HAVE_TIMER_EVENT)

  445.         if (event_list[i].filter == EVFILT_TIMER) {
  446.             ngx_time_update();
  447.             continue;
  448.         }

  449. #endif

  450.         ev = (ngx_event_t *) event_list[i].udata;

  451.         switch (event_list[i].filter) {

  452.         case EVFILT_READ:
  453.         case EVFILT_WRITE:

  454.             instance = (uintptr_t) ev & 1;
  455.             ev = (ngx_event_t *) ((uintptr_t) ev & (uintptr_t) ~1);

  456.             if (ev->closed || ev->instance != instance) {

  457.                 /*
  458.                  * the stale event from a file descriptor
  459.                  * that was just closed in this iteration
  460.                  */

  461.                 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  462.                                "kevent: stale event %p", ev);
  463.                 continue;
  464.             }

  465.             if (ev->log && (ev->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
  466.                 ngx_kqueue_dump_event(ev->log, &event_list[i]);
  467.             }

  468.             if (ev->oneshot) {
  469.                 ev->active = 0;
  470.             }

  471.             ev->available = event_list[i].data;

  472.             if (event_list[i].flags & EV_EOF) {
  473.                 ev->pending_eof = 1;
  474.                 ev->kq_errno = event_list[i].fflags;
  475.             }

  476.             ev->ready = 1;

  477.             break;

  478.         case EVFILT_VNODE:
  479.             ev->kq_vnode = 1;

  480.             break;

  481.         case EVFILT_AIO:
  482.             ev->complete = 1;
  483.             ev->ready = 1;

  484.             break;

  485.         default:
  486.             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
  487.                           "unexpected kevent() filter %d",
  488.                           event_list[i].filter);
  489.             continue;
  490.         }

  491.         if (flags & NGX_POST_EVENTS) {
  492.             queue = ev->accept ? &ngx_posted_accept_events
  493.                                : &ngx_posted_events;

  494.             ngx_post_event(ev, queue);

  495.             continue;
  496.         }

  497.         ev->handler(ev);
  498.     }

  499.     return NGX_OK;
  500. }


  501. static ngx_int_t
  502. ngx_kqueue_process_changes(ngx_cycle_t *cycle, ngx_uint_t try)
  503. {
  504.     int               n;
  505.     ngx_int_t         rc;
  506.     ngx_err_t         err;
  507.     struct timespec   ts;
  508.     struct kevent    *changes;

  509.     ngx_mutex_lock(kevent_mutex);

  510.     ngx_mutex_lock(list_mutex);

  511.     if (nchanges == 0) {
  512.         ngx_mutex_unlock(list_mutex);
  513.         ngx_mutex_unlock(kevent_mutex);
  514.         return NGX_OK;
  515.     }

  516.     changes = change_list;
  517.     if (change_list == change_list0) {
  518.         change_list = change_list1;
  519.     } else {
  520.         change_list = change_list0;
  521.     }

  522.     n = (int) nchanges;
  523.     nchanges = 0;

  524.     ngx_mutex_unlock(list_mutex);

  525.     ts.tv_sec = 0;
  526.     ts.tv_nsec = 0;

  527.     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
  528.                    "kevent changes: %d", n);

  529.     if (kevent(ngx_kqueue, changes, n, NULL, 0, &ts) == -1) {
  530.         err = ngx_errno;
  531.         ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
  532.                       cycle->log, err, "kevent() failed");
  533.         rc = NGX_ERROR;

  534.     } else {
  535.         rc = NGX_OK;
  536.     }

  537.     ngx_mutex_unlock(kevent_mutex);

  538.     return rc;
  539. }


  540. static ngx_inline void
  541. ngx_kqueue_dump_event(ngx_log_t *log, struct kevent *kev)
  542. {
  543.     ngx_log_debug6(NGX_LOG_DEBUG_EVENT, log, 0,
  544.                    (kev->ident > 0x8000000 && kev->ident != (unsigned) -1) ?
  545.                     "kevent: %p: ft:%d fl:%04Xd ff:%08Xd d:%d ud:%p":
  546.                     "kevent: %d: ft:%d fl:%04Xd ff:%08Xd d:%d ud:%p",
  547.                     kev->ident, kev->filter,
  548.                     kev->flags, kev->fflags,
  549.                     kev->data, kev->udata);
  550. }


  551. static void *
  552. ngx_kqueue_create_conf(ngx_cycle_t *cycle)
  553. {
  554.     ngx_kqueue_conf_t  *kcf;

  555.     kcf = ngx_palloc(cycle->pool, sizeof(ngx_kqueue_conf_t));
  556.     if (kcf == NULL) {
  557.         return NULL;
  558.     }

  559.     kcf->changes = NGX_CONF_UNSET;
  560.     kcf->events = NGX_CONF_UNSET;

  561.     return kcf;
  562. }


  563. static char *
  564. ngx_kqueue_init_conf(ngx_cycle_t *cycle, void *conf)
  565. {
  566.     ngx_kqueue_conf_t *kcf = conf;

  567.     ngx_conf_init_uint_value(kcf->changes, 512);
  568.     ngx_conf_init_uint_value(kcf->events, 512);

  569.     return NGX_CONF_OK;
  570. }