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