Back to home page

Nginx displayed by LXR

Source navigation ]
Diff markup ]
Identifier search ]
general search ]
 
 
Version: nginx-1.13.12 ]​[ nginx-1.12.2 ]​

0001 
0002 /*
0003  * Copyright (C) Igor Sysoev
0004  * Copyright (C) Nginx, Inc.
0005  */
0006 
0007 
0008 #include <ngx_config.h>
0009 #include <ngx_core.h>
0010 #include <ngx_event.h>
0011 
0012 
0013 typedef struct {
0014     ngx_uint_t  changes;
0015     ngx_uint_t  events;
0016 } ngx_kqueue_conf_t;
0017 
0018 
0019 static ngx_int_t ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer);
0020 #ifdef EVFILT_USER
0021 static ngx_int_t ngx_kqueue_notify_init(ngx_log_t *log);
0022 #endif
0023 static void ngx_kqueue_done(ngx_cycle_t *cycle);
0024 static ngx_int_t ngx_kqueue_add_event(ngx_event_t *ev, ngx_int_t event,
0025     ngx_uint_t flags);
0026 static ngx_int_t ngx_kqueue_del_event(ngx_event_t *ev, ngx_int_t event,
0027     ngx_uint_t flags);
0028 static ngx_int_t ngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter,
0029     ngx_uint_t flags);
0030 #ifdef EVFILT_USER
0031 static ngx_int_t ngx_kqueue_notify(ngx_event_handler_pt handler);
0032 #endif
0033 static ngx_int_t ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
0034     ngx_uint_t flags);
0035 static ngx_inline void ngx_kqueue_dump_event(ngx_log_t *log,
0036     struct kevent *kev);
0037 
0038 static void *ngx_kqueue_create_conf(ngx_cycle_t *cycle);
0039 static char *ngx_kqueue_init_conf(ngx_cycle_t *cycle, void *conf);
0040 
0041 
0042 int                    ngx_kqueue = -1;
0043 
0044 static struct kevent  *change_list;
0045 static struct kevent  *event_list;
0046 static ngx_uint_t      max_changes, nchanges, nevents;
0047 
0048 #ifdef EVFILT_USER
0049 static ngx_event_t     notify_event;
0050 static struct kevent   notify_kev;
0051 #endif
0052 
0053 
0054 static ngx_str_t      kqueue_name = ngx_string("kqueue");
0055 
0056 static ngx_command_t  ngx_kqueue_commands[] = {
0057 
0058     { ngx_string("kqueue_changes"),
0059       NGX_EVENT_CONF|NGX_CONF_TAKE1,
0060       ngx_conf_set_num_slot,
0061       0,
0062       offsetof(ngx_kqueue_conf_t, changes),
0063       NULL },
0064 
0065     { ngx_string("kqueue_events"),
0066       NGX_EVENT_CONF|NGX_CONF_TAKE1,
0067       ngx_conf_set_num_slot,
0068       0,
0069       offsetof(ngx_kqueue_conf_t, events),
0070       NULL },
0071 
0072       ngx_null_command
0073 };
0074 
0075 
0076 static ngx_event_module_t  ngx_kqueue_module_ctx = {
0077     &kqueue_name,
0078     ngx_kqueue_create_conf,                /* create configuration */
0079     ngx_kqueue_init_conf,                  /* init configuration */
0080 
0081     {
0082         ngx_kqueue_add_event,              /* add an event */
0083         ngx_kqueue_del_event,              /* delete an event */
0084         ngx_kqueue_add_event,              /* enable an event */
0085         ngx_kqueue_del_event,              /* disable an event */
0086         NULL,                              /* add an connection */
0087         NULL,                              /* delete an connection */
0088 #ifdef EVFILT_USER
0089         ngx_kqueue_notify,                 /* trigger a notify */
0090 #else
0091         NULL,                              /* trigger a notify */
0092 #endif
0093         ngx_kqueue_process_events,         /* process the events */
0094         ngx_kqueue_init,                   /* init the events */
0095         ngx_kqueue_done                    /* done the events */
0096     }
0097 
0098 };
0099 
0100 ngx_module_t  ngx_kqueue_module = {
0101     NGX_MODULE_V1,
0102     &ngx_kqueue_module_ctx,                /* module context */
0103     ngx_kqueue_commands,                   /* module directives */
0104     NGX_EVENT_MODULE,                      /* module type */
0105     NULL,                                  /* init master */
0106     NULL,                                  /* init module */
0107     NULL,                                  /* init process */
0108     NULL,                                  /* init thread */
0109     NULL,                                  /* exit thread */
0110     NULL,                                  /* exit process */
0111     NULL,                                  /* exit master */
0112     NGX_MODULE_V1_PADDING
0113 };
0114 
0115 
0116 static ngx_int_t
0117 ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer)
0118 {
0119     ngx_kqueue_conf_t  *kcf;
0120     struct timespec     ts;
0121 #if (NGX_HAVE_TIMER_EVENT)
0122     struct kevent       kev;
0123 #endif
0124 
0125     kcf = ngx_event_get_conf(cycle->conf_ctx, ngx_kqueue_module);
0126 
0127     if (ngx_kqueue == -1) {
0128         ngx_kqueue = kqueue();
0129 
0130         if (ngx_kqueue == -1) {
0131             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
0132                           "kqueue() failed");
0133             return NGX_ERROR;
0134         }
0135 
0136 #ifdef EVFILT_USER
0137         if (ngx_kqueue_notify_init(cycle->log) != NGX_OK) {
0138             return NGX_ERROR;
0139         }
0140 #endif
0141     }
0142 
0143     if (max_changes < kcf->changes) {
0144         if (nchanges) {
0145             ts.tv_sec = 0;
0146             ts.tv_nsec = 0;
0147 
0148             if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)
0149                 == -1)
0150             {
0151                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0152                               "kevent() failed");
0153                 return NGX_ERROR;
0154             }
0155             nchanges = 0;
0156         }
0157 
0158         if (change_list) {
0159             ngx_free(change_list);
0160         }
0161 
0162         change_list = ngx_alloc(kcf->changes * sizeof(struct kevent),
0163                                 cycle->log);
0164         if (change_list == NULL) {
0165             return NGX_ERROR;
0166         }
0167     }
0168 
0169     max_changes = kcf->changes;
0170 
0171     if (nevents < kcf->events) {
0172         if (event_list) {
0173             ngx_free(event_list);
0174         }
0175 
0176         event_list = ngx_alloc(kcf->events * sizeof(struct kevent), cycle->log);
0177         if (event_list == NULL) {
0178             return NGX_ERROR;
0179         }
0180     }
0181 
0182     ngx_event_flags = NGX_USE_ONESHOT_EVENT
0183                       |NGX_USE_KQUEUE_EVENT
0184                       |NGX_USE_VNODE_EVENT;
0185 
0186 #if (NGX_HAVE_TIMER_EVENT)
0187 
0188     if (timer) {
0189         kev.ident = 0;
0190         kev.filter = EVFILT_TIMER;
0191         kev.flags = EV_ADD|EV_ENABLE;
0192         kev.fflags = 0;
0193         kev.data = timer;
0194         kev.udata = 0;
0195 
0196         ts.tv_sec = 0;
0197         ts.tv_nsec = 0;
0198 
0199         if (kevent(ngx_kqueue, &kev, 1, NULL, 0, &ts) == -1) {
0200             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0201                           "kevent(EVFILT_TIMER) failed");
0202             return NGX_ERROR;
0203         }
0204 
0205         ngx_event_flags |= NGX_USE_TIMER_EVENT;
0206     }
0207 
0208 #endif
0209 
0210 #if (NGX_HAVE_CLEAR_EVENT)
0211     ngx_event_flags |= NGX_USE_CLEAR_EVENT;
0212 #else
0213     ngx_event_flags |= NGX_USE_LEVEL_EVENT;
0214 #endif
0215 
0216 #if (NGX_HAVE_LOWAT_EVENT)
0217     ngx_event_flags |= NGX_USE_LOWAT_EVENT;
0218 #endif
0219 
0220     nevents = kcf->events;
0221 
0222     ngx_io = ngx_os_io;
0223 
0224     ngx_event_actions = ngx_kqueue_module_ctx.actions;
0225 
0226     return NGX_OK;
0227 }
0228 
0229 
0230 #ifdef EVFILT_USER
0231 
0232 static ngx_int_t
0233 ngx_kqueue_notify_init(ngx_log_t *log)
0234 {
0235     notify_kev.ident = 0;
0236     notify_kev.filter = EVFILT_USER;
0237     notify_kev.data = 0;
0238     notify_kev.flags = EV_ADD|EV_CLEAR;
0239     notify_kev.fflags = 0;
0240     notify_kev.udata = 0;
0241 
0242     if (kevent(ngx_kqueue, &notify_kev, 1, NULL, 0, NULL) == -1) {
0243         ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
0244                       "kevent(EVFILT_USER, EV_ADD) failed");
0245         return NGX_ERROR;
0246     }
0247 
0248     notify_event.active = 1;
0249     notify_event.log = log;
0250 
0251     notify_kev.flags = 0;
0252     notify_kev.fflags = NOTE_TRIGGER;
0253     notify_kev.udata = NGX_KQUEUE_UDATA_T ((uintptr_t) &notify_event);
0254 
0255     return NGX_OK;
0256 }
0257 
0258 #endif
0259 
0260 
0261 static void
0262 ngx_kqueue_done(ngx_cycle_t *cycle)
0263 {
0264     if (close(ngx_kqueue) == -1) {
0265         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
0266                       "kqueue close() failed");
0267     }
0268 
0269     ngx_kqueue = -1;
0270 
0271     ngx_free(change_list);
0272     ngx_free(event_list);
0273 
0274     change_list = NULL;
0275     event_list = NULL;
0276     max_changes = 0;
0277     nchanges = 0;
0278     nevents = 0;
0279 }
0280 
0281 
0282 static ngx_int_t
0283 ngx_kqueue_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
0284 {
0285     ngx_int_t          rc;
0286 #if 0
0287     ngx_event_t       *e;
0288     ngx_connection_t  *c;
0289 #endif
0290 
0291     ev->active = 1;
0292     ev->disabled = 0;
0293     ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1 : 0;
0294 
0295 #if 0
0296 
0297     if (ev->index < nchanges
0298         && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1)
0299             == (uintptr_t) ev)
0300     {
0301         if (change_list[ev->index].flags == EV_DISABLE) {
0302 
0303             /*
0304              * if the EV_DISABLE is still not passed to a kernel
0305              * we will not pass it
0306              */
0307 
0308             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
0309                            "kevent activated: %d: ft:%i",
0310                            ngx_event_ident(ev->data), event);
0311 
0312             if (ev->index < --nchanges) {
0313                 e = (ngx_event_t *)
0314                     ((uintptr_t) change_list[nchanges].udata & (uintptr_t) ~1);
0315                 change_list[ev->index] = change_list[nchanges];
0316                 e->index = ev->index;
0317             }
0318 
0319             return NGX_OK;
0320         }
0321 
0322         c = ev->data;
0323 
0324         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
0325                       "previous event on #%d were not passed in kernel", c->fd);
0326 
0327         return NGX_ERROR;
0328     }
0329 
0330 #endif
0331 
0332     rc = ngx_kqueue_set_event(ev, event, EV_ADD|EV_ENABLE|flags);
0333 
0334     return rc;
0335 }
0336 
0337 
0338 static ngx_int_t
0339 ngx_kqueue_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
0340 {
0341     ngx_int_t     rc;
0342     ngx_event_t  *e;
0343 
0344     ev->active = 0;
0345     ev->disabled = 0;
0346 
0347     if (ev->index < nchanges
0348         && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1)
0349             == (uintptr_t) ev)
0350     {
0351         ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
0352                        "kevent deleted: %d: ft:%i",
0353                        ngx_event_ident(ev->data), event);
0354 
0355         /* if the event is still not passed to a kernel we will not pass it */
0356 
0357         nchanges--;
0358 
0359         if (ev->index < nchanges) {
0360             e = (ngx_event_t *)
0361                     ((uintptr_t) change_list[nchanges].udata & (uintptr_t) ~1);
0362             change_list[ev->index] = change_list[nchanges];
0363             e->index = ev->index;
0364         }
0365 
0366         return NGX_OK;
0367     }
0368 
0369     /*
0370      * when the file descriptor is closed the kqueue automatically deletes
0371      * its filters so we do not need to delete explicitly the event
0372      * before the closing the file descriptor.
0373      */
0374 
0375     if (flags & NGX_CLOSE_EVENT) {
0376         return NGX_OK;
0377     }
0378 
0379     if (flags & NGX_DISABLE_EVENT) {
0380         ev->disabled = 1;
0381 
0382     } else {
0383         flags |= EV_DELETE;
0384     }
0385 
0386     rc = ngx_kqueue_set_event(ev, event, flags);
0387 
0388     return rc;
0389 }
0390 
0391 
0392 static ngx_int_t
0393 ngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter, ngx_uint_t flags)
0394 {
0395     struct kevent     *kev;
0396     struct timespec    ts;
0397     ngx_connection_t  *c;
0398 
0399     c = ev->data;
0400 
0401     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
0402                    "kevent set event: %d: ft:%i fl:%04Xi",
0403                    c->fd, filter, flags);
0404 
0405     if (nchanges >= max_changes) {
0406         ngx_log_error(NGX_LOG_WARN, ev->log, 0,
0407                       "kqueue change list is filled up");
0408 
0409         ts.tv_sec = 0;
0410         ts.tv_nsec = 0;
0411 
0412         if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)
0413             == -1)
0414         {
0415             ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent() failed");
0416             return NGX_ERROR;
0417         }
0418 
0419         nchanges = 0;
0420     }
0421 
0422     kev = &change_list[nchanges];
0423 
0424     kev->ident = c->fd;
0425     kev->filter = (short) filter;
0426     kev->flags = (u_short) flags;
0427     kev->udata = NGX_KQUEUE_UDATA_T ((uintptr_t) ev | ev->instance);
0428 
0429     if (filter == EVFILT_VNODE) {
0430         kev->fflags = NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND
0431                                  |NOTE_ATTRIB|NOTE_RENAME
0432 #if (__FreeBSD__ == 4 && __FreeBSD_version >= 430000) \
0433     || __FreeBSD_version >= 500018
0434                                  |NOTE_REVOKE
0435 #endif
0436                       ;
0437         kev->data = 0;
0438 
0439     } else {
0440 #if (NGX_HAVE_LOWAT_EVENT)
0441         if (flags & NGX_LOWAT_EVENT) {
0442             kev->fflags = NOTE_LOWAT;
0443             kev->data = ev->available;
0444 
0445         } else {
0446             kev->fflags = 0;
0447             kev->data = 0;
0448         }
0449 #else
0450         kev->fflags = 0;
0451         kev->data = 0;
0452 #endif
0453     }
0454 
0455     ev->index = nchanges;
0456     nchanges++;
0457 
0458     if (flags & NGX_FLUSH_EVENT) {
0459         ts.tv_sec = 0;
0460         ts.tv_nsec = 0;
0461 
0462         ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "kevent flush");
0463 
0464         if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)
0465             == -1)
0466         {
0467             ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent() failed");
0468             return NGX_ERROR;
0469         }
0470 
0471         nchanges = 0;
0472     }
0473 
0474     return NGX_OK;
0475 }
0476 
0477 
0478 #ifdef EVFILT_USER
0479 
0480 static ngx_int_t
0481 ngx_kqueue_notify(ngx_event_handler_pt handler)
0482 {
0483     notify_event.handler = handler;
0484 
0485     if (kevent(ngx_kqueue, &notify_kev, 1, NULL, 0, NULL) == -1) {
0486         ngx_log_error(NGX_LOG_ALERT, notify_event.log, ngx_errno,
0487                       "kevent(EVFILT_USER, NOTE_TRIGGER) failed");
0488         return NGX_ERROR;
0489     }
0490 
0491     return NGX_OK;
0492 }
0493 
0494 #endif
0495 
0496 
0497 static ngx_int_t
0498 ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
0499     ngx_uint_t flags)
0500 {
0501     int               events, n;
0502     ngx_int_t         i, instance;
0503     ngx_uint_t        level;
0504     ngx_err_t         err;
0505     ngx_event_t      *ev;
0506     ngx_queue_t      *queue;
0507     struct timespec   ts, *tp;
0508 
0509     n = (int) nchanges;
0510     nchanges = 0;
0511 
0512     if (timer == NGX_TIMER_INFINITE) {
0513         tp = NULL;
0514 
0515     } else {
0516 
0517         ts.tv_sec = timer / 1000;
0518         ts.tv_nsec = (timer % 1000) * 1000000;
0519 
0520         /*
0521          * 64-bit Darwin kernel has the bug: kernel level ts.tv_nsec is
0522          * the int32_t while user level ts.tv_nsec is the long (64-bit),
0523          * so on the big endian PowerPC all nanoseconds are lost.
0524          */
0525 
0526 #if (NGX_DARWIN_KEVENT_BUG)
0527         ts.tv_nsec <<= 32;
0528 #endif
0529 
0530         tp = &ts;
0531     }
0532 
0533     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0534                    "kevent timer: %M, changes: %d", timer, n);
0535 
0536     events = kevent(ngx_kqueue, change_list, n, event_list, (int) nevents, tp);
0537 
0538     err = (events == -1) ? ngx_errno : 0;
0539 
0540     if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
0541         ngx_time_update();
0542     }
0543 
0544     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0545                    "kevent events: %d", events);
0546 
0547     if (err) {
0548         if (err == NGX_EINTR) {
0549 
0550             if (ngx_event_timer_alarm) {
0551                 ngx_event_timer_alarm = 0;
0552                 return NGX_OK;
0553             }
0554 
0555             level = NGX_LOG_INFO;
0556 
0557         } else {
0558             level = NGX_LOG_ALERT;
0559         }
0560 
0561         ngx_log_error(level, cycle->log, err, "kevent() failed");
0562         return NGX_ERROR;
0563     }
0564 
0565     if (events == 0) {
0566         if (timer != NGX_TIMER_INFINITE) {
0567             return NGX_OK;
0568         }
0569 
0570         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0571                       "kevent() returned no events without timeout");
0572         return NGX_ERROR;
0573     }
0574 
0575     for (i = 0; i < events; i++) {
0576 
0577         ngx_kqueue_dump_event(cycle->log, &event_list[i]);
0578 
0579         if (event_list[i].flags & EV_ERROR) {
0580             ngx_log_error(NGX_LOG_ALERT, cycle->log, event_list[i].data,
0581                           "kevent() error on %d filter:%d flags:%04Xd",
0582                           (int) event_list[i].ident, event_list[i].filter,
0583                           event_list[i].flags);
0584             continue;
0585         }
0586 
0587 #if (NGX_HAVE_TIMER_EVENT)
0588 
0589         if (event_list[i].filter == EVFILT_TIMER) {
0590             ngx_time_update();
0591             continue;
0592         }
0593 
0594 #endif
0595 
0596         ev = (ngx_event_t *) event_list[i].udata;
0597 
0598         switch (event_list[i].filter) {
0599 
0600         case EVFILT_READ:
0601         case EVFILT_WRITE:
0602 
0603             instance = (uintptr_t) ev & 1;
0604             ev = (ngx_event_t *) ((uintptr_t) ev & (uintptr_t) ~1);
0605 
0606             if (ev->closed || ev->instance != instance) {
0607 
0608                 /*
0609                  * the stale event from a file descriptor
0610                  * that was just closed in this iteration
0611                  */
0612 
0613                 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
0614                                "kevent: stale event %p", ev);
0615                 continue;
0616             }
0617 
0618             if (ev->log && (ev->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
0619                 ngx_kqueue_dump_event(ev->log, &event_list[i]);
0620             }
0621 
0622             if (ev->oneshot) {
0623                 ev->active = 0;
0624             }
0625 
0626             ev->available = event_list[i].data;
0627 
0628             if (event_list[i].flags & EV_EOF) {
0629                 ev->pending_eof = 1;
0630                 ev->kq_errno = event_list[i].fflags;
0631             }
0632 
0633             ev->ready = 1;
0634 
0635             break;
0636 
0637         case EVFILT_VNODE:
0638             ev->kq_vnode = 1;
0639 
0640             break;
0641 
0642         case EVFILT_AIO:
0643             ev->complete = 1;
0644             ev->ready = 1;
0645 
0646             break;
0647 
0648 #ifdef EVFILT_USER
0649         case EVFILT_USER:
0650             break;
0651 #endif
0652 
0653         default:
0654             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
0655                           "unexpected kevent() filter %d",
0656                           event_list[i].filter);
0657             continue;
0658         }
0659 
0660         if (flags & NGX_POST_EVENTS) {
0661             queue = ev->accept ? &ngx_posted_accept_events
0662                                : &ngx_posted_events;
0663 
0664             ngx_post_event(ev, queue);
0665 
0666             continue;
0667         }
0668 
0669         ev->handler(ev);
0670     }
0671 
0672     return NGX_OK;
0673 }
0674 
0675 
0676 static ngx_inline void
0677 ngx_kqueue_dump_event(ngx_log_t *log, struct kevent *kev)
0678 {
0679     if (kev->ident > 0x8000000 && kev->ident != (unsigned) -1) {
0680         ngx_log_debug6(NGX_LOG_DEBUG_EVENT, log, 0,
0681                        "kevent: %p: ft:%d fl:%04Xd ff:%08Xd d:%d ud:%p",
0682                        (void *) kev->ident, kev->filter,
0683                        kev->flags, kev->fflags,
0684                        (int) kev->data, kev->udata);
0685 
0686     } else {
0687         ngx_log_debug6(NGX_LOG_DEBUG_EVENT, log, 0,
0688                        "kevent: %d: ft:%d fl:%04Xd ff:%08Xd d:%d ud:%p",
0689                        (int) kev->ident, kev->filter,
0690                        kev->flags, kev->fflags,
0691                        (int) kev->data, kev->udata);
0692     }
0693 }
0694 
0695 
0696 static void *
0697 ngx_kqueue_create_conf(ngx_cycle_t *cycle)
0698 {
0699     ngx_kqueue_conf_t  *kcf;
0700 
0701     kcf = ngx_palloc(cycle->pool, sizeof(ngx_kqueue_conf_t));
0702     if (kcf == NULL) {
0703         return NULL;
0704     }
0705 
0706     kcf->changes = NGX_CONF_UNSET;
0707     kcf->events = NGX_CONF_UNSET;
0708 
0709     return kcf;
0710 }
0711 
0712 
0713 static char *
0714 ngx_kqueue_init_conf(ngx_cycle_t *cycle, void *conf)
0715 {
0716     ngx_kqueue_conf_t *kcf = conf;
0717 
0718     ngx_conf_init_uint_value(kcf->changes, 512);
0719     ngx_conf_init_uint_value(kcf->events, 512);
0720 
0721     return NGX_CONF_OK;
0722 }