comparison src/event/modules/ngx_kqueue_module.c @ 380:5ce6561246a5

nginx-0.0.7-2004-07-07-10:15:04 import
author Igor Sysoev <igor@sysoev.ru>
date Wed, 07 Jul 2004 06:15:04 +0000
parents 73688d5d7fc3
children 02a511569afb
comparison
equal deleted inserted replaced
379:73688d5d7fc3 380:5ce6561246a5
19 static ngx_int_t ngx_kqueue_init(ngx_cycle_t *cycle); 19 static ngx_int_t ngx_kqueue_init(ngx_cycle_t *cycle);
20 static void ngx_kqueue_done(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); 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); 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); 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);
24 static ngx_int_t ngx_kqueue_process_events(ngx_cycle_t *cycle); 25 static ngx_int_t ngx_kqueue_process_events(ngx_cycle_t *cycle);
25 static ngx_inline void ngx_kqueue_dump_event(ngx_log_t *log, 26 static ngx_inline void ngx_kqueue_dump_event(ngx_log_t *log,
26 struct kevent *kev); 27 struct kevent *kev);
27 28
28 static void *ngx_kqueue_create_conf(ngx_cycle_t *cycle); 29 static void *ngx_kqueue_create_conf(ngx_cycle_t *cycle);
29 static char *ngx_kqueue_init_conf(ngx_cycle_t *cycle, void *conf); 30 static char *ngx_kqueue_init_conf(ngx_cycle_t *cycle, void *conf);
30 31
31 32
32 int ngx_kqueue = -1; 33 int ngx_kqueue = -1;
33 34
34 static struct kevent *change_list, *event_list; 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;
35 static int max_changes, nchanges, nevents; 45 static int max_changes, nchanges, nevents;
46
47 #if (NGX_THREADS)
48 static ngx_mutex_t *ngx_kqueue_mutex;
49 #endif
50
36 51
37 52
38 static ngx_str_t kqueue_name = ngx_string("kqueue"); 53 static ngx_str_t kqueue_name = ngx_string("kqueue");
39 54
40 static ngx_command_t ngx_kqueue_commands[] = { 55 static ngx_command_t ngx_kqueue_commands[] = {
67 ngx_kqueue_del_event, /* delete an event */ 82 ngx_kqueue_del_event, /* delete an event */
68 ngx_kqueue_add_event, /* enable an event */ 83 ngx_kqueue_add_event, /* enable an event */
69 ngx_kqueue_del_event, /* disable an event */ 84 ngx_kqueue_del_event, /* disable an event */
70 NULL, /* add an connection */ 85 NULL, /* add an connection */
71 NULL, /* delete an connection */ 86 NULL, /* delete an connection */
87 ngx_kqueue_process_changes, /* process the changes */
72 ngx_kqueue_process_events, /* process the events */ 88 ngx_kqueue_process_events, /* process the events */
73 ngx_kqueue_init, /* init the events */ 89 ngx_kqueue_init, /* init the events */
74 ngx_kqueue_done /* done the events */ 90 ngx_kqueue_done /* done the events */
75 } 91 }
76 92
80 NGX_MODULE, 96 NGX_MODULE,
81 &ngx_kqueue_module_ctx, /* module context */ 97 &ngx_kqueue_module_ctx, /* module context */
82 ngx_kqueue_commands, /* module directives */ 98 ngx_kqueue_commands, /* module directives */
83 NGX_EVENT_MODULE, /* module type */ 99 NGX_EVENT_MODULE, /* module type */
84 NULL, /* init module */ 100 NULL, /* init module */
85 NULL /* init child */ 101 NULL /* init process */
86 }; 102 };
87 103
88 104
89 105
90 static ngx_int_t ngx_kqueue_init(ngx_cycle_t *cycle) 106 static ngx_int_t ngx_kqueue_init(ngx_cycle_t *cycle)
100 if (ngx_kqueue == -1) { 116 if (ngx_kqueue == -1) {
101 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, 117 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
102 "kqueue() failed"); 118 "kqueue() failed");
103 return NGX_ERROR; 119 return NGX_ERROR;
104 } 120 }
121
122 #if (NGX_THREADS)
123 if (!(ngx_kqueue_mutex = ngx_mutex_init(cycle->log, 0))) {
124 return NGX_ERROR;
125 }
126 #endif
105 } 127 }
106 128
107 if (max_changes < kcf->changes) { 129 if (max_changes < kcf->changes) {
108 if (nchanges) { 130 if (nchanges) {
109 ts.tv_sec = 0; 131 ts.tv_sec = 0;
115 return NGX_ERROR; 137 return NGX_ERROR;
116 } 138 }
117 nchanges = 0; 139 nchanges = 0;
118 } 140 }
119 141
120 if (change_list) { 142 if (change_list0) {
121 ngx_free(change_list); 143 ngx_free(change_list0);
122 } 144 }
123 145
124 change_list = ngx_alloc(kcf->changes * sizeof(struct kevent), 146 change_list0 = ngx_alloc(kcf->changes * sizeof(struct kevent),
125 cycle->log); 147 cycle->log);
126 if (change_list == NULL) { 148 if (change_list0 == NULL) {
127 return NGX_ERROR; 149 return NGX_ERROR;
128 } 150 }
151
152 if (change_list1) {
153 ngx_free(change_list1);
154 }
155
156 change_list1 = ngx_alloc(kcf->changes * sizeof(struct kevent),
157 cycle->log);
158 if (change_list1 == NULL) {
159 return NGX_ERROR;
160 }
161
162 change_list = change_list0;
129 } 163 }
130 164
131 max_changes = kcf->changes; 165 max_changes = kcf->changes;
132 166
133 if (nevents < kcf->events) { 167 if (nevents < kcf->events) {
134 if (event_list) { 168 if (event_list) {
135 ngx_free(event_list); 169 ngx_free(event_list);
136 } 170 }
137 171
138 event_list = ngx_alloc(kcf->events * sizeof(struct kevent), 172 event_list = ngx_alloc(kcf->events * sizeof(struct kevent), cycle->log);
139 cycle->log);
140 if (event_list == NULL) { 173 if (event_list == NULL) {
141 return NGX_ERROR; 174 return NGX_ERROR;
142 } 175 }
143 } 176 }
144 177
170 "kqueue close() failed"); 203 "kqueue close() failed");
171 } 204 }
172 205
173 ngx_kqueue = -1; 206 ngx_kqueue = -1;
174 207
175 ngx_free(change_list); 208 ngx_mutex_destroy(ngx_kqueue_mutex);
209
210 ngx_free(change_list1);
211 ngx_free(change_list0);
176 ngx_free(event_list); 212 ngx_free(event_list);
177 213
214 change_list1 = NULL;
215 change_list0 = NULL;
178 change_list = NULL; 216 change_list = NULL;
179 event_list = NULL; 217 event_list = NULL;
180 max_changes = 0; 218 max_changes = 0;
181 nchanges = 0; 219 nchanges = 0;
182 nevents = 0; 220 nevents = 0;
183 } 221 }
184 222
185 223
186 static ngx_int_t ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags) 224 static ngx_int_t ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags)
187 { 225 {
226 ngx_int_t rc;
188 ngx_event_t *e; 227 ngx_event_t *e;
189 ngx_connection_t *c; 228 ngx_connection_t *c;
190 229
191 ev->active = 1; 230 ev->active = 1;
192 ev->disabled = 0; 231 ev->disabled = 0;
193 ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1 : 0; 232 ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1 : 0;
194 233
195 if (ngx_thread_main() 234 if (ngx_mutex_lock(ngx_kqueue_mutex) == NGX_ERROR) {
196 && nchanges > 0 235 return NGX_ERROR;
236 }
237
238 if (nchanges > 0
197 && ev->index < (u_int) nchanges 239 && ev->index < (u_int) nchanges
198 && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1) 240 && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1)
199 == (uintptr_t) ev) 241 == (uintptr_t) ev)
200 { 242 {
201 if (change_list[ev->index].flags == EV_DISABLE) { 243 if (change_list[ev->index].flags == EV_DISABLE) {
213 e = (ngx_event_t *) change_list[nchanges].udata; 255 e = (ngx_event_t *) change_list[nchanges].udata;
214 change_list[ev->index] = change_list[nchanges]; 256 change_list[ev->index] = change_list[nchanges];
215 e->index = ev->index; 257 e->index = ev->index;
216 } 258 }
217 259
260 ngx_mutex_unlock(ngx_kqueue_mutex);
261
218 return NGX_OK; 262 return NGX_OK;
219 } 263 }
220 264
221 c = ev->data; 265 c = ev->data;
266
222 ngx_log_error(NGX_LOG_ALERT, ev->log, 0, 267 ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
223 "previous event on #%d were not passed in kernel", c->fd); 268 "previous event on #%d were not passed in kernel", c->fd);
224 269
270 ngx_mutex_unlock(ngx_kqueue_mutex);
271
225 return NGX_ERROR; 272 return NGX_ERROR;
226 } 273 }
227 274
228 return ngx_kqueue_set_event(ev, event, EV_ADD|EV_ENABLE|flags); 275 rc = ngx_kqueue_set_event(ev, event, EV_ADD|EV_ENABLE|flags);
276
277 ngx_mutex_unlock(ngx_kqueue_mutex);
278
279 return rc;
229 } 280 }
230 281
231 282
232 static ngx_int_t ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags) 283 static ngx_int_t ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags)
233 { 284 {
285 ngx_int_t rc;
234 ngx_event_t *e; 286 ngx_event_t *e;
235 287
236 ev->active = 0; 288 ev->active = 0;
237 ev->disabled = 0; 289 ev->disabled = 0;
238 290
239 if (ngx_thread_main() 291 if (ngx_mutex_lock(ngx_kqueue_mutex) == NGX_ERROR) {
240 && nchanges > 0 292 return NGX_ERROR;
293 }
294
295 if (nchanges > 0
241 && ev->index < (u_int) nchanges 296 && ev->index < (u_int) nchanges
242 && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1) 297 && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1)
243 == (uintptr_t) ev) 298 == (uintptr_t) ev)
244 { 299 {
245 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, 300 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
252 e = (ngx_event_t *) change_list[nchanges].udata; 307 e = (ngx_event_t *) change_list[nchanges].udata;
253 change_list[ev->index] = change_list[nchanges]; 308 change_list[ev->index] = change_list[nchanges];
254 e->index = ev->index; 309 e->index = ev->index;
255 } 310 }
256 311
312 ngx_mutex_unlock(ngx_kqueue_mutex);
313
257 return NGX_OK; 314 return NGX_OK;
258 } 315 }
259 316
260 /* 317 /*
261 * when the file descriptor is closed the kqueue automatically deletes 318 * when the file descriptor is closed the kqueue automatically deletes
262 * its filters so we do not need to delete explicity the event 319 * its filters so we do not need to delete explicity the event
263 * before the closing the file descriptor. 320 * before the closing the file descriptor.
264 */ 321 */
265 322
266 if (flags & NGX_CLOSE_EVENT) { 323 if (flags & NGX_CLOSE_EVENT) {
324 ngx_mutex_unlock(ngx_kqueue_mutex);
267 return NGX_OK; 325 return NGX_OK;
268 } 326 }
269 327
270 if (flags & NGX_DISABLE_EVENT) { 328 if (flags & NGX_DISABLE_EVENT) {
271 ev->disabled = 1; 329 ev->disabled = 1;
272 } 330 }
273 331
274 return ngx_kqueue_set_event(ev, event, 332 rc = ngx_kqueue_set_event(ev, event,
275 flags & NGX_DISABLE_EVENT ? EV_DISABLE : EV_DELETE); 333 flags & NGX_DISABLE_EVENT ? EV_DISABLE : EV_DELETE);
334
335 ngx_mutex_unlock(ngx_kqueue_mutex);
336
337 return rc;
276 } 338 }
277 339
278 340
279 static ngx_int_t ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags) 341 static ngx_int_t ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags)
280 { 342 {
281 struct kevent *kev, kv; 343 struct kevent *kev;
282 struct timespec ts; 344 struct timespec ts;
283 ngx_connection_t *c; 345 ngx_connection_t *c;
284 346
285 c = ev->data; 347 c = ev->data;
286 348
287 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0, 349 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
288 "kevent set event: %d: ft:%d fl:%04X", 350 "kevent set event: %d: ft:%d fl:%04X",
289 c->fd, filter, flags); 351 c->fd, filter, flags);
290 352
291 if (ngx_thread_main() && nchanges >= max_changes) { 353 if (nchanges >= max_changes) {
292 ngx_log_error(NGX_LOG_WARN, ev->log, 0, 354 ngx_log_error(NGX_LOG_WARN, ev->log, 0,
293 "kqueue change list is filled up"); 355 "kqueue change list is filled up");
294 356
295 ts.tv_sec = 0; 357 ts.tv_sec = 0;
296 ts.tv_nsec = 0; 358 ts.tv_nsec = 0;
301 } 363 }
302 364
303 nchanges = 0; 365 nchanges = 0;
304 } 366 }
305 367
306 kev = ngx_thread_main() ? &change_list[nchanges] : &kv; 368 kev = &change_list[nchanges];
307 369
308 kev->ident = c->fd; 370 kev->ident = c->fd;
309 kev->filter = filter; 371 kev->filter = filter;
310 kev->flags = flags; 372 kev->flags = flags;
311 kev->udata = (void *) ((uintptr_t) ev | ev->instance); 373 kev->udata = (void *) ((uintptr_t) ev | ev->instance);
334 kev->fflags = 0; 396 kev->fflags = 0;
335 kev->data = 0; 397 kev->data = 0;
336 #endif 398 #endif
337 } 399 }
338 400
339 if (ngx_thread_main()) { 401 ev->index = nchanges;
340 ev->index = nchanges; 402 nchanges++;
341 nchanges++;
342
343 } else {
344 ts.tv_sec = 0;
345 ts.tv_nsec = 0;
346
347 if (kevent(ngx_kqueue, &kv, 1, NULL, 0, &ts) == -1) {
348 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent() failed");
349 return NGX_ERROR;
350 }
351 }
352 403
353 return NGX_OK; 404 return NGX_OK;
354 } 405 }
355 406
356 407
357 static ngx_int_t ngx_kqueue_process_events(ngx_cycle_t *cycle) 408 static ngx_int_t ngx_kqueue_process_events(ngx_cycle_t *cycle)
358 { 409 {
359 int events; 410 int events, n;
360 ngx_int_t i, instance; 411 ngx_int_t i, instance;
361 ngx_uint_t lock, accept_lock, expire; 412 ngx_uint_t lock, accept_lock, expire;
362 ngx_err_t err; 413 ngx_err_t err;
363 ngx_msec_t timer; 414 ngx_msec_t timer;
364 ngx_event_t *ev; 415 ngx_event_t *ev;
417 expire = 0; 468 expire = 0;
418 } 469 }
419 } 470 }
420 } 471 }
421 472
473 if (ngx_threaded) {
474 if (ngx_kqueue_process_changes(cycle, 0) == NGX_ERROR) {
475 ngx_accept_mutex_unlock();
476 return NGX_ERROR;
477 }
478
479 n = 0;
480
481 } else {
482 n = nchanges;
483 nchanges = 0;
484 }
485
422 if (timer == NGX_TIMER_INFINITE) { 486 if (timer == NGX_TIMER_INFINITE) {
423 tp = NULL; 487 tp = NULL;
424 expire = 0; 488 expire = 0;
425 489
426 } else { 490 } else {
427 ts.tv_sec = timer / 1000; 491 ts.tv_sec = timer / 1000;
428 ts.tv_nsec = (timer % 1000) * 1000000; 492 ts.tv_nsec = (timer % 1000) * 1000000;
429 tp = &ts; 493 tp = &ts;
430 } 494 }
431 495
432 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, 496 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
433 "kevent timer: %d", timer); 497 "kevent timer: %d, changes: %d", timer, n);
434 498
435 events = kevent(ngx_kqueue, change_list, nchanges, event_list, nevents, tp); 499 events = kevent(ngx_kqueue, change_list, n, event_list, nevents, tp);
436 500
437 if (events == -1) { 501 if (events == -1) {
438 err = ngx_errno; 502 err = ngx_errno;
439 } else { 503 } else {
440 err = 0; 504 err = 0;
441 } 505 }
442
443 nchanges = 0;
444 506
445 ngx_gettimeofday(&tv); 507 ngx_gettimeofday(&tv);
446 ngx_time_update(tv.tv_sec); 508 ngx_time_update(tv.tv_sec);
447 509
448 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, 510 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
624 ngx_event_process_posted(cycle); 686 ngx_event_process_posted(cycle);
625 } 687 }
626 } 688 }
627 689
628 return NGX_OK; 690 return NGX_OK;
691 }
692
693
694 static ngx_int_t 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 if (try) {
703 rc = ngx_mutex_trylock(ngx_kqueue_mutex);
704 if (rc != NGX_OK) {
705 return rc;
706 }
707
708 } else {
709 if (ngx_mutex_lock(ngx_kqueue_mutex) == NGX_ERROR) {
710 return NGX_ERROR;
711 }
712 }
713
714 if (nchanges == 0) {
715 ngx_mutex_unlock(ngx_kqueue_mutex);
716 return NGX_OK;
717 }
718
719 changes = (struct kevent *) change_list;
720 if (change_list == change_list0) {
721 change_list = change_list1;
722 } else {
723 change_list = change_list0;
724 }
725
726 n = nchanges;
727 nchanges = 0;
728
729 ts.tv_sec = 0;
730 ts.tv_nsec = 0;
731
732 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
733 "kevent changes: %d", n);
734
735 if (kevent(ngx_kqueue, changes, n, NULL, 0, &ts) == -1) {
736 err = ngx_errno;
737 ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
738 cycle->log, err, "kevent() failed");
739 rc = NGX_ERROR;
740
741 } else {
742 rc = NGX_OK;
743 }
744
745 ngx_mutex_unlock(ngx_kqueue_mutex);
746
747 return rc;
629 } 748 }
630 749
631 750
632 static ngx_inline void ngx_kqueue_dump_event(ngx_log_t *log, struct kevent *kev) 751 static ngx_inline void ngx_kqueue_dump_event(ngx_log_t *log, struct kevent *kev)
633 { 752 {