Annotation of embedaddon/nginx/src/event/modules/ngx_kqueue_module.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (C) Igor Sysoev
4: * Copyright (C) Nginx, Inc.
5: */
6:
7:
8: #include <ngx_config.h>
9: #include <ngx_core.h>
10: #include <ngx_event.h>
11:
12:
13: typedef struct {
14: ngx_uint_t changes;
15: ngx_uint_t events;
16: } ngx_kqueue_conf_t;
17:
18:
19: static ngx_int_t ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer);
20: static void ngx_kqueue_done(ngx_cycle_t *cycle);
21: static ngx_int_t ngx_kqueue_add_event(ngx_event_t *ev, ngx_int_t event,
22: ngx_uint_t flags);
23: static ngx_int_t ngx_kqueue_del_event(ngx_event_t *ev, ngx_int_t event,
24: ngx_uint_t flags);
25: static ngx_int_t ngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter,
26: ngx_uint_t flags);
27: static ngx_int_t ngx_kqueue_process_changes(ngx_cycle_t *cycle, ngx_uint_t try);
28: static ngx_int_t ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
29: ngx_uint_t flags);
30: static ngx_inline void ngx_kqueue_dump_event(ngx_log_t *log,
31: struct kevent *kev);
32:
33: static void *ngx_kqueue_create_conf(ngx_cycle_t *cycle);
34: static char *ngx_kqueue_init_conf(ngx_cycle_t *cycle, void *conf);
35:
36:
37: int ngx_kqueue = -1;
38:
39: /*
40: * The "change_list" should be declared as ngx_thread_volatile.
41: * However, the use of the change_list is localized in kqueue functions and
42: * is protected by the mutex so even the "icc -ipo" should not build the code
43: * with the race condition. Thus we avoid the declaration to make a more
44: * readable code.
45: */
46:
47: static struct kevent *change_list, *change_list0, *change_list1;
48: static struct kevent *event_list;
49: static ngx_uint_t max_changes, nchanges, nevents;
50:
51: #if (NGX_THREADS)
52: static ngx_mutex_t *list_mutex;
53: static ngx_mutex_t *kevent_mutex;
54: #endif
55:
56:
57:
58: static ngx_str_t kqueue_name = ngx_string("kqueue");
59:
60: static ngx_command_t ngx_kqueue_commands[] = {
61:
62: { ngx_string("kqueue_changes"),
63: NGX_EVENT_CONF|NGX_CONF_TAKE1,
64: ngx_conf_set_num_slot,
65: 0,
66: offsetof(ngx_kqueue_conf_t, changes),
67: NULL },
68:
69: { ngx_string("kqueue_events"),
70: NGX_EVENT_CONF|NGX_CONF_TAKE1,
71: ngx_conf_set_num_slot,
72: 0,
73: offsetof(ngx_kqueue_conf_t, events),
74: NULL },
75:
76: ngx_null_command
77: };
78:
79:
80: ngx_event_module_t ngx_kqueue_module_ctx = {
81: &kqueue_name,
82: ngx_kqueue_create_conf, /* create configuration */
83: ngx_kqueue_init_conf, /* init configuration */
84:
85: {
86: ngx_kqueue_add_event, /* add an event */
87: ngx_kqueue_del_event, /* delete an event */
88: ngx_kqueue_add_event, /* enable an event */
89: ngx_kqueue_del_event, /* disable an event */
90: NULL, /* add an connection */
91: NULL, /* delete an connection */
92: ngx_kqueue_process_changes, /* process the changes */
93: ngx_kqueue_process_events, /* process the events */
94: ngx_kqueue_init, /* init the events */
95: ngx_kqueue_done /* done the events */
96: }
97:
98: };
99:
100: ngx_module_t ngx_kqueue_module = {
101: NGX_MODULE_V1,
102: &ngx_kqueue_module_ctx, /* module context */
103: ngx_kqueue_commands, /* module directives */
104: NGX_EVENT_MODULE, /* module type */
105: NULL, /* init master */
106: NULL, /* init module */
107: NULL, /* init process */
108: NULL, /* init thread */
109: NULL, /* exit thread */
110: NULL, /* exit process */
111: NULL, /* exit master */
112: NGX_MODULE_V1_PADDING
113: };
114:
115:
116: static ngx_int_t
117: ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer)
118: {
119: ngx_kqueue_conf_t *kcf;
120: struct timespec ts;
121: #if (NGX_HAVE_TIMER_EVENT)
122: struct kevent kev;
123: #endif
124:
125: kcf = ngx_event_get_conf(cycle->conf_ctx, ngx_kqueue_module);
126:
127: if (ngx_kqueue == -1) {
128: ngx_kqueue = kqueue();
129:
130: if (ngx_kqueue == -1) {
131: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
132: "kqueue() failed");
133: return NGX_ERROR;
134: }
135:
136: #if (NGX_THREADS)
137:
138: list_mutex = ngx_mutex_init(cycle->log, 0);
139: if (list_mutex == NULL) {
140: return NGX_ERROR;
141: }
142:
143: kevent_mutex = ngx_mutex_init(cycle->log, 0);
144: if (kevent_mutex == NULL) {
145: return NGX_ERROR;
146: }
147:
148: #endif
149: }
150:
151: if (max_changes < kcf->changes) {
152: if (nchanges) {
153: ts.tv_sec = 0;
154: ts.tv_nsec = 0;
155:
156: if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)
157: == -1)
158: {
159: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
160: "kevent() failed");
161: return NGX_ERROR;
162: }
163: nchanges = 0;
164: }
165:
166: if (change_list0) {
167: ngx_free(change_list0);
168: }
169:
170: change_list0 = ngx_alloc(kcf->changes * sizeof(struct kevent),
171: cycle->log);
172: if (change_list0 == NULL) {
173: return NGX_ERROR;
174: }
175:
176: if (change_list1) {
177: ngx_free(change_list1);
178: }
179:
180: change_list1 = ngx_alloc(kcf->changes * sizeof(struct kevent),
181: cycle->log);
182: if (change_list1 == NULL) {
183: return NGX_ERROR;
184: }
185:
186: change_list = change_list0;
187: }
188:
189: max_changes = kcf->changes;
190:
191: if (nevents < kcf->events) {
192: if (event_list) {
193: ngx_free(event_list);
194: }
195:
196: event_list = ngx_alloc(kcf->events * sizeof(struct kevent), cycle->log);
197: if (event_list == NULL) {
198: return NGX_ERROR;
199: }
200: }
201:
202: ngx_event_flags = NGX_USE_ONESHOT_EVENT
203: |NGX_USE_KQUEUE_EVENT
204: |NGX_USE_VNODE_EVENT;
205:
206: #if (NGX_HAVE_TIMER_EVENT)
207:
208: if (timer) {
209: kev.ident = 0;
210: kev.filter = EVFILT_TIMER;
211: kev.flags = EV_ADD|EV_ENABLE;
212: kev.fflags = 0;
213: kev.data = timer;
214: kev.udata = 0;
215:
216: ts.tv_sec = 0;
217: ts.tv_nsec = 0;
218:
219: if (kevent(ngx_kqueue, &kev, 1, NULL, 0, &ts) == -1) {
220: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
221: "kevent(EVFILT_TIMER) failed");
222: return NGX_ERROR;
223: }
224:
225: ngx_event_flags |= NGX_USE_TIMER_EVENT;
226: }
227:
228: #endif
229:
230: #if (NGX_HAVE_CLEAR_EVENT)
231: ngx_event_flags |= NGX_USE_CLEAR_EVENT;
232: #else
233: ngx_event_flags |= NGX_USE_LEVEL_EVENT;
234: #endif
235:
236: #if (NGX_HAVE_LOWAT_EVENT)
237: ngx_event_flags |= NGX_USE_LOWAT_EVENT;
238: #endif
239:
240: nevents = kcf->events;
241:
242: ngx_io = ngx_os_io;
243:
244: ngx_event_actions = ngx_kqueue_module_ctx.actions;
245:
246: return NGX_OK;
247: }
248:
249:
250: static void
251: ngx_kqueue_done(ngx_cycle_t *cycle)
252: {
253: if (close(ngx_kqueue) == -1) {
254: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
255: "kqueue close() failed");
256: }
257:
258: ngx_kqueue = -1;
259:
260: #if (NGX_THREADS)
261: ngx_mutex_destroy(kevent_mutex);
262: ngx_mutex_destroy(list_mutex);
263: #endif
264:
265: ngx_free(change_list1);
266: ngx_free(change_list0);
267: ngx_free(event_list);
268:
269: change_list1 = NULL;
270: change_list0 = NULL;
271: change_list = NULL;
272: event_list = NULL;
273: max_changes = 0;
274: nchanges = 0;
275: nevents = 0;
276: }
277:
278:
279: static ngx_int_t
280: ngx_kqueue_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
281: {
282: ngx_int_t rc;
283: #if 0
284: ngx_event_t *e;
285: ngx_connection_t *c;
286: #endif
287:
288: ev->active = 1;
289: ev->disabled = 0;
290: ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1 : 0;
291:
292: ngx_mutex_lock(list_mutex);
293:
294: #if 0
295:
296: if (ev->index < nchanges
297: && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1)
298: == (uintptr_t) ev)
299: {
300: if (change_list[ev->index].flags == EV_DISABLE) {
301:
302: /*
303: * if the EV_DISABLE is still not passed to a kernel
304: * we will not pass it
305: */
306:
307: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
308: "kevent activated: %d: ft:%i",
309: ngx_event_ident(ev->data), event);
310:
311: if (ev->index < --nchanges) {
312: e = (ngx_event_t *)
313: ((uintptr_t) change_list[nchanges].udata & (uintptr_t) ~1);
314: change_list[ev->index] = change_list[nchanges];
315: e->index = ev->index;
316: }
317:
318: ngx_mutex_unlock(list_mutex);
319:
320: return NGX_OK;
321: }
322:
323: c = ev->data;
324:
325: ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
326: "previous event on #%d were not passed in kernel", c->fd);
327:
328: ngx_mutex_unlock(list_mutex);
329:
330: return NGX_ERROR;
331: }
332:
333: #endif
334:
335: rc = ngx_kqueue_set_event(ev, event, EV_ADD|EV_ENABLE|flags);
336:
337: ngx_mutex_unlock(list_mutex);
338:
339: return rc;
340: }
341:
342:
343: static ngx_int_t
344: ngx_kqueue_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
345: {
346: ngx_int_t rc;
347: ngx_event_t *e;
348:
349: ev->active = 0;
350: ev->disabled = 0;
351:
352: ngx_mutex_lock(list_mutex);
353:
354: if (ev->index < nchanges
355: && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1)
356: == (uintptr_t) ev)
357: {
358: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
359: "kevent deleted: %d: ft:%i",
360: ngx_event_ident(ev->data), event);
361:
362: /* if the event is still not passed to a kernel we will not pass it */
363:
364: nchanges--;
365:
366: if (ev->index < nchanges) {
367: e = (ngx_event_t *)
368: ((uintptr_t) change_list[nchanges].udata & (uintptr_t) ~1);
369: change_list[ev->index] = change_list[nchanges];
370: e->index = ev->index;
371: }
372:
373: ngx_mutex_unlock(list_mutex);
374:
375: return NGX_OK;
376: }
377:
378: /*
379: * when the file descriptor is closed the kqueue automatically deletes
380: * its filters so we do not need to delete explicitly the event
381: * before the closing the file descriptor.
382: */
383:
384: if (flags & NGX_CLOSE_EVENT) {
385: ngx_mutex_unlock(list_mutex);
386: return NGX_OK;
387: }
388:
389: if (flags & NGX_DISABLE_EVENT) {
390: ev->disabled = 1;
391:
392: } else {
393: flags |= EV_DELETE;
394: }
395:
396: rc = ngx_kqueue_set_event(ev, event, flags);
397:
398: ngx_mutex_unlock(list_mutex);
399:
400: return rc;
401: }
402:
403:
404: static ngx_int_t
405: ngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter, ngx_uint_t flags)
406: {
407: struct kevent *kev;
408: struct timespec ts;
409: ngx_connection_t *c;
410:
411: c = ev->data;
412:
413: ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
414: "kevent set event: %d: ft:%i fl:%04Xi",
415: c->fd, filter, flags);
416:
417: if (nchanges >= max_changes) {
418: ngx_log_error(NGX_LOG_WARN, ev->log, 0,
419: "kqueue change list is filled up");
420:
421: ts.tv_sec = 0;
422: ts.tv_nsec = 0;
423:
424: if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)
425: == -1)
426: {
427: ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent() failed");
428: return NGX_ERROR;
429: }
430:
431: nchanges = 0;
432: }
433:
434: kev = &change_list[nchanges];
435:
436: kev->ident = c->fd;
437: kev->filter = (short) filter;
438: kev->flags = (u_short) flags;
439: kev->udata = NGX_KQUEUE_UDATA_T ((uintptr_t) ev | ev->instance);
440:
441: if (filter == EVFILT_VNODE) {
442: kev->fflags = NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND
443: |NOTE_ATTRIB|NOTE_RENAME
444: #if (__FreeBSD__ == 4 && __FreeBSD_version >= 430000) \
445: || __FreeBSD_version >= 500018
446: |NOTE_REVOKE
447: #endif
448: ;
449: kev->data = 0;
450:
451: } else {
452: #if (NGX_HAVE_LOWAT_EVENT)
453: if (flags & NGX_LOWAT_EVENT) {
454: kev->fflags = NOTE_LOWAT;
455: kev->data = ev->available;
456:
457: } else {
458: kev->fflags = 0;
459: kev->data = 0;
460: }
461: #else
462: kev->fflags = 0;
463: kev->data = 0;
464: #endif
465: }
466:
467: ev->index = nchanges;
468: nchanges++;
469:
470: if (flags & NGX_FLUSH_EVENT) {
471: ts.tv_sec = 0;
472: ts.tv_nsec = 0;
473:
474: ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "kevent flush");
475:
476: if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)
477: == -1)
478: {
479: ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent() failed");
480: return NGX_ERROR;
481: }
482:
483: nchanges = 0;
484: }
485:
486: return NGX_OK;
487: }
488:
489:
490: static ngx_int_t
491: ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
492: ngx_uint_t flags)
493: {
494: int events, n;
495: ngx_int_t i, instance;
496: ngx_uint_t level;
497: ngx_err_t err;
498: ngx_event_t *ev, **queue;
499: struct timespec ts, *tp;
500:
501: if (ngx_threaded) {
502: if (ngx_kqueue_process_changes(cycle, 0) == NGX_ERROR) {
503: return NGX_ERROR;
504: }
505:
506: n = 0;
507:
508: } else {
509: n = (int) nchanges;
510: nchanges = 0;
511: }
512:
513: if (timer == NGX_TIMER_INFINITE) {
514: tp = NULL;
515:
516: } else {
517:
518: ts.tv_sec = timer / 1000;
519: ts.tv_nsec = (timer % 1000) * 1000000;
520:
521: /*
522: * 64-bit Darwin kernel has the bug: kernel level ts.tv_nsec is
523: * the int32_t while user level ts.tv_nsec is the long (64-bit),
524: * so on the big endian PowerPC all nanoseconds are lost.
525: */
526:
527: #if (NGX_DARWIN_KEVENT_BUG)
528: ts.tv_nsec <<= 32;
529: #endif
530:
531: tp = &ts;
532: }
533:
534: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
535: "kevent timer: %M, changes: %d", timer, n);
536:
537: events = kevent(ngx_kqueue, change_list, n, event_list, (int) nevents, tp);
538:
539: err = (events == -1) ? ngx_errno : 0;
540:
541: if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
542: ngx_time_update();
543: }
544:
545: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
546: "kevent events: %d", events);
547:
548: if (err) {
549: if (err == NGX_EINTR) {
550:
551: if (ngx_event_timer_alarm) {
552: ngx_event_timer_alarm = 0;
553: return NGX_OK;
554: }
555:
556: level = NGX_LOG_INFO;
557:
558: } else {
559: level = NGX_LOG_ALERT;
560: }
561:
562: ngx_log_error(level, cycle->log, err, "kevent() failed");
563: return NGX_ERROR;
564: }
565:
566: if (events == 0) {
567: if (timer != NGX_TIMER_INFINITE) {
568: return NGX_OK;
569: }
570:
571: ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
572: "kevent() returned no events without timeout");
573: return NGX_ERROR;
574: }
575:
576: ngx_mutex_lock(ngx_posted_events_mutex);
577:
578: for (i = 0; i < events; i++) {
579:
580: ngx_kqueue_dump_event(cycle->log, &event_list[i]);
581:
582: if (event_list[i].flags & EV_ERROR) {
583: ngx_log_error(NGX_LOG_ALERT, cycle->log, event_list[i].data,
584: "kevent() error on %d filter:%d flags:%04Xd",
585: event_list[i].ident, event_list[i].filter,
586: event_list[i].flags);
587: continue;
588: }
589:
590: #if (NGX_HAVE_TIMER_EVENT)
591:
592: if (event_list[i].filter == EVFILT_TIMER) {
593: ngx_time_update();
594: continue;
595: }
596:
597: #endif
598:
599: ev = (ngx_event_t *) event_list[i].udata;
600:
601: switch (event_list[i].filter) {
602:
603: case EVFILT_READ:
604: case EVFILT_WRITE:
605:
606: instance = (uintptr_t) ev & 1;
607: ev = (ngx_event_t *) ((uintptr_t) ev & (uintptr_t) ~1);
608:
609: if (ev->closed || ev->instance != instance) {
610:
611: /*
612: * the stale event from a file descriptor
613: * that was just closed in this iteration
614: */
615:
616: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
617: "kevent: stale event %p", ev);
618: continue;
619: }
620:
621: if (ev->log && (ev->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
622: ngx_kqueue_dump_event(ev->log, &event_list[i]);
623: }
624:
625: if (ev->oneshot) {
626: ev->active = 0;
627: }
628:
629: #if (NGX_THREADS)
630:
631: if ((flags & NGX_POST_THREAD_EVENTS) && !ev->accept) {
632: ev->posted_ready = 1;
633: ev->posted_available = event_list[i].data;
634:
635: if (event_list[i].flags & EV_EOF) {
636: ev->posted_eof = 1;
637: ev->posted_errno = event_list[i].fflags;
638: }
639:
640: ngx_locked_post_event(ev, &ngx_posted_events);
641:
642: continue;
643: }
644:
645: #endif
646:
647: ev->available = event_list[i].data;
648:
649: if (event_list[i].flags & EV_EOF) {
650: ev->pending_eof = 1;
651: ev->kq_errno = event_list[i].fflags;
652: }
653:
654: ev->ready = 1;
655:
656: break;
657:
658: case EVFILT_VNODE:
659: ev->kq_vnode = 1;
660:
661: break;
662:
663: case EVFILT_AIO:
664: ev->complete = 1;
665: ev->ready = 1;
666:
667: break;
668:
669: default:
670: ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
671: "unexpected kevent() filter %d",
672: event_list[i].filter);
673: continue;
674: }
675:
676: if (flags & NGX_POST_EVENTS) {
677: queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events:
678: &ngx_posted_events);
679: ngx_locked_post_event(ev, queue);
680:
681: continue;
682: }
683:
684: ev->handler(ev);
685: }
686:
687: ngx_mutex_unlock(ngx_posted_events_mutex);
688:
689: return NGX_OK;
690: }
691:
692:
693: static ngx_int_t
694: ngx_kqueue_process_changes(ngx_cycle_t *cycle, ngx_uint_t try)
695: {
696: int n;
697: ngx_int_t rc;
698: ngx_err_t err;
699: struct timespec ts;
700: struct kevent *changes;
701:
702: ngx_mutex_lock(kevent_mutex);
703:
704: ngx_mutex_lock(list_mutex);
705:
706: if (nchanges == 0) {
707: ngx_mutex_unlock(list_mutex);
708: ngx_mutex_unlock(kevent_mutex);
709: return NGX_OK;
710: }
711:
712: changes = change_list;
713: if (change_list == change_list0) {
714: change_list = change_list1;
715: } else {
716: change_list = change_list0;
717: }
718:
719: n = (int) nchanges;
720: nchanges = 0;
721:
722: ngx_mutex_unlock(list_mutex);
723:
724: ts.tv_sec = 0;
725: ts.tv_nsec = 0;
726:
727: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
728: "kevent changes: %d", n);
729:
730: if (kevent(ngx_kqueue, changes, n, NULL, 0, &ts) == -1) {
731: err = ngx_errno;
732: ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
733: cycle->log, err, "kevent() failed");
734: rc = NGX_ERROR;
735:
736: } else {
737: rc = NGX_OK;
738: }
739:
740: ngx_mutex_unlock(kevent_mutex);
741:
742: return rc;
743: }
744:
745:
746: static ngx_inline void
747: ngx_kqueue_dump_event(ngx_log_t *log, struct kevent *kev)
748: {
749: ngx_log_debug6(NGX_LOG_DEBUG_EVENT, log, 0,
750: (kev->ident > 0x8000000 && kev->ident != (unsigned) -1) ?
751: "kevent: %p: ft:%d fl:%04Xd ff:%08Xd d:%d ud:%p":
752: "kevent: %d: ft:%d fl:%04Xd ff:%08Xd d:%d ud:%p",
753: kev->ident, kev->filter,
754: kev->flags, kev->fflags,
755: kev->data, kev->udata);
756: }
757:
758:
759: static void *
760: ngx_kqueue_create_conf(ngx_cycle_t *cycle)
761: {
762: ngx_kqueue_conf_t *kcf;
763:
764: kcf = ngx_palloc(cycle->pool, sizeof(ngx_kqueue_conf_t));
765: if (kcf == NULL) {
766: return NULL;
767: }
768:
769: kcf->changes = NGX_CONF_UNSET;
770: kcf->events = NGX_CONF_UNSET;
771:
772: return kcf;
773: }
774:
775:
776: static char *
777: ngx_kqueue_init_conf(ngx_cycle_t *cycle, void *conf)
778: {
779: ngx_kqueue_conf_t *kcf = conf;
780:
781: ngx_conf_init_uint_value(kcf->changes, 512);
782: ngx_conf_init_uint_value(kcf->events, 512);
783:
784: return NGX_CONF_OK;
785: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>