Mercurial > hg > nginx
comparison src/event/modules/ngx_epoll_module.c @ 6019:40e244e042a7
Events: implemented epoll notification mechanism.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Sat, 14 Mar 2015 17:37:13 +0300 |
parents | 466bd63b63d1 |
children | 4652f8f26b12 |
comparison
equal
deleted
inserted
replaced
6018:466bd63b63d1 | 6019:40e244e042a7 |
---|---|
68 int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout) | 68 int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout) |
69 { | 69 { |
70 return -1; | 70 return -1; |
71 } | 71 } |
72 | 72 |
73 #if (NGX_HAVE_EVENTFD) | |
74 #define SYS_eventfd 323 | |
75 #endif | |
76 | |
73 #if (NGX_HAVE_FILE_AIO) | 77 #if (NGX_HAVE_FILE_AIO) |
74 | 78 |
75 #define SYS_io_setup 245 | 79 #define SYS_io_setup 245 |
76 #define SYS_io_destroy 246 | 80 #define SYS_io_destroy 246 |
77 #define SYS_io_getevents 247 | 81 #define SYS_io_getevents 247 |
78 #define SYS_eventfd 323 | |
79 | 82 |
80 typedef u_int aio_context_t; | 83 typedef u_int aio_context_t; |
81 | 84 |
82 struct io_event { | 85 struct io_event { |
83 uint64_t data; /* the data field from the iocb */ | 86 uint64_t data; /* the data field from the iocb */ |
86 int64_t res2; /* secondary result */ | 89 int64_t res2; /* secondary result */ |
87 }; | 90 }; |
88 | 91 |
89 | 92 |
90 #endif | 93 #endif |
91 #endif | 94 #endif /* NGX_TEST_BUILD_EPOLL */ |
92 | 95 |
93 | 96 |
94 typedef struct { | 97 typedef struct { |
95 ngx_uint_t events; | 98 ngx_uint_t events; |
96 ngx_uint_t aio_requests; | 99 ngx_uint_t aio_requests; |
97 } ngx_epoll_conf_t; | 100 } ngx_epoll_conf_t; |
98 | 101 |
99 | 102 |
100 static ngx_int_t ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer); | 103 static ngx_int_t ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer); |
104 #if (NGX_HAVE_EVENTFD) | |
105 static ngx_int_t ngx_epoll_notify_init(ngx_log_t *log); | |
106 static void ngx_epoll_notify_handler(ngx_event_t *ev); | |
107 #endif | |
101 static void ngx_epoll_done(ngx_cycle_t *cycle); | 108 static void ngx_epoll_done(ngx_cycle_t *cycle); |
102 static ngx_int_t ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, | 109 static ngx_int_t ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, |
103 ngx_uint_t flags); | 110 ngx_uint_t flags); |
104 static ngx_int_t ngx_epoll_del_event(ngx_event_t *ev, ngx_int_t event, | 111 static ngx_int_t ngx_epoll_del_event(ngx_event_t *ev, ngx_int_t event, |
105 ngx_uint_t flags); | 112 ngx_uint_t flags); |
106 static ngx_int_t ngx_epoll_add_connection(ngx_connection_t *c); | 113 static ngx_int_t ngx_epoll_add_connection(ngx_connection_t *c); |
107 static ngx_int_t ngx_epoll_del_connection(ngx_connection_t *c, | 114 static ngx_int_t ngx_epoll_del_connection(ngx_connection_t *c, |
108 ngx_uint_t flags); | 115 ngx_uint_t flags); |
116 #if (NGX_HAVE_EVENTFD) | |
117 static ngx_int_t ngx_epoll_notify(ngx_event_handler_pt handler); | |
118 #endif | |
109 static ngx_int_t ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, | 119 static ngx_int_t ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, |
110 ngx_uint_t flags); | 120 ngx_uint_t flags); |
111 | 121 |
112 #if (NGX_HAVE_FILE_AIO) | 122 #if (NGX_HAVE_FILE_AIO) |
113 static void ngx_epoll_eventfd_handler(ngx_event_t *ev); | 123 static void ngx_epoll_eventfd_handler(ngx_event_t *ev); |
117 static char *ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf); | 127 static char *ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf); |
118 | 128 |
119 static int ep = -1; | 129 static int ep = -1; |
120 static struct epoll_event *event_list; | 130 static struct epoll_event *event_list; |
121 static ngx_uint_t nevents; | 131 static ngx_uint_t nevents; |
132 | |
133 #if (NGX_HAVE_EVENTFD) | |
134 static int notify_fd = -1; | |
135 static ngx_event_t notify_event; | |
136 static ngx_connection_t notify_conn; | |
137 #endif | |
122 | 138 |
123 #if (NGX_HAVE_FILE_AIO) | 139 #if (NGX_HAVE_FILE_AIO) |
124 | 140 |
125 int ngx_eventfd = -1; | 141 int ngx_eventfd = -1; |
126 aio_context_t ngx_aio_ctx = 0; | 142 aio_context_t ngx_aio_ctx = 0; |
162 ngx_epoll_del_event, /* delete an event */ | 178 ngx_epoll_del_event, /* delete an event */ |
163 ngx_epoll_add_event, /* enable an event */ | 179 ngx_epoll_add_event, /* enable an event */ |
164 ngx_epoll_del_event, /* disable an event */ | 180 ngx_epoll_del_event, /* disable an event */ |
165 ngx_epoll_add_connection, /* add an connection */ | 181 ngx_epoll_add_connection, /* add an connection */ |
166 ngx_epoll_del_connection, /* delete an connection */ | 182 ngx_epoll_del_connection, /* delete an connection */ |
183 #if (NGX_HAVE_EVENTFD) | |
184 ngx_epoll_notify, /* trigger a notify */ | |
185 #else | |
167 NULL, /* trigger a notify */ | 186 NULL, /* trigger a notify */ |
187 #endif | |
168 NULL, /* process the changes */ | 188 NULL, /* process the changes */ |
169 ngx_epoll_process_events, /* process the events */ | 189 ngx_epoll_process_events, /* process the events */ |
170 ngx_epoll_init, /* init the events */ | 190 ngx_epoll_init, /* init the events */ |
171 ngx_epoll_done, /* done the events */ | 191 ngx_epoll_done, /* done the events */ |
172 } | 192 } |
306 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | 326 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, |
307 "epoll_create() failed"); | 327 "epoll_create() failed"); |
308 return NGX_ERROR; | 328 return NGX_ERROR; |
309 } | 329 } |
310 | 330 |
331 #if (NGX_HAVE_EVENTFD) | |
332 if (ngx_epoll_notify_init(cycle->log) != NGX_OK) { | |
333 return NGX_ERROR; | |
334 } | |
335 #endif | |
336 | |
311 #if (NGX_HAVE_FILE_AIO) | 337 #if (NGX_HAVE_FILE_AIO) |
312 | 338 |
313 ngx_epoll_aio_init(cycle, epcf); | 339 ngx_epoll_aio_init(cycle, epcf); |
314 | 340 |
315 #endif | 341 #endif |
343 | 369 |
344 return NGX_OK; | 370 return NGX_OK; |
345 } | 371 } |
346 | 372 |
347 | 373 |
374 #if (NGX_HAVE_EVENTFD) | |
375 | |
376 static ngx_int_t | |
377 ngx_epoll_notify_init(ngx_log_t *log) | |
378 { | |
379 struct epoll_event ee; | |
380 | |
381 #if (NGX_HAVE_SYS_EVENTFD_H) | |
382 notify_fd = eventfd(0, 0); | |
383 #else | |
384 notify_fd = syscall(SYS_eventfd, 0); | |
385 #endif | |
386 | |
387 if (notify_fd == -1) { | |
388 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "eventfd() failed"); | |
389 return NGX_ERROR; | |
390 } | |
391 | |
392 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, | |
393 "notify eventfd: %d", notify_fd); | |
394 | |
395 notify_event.handler = ngx_epoll_notify_handler; | |
396 notify_event.log = log; | |
397 notify_event.active = 1; | |
398 | |
399 notify_conn.fd = notify_fd; | |
400 notify_conn.read = ¬ify_event; | |
401 notify_conn.log = log; | |
402 | |
403 ee.events = EPOLLIN|EPOLLET; | |
404 ee.data.ptr = ¬ify_conn; | |
405 | |
406 if (epoll_ctl(ep, EPOLL_CTL_ADD, notify_fd, &ee) == -1) { | |
407 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, | |
408 "epoll_ctl(EPOLL_CTL_ADD, eventfd) failed"); | |
409 | |
410 if (close(notify_fd) == -1) { | |
411 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, | |
412 "eventfd close() failed"); | |
413 } | |
414 | |
415 return NGX_ERROR; | |
416 } | |
417 | |
418 return NGX_OK; | |
419 } | |
420 | |
421 | |
422 static void | |
423 ngx_epoll_notify_handler(ngx_event_t *ev) | |
424 { | |
425 ssize_t n; | |
426 uint64_t count; | |
427 ngx_err_t err; | |
428 ngx_event_handler_pt handler; | |
429 | |
430 if (++ev->index == NGX_MAX_UINT32_VALUE) { | |
431 ev->index = 0; | |
432 | |
433 n = read(notify_fd, &count, sizeof(uint64_t)); | |
434 | |
435 err = ngx_errno; | |
436 | |
437 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0, | |
438 "read() eventfd %d: %z count:%uL", notify_fd, n, count); | |
439 | |
440 if ((size_t) n != sizeof(uint64_t)) { | |
441 ngx_log_error(NGX_LOG_ALERT, ev->log, err, | |
442 "read() eventfd %d failed", notify_fd); | |
443 } | |
444 } | |
445 | |
446 handler = ev->data; | |
447 handler(ev); | |
448 } | |
449 | |
450 #endif | |
451 | |
452 | |
348 static void | 453 static void |
349 ngx_epoll_done(ngx_cycle_t *cycle) | 454 ngx_epoll_done(ngx_cycle_t *cycle) |
350 { | 455 { |
351 if (close(ep) == -1) { | 456 if (close(ep) == -1) { |
352 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | 457 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, |
353 "epoll close() failed"); | 458 "epoll close() failed"); |
354 } | 459 } |
355 | 460 |
356 ep = -1; | 461 ep = -1; |
462 | |
463 #if (NGX_HAVE_EVENTFD) | |
464 | |
465 if (close(notify_fd) == -1) { | |
466 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
467 "eventfd close() failed"); | |
468 } | |
469 | |
470 notify_fd = -1; | |
471 | |
472 #endif | |
357 | 473 |
358 #if (NGX_HAVE_FILE_AIO) | 474 #if (NGX_HAVE_FILE_AIO) |
359 | 475 |
360 if (ngx_eventfd != -1) { | 476 if (ngx_eventfd != -1) { |
361 | 477 |
557 c->read->active = 0; | 673 c->read->active = 0; |
558 c->write->active = 0; | 674 c->write->active = 0; |
559 | 675 |
560 return NGX_OK; | 676 return NGX_OK; |
561 } | 677 } |
678 | |
679 | |
680 #if (NGX_HAVE_EVENTFD) | |
681 | |
682 static ngx_int_t | |
683 ngx_epoll_notify(ngx_event_handler_pt handler) | |
684 { | |
685 static uint64_t inc = 1; | |
686 | |
687 if ((size_t) write(notify_fd, &inc, sizeof(uint64_t)) != sizeof(uint64_t)) { | |
688 ngx_log_error(NGX_LOG_ALERT, notify_event.log, ngx_errno, | |
689 "write() to eventfd %d failed", notify_fd); | |
690 return NGX_ERROR; | |
691 } | |
692 | |
693 notify_event.data = handler; | |
694 | |
695 return NGX_OK; | |
696 } | |
697 | |
698 #endif | |
562 | 699 |
563 | 700 |
564 static ngx_int_t | 701 static ngx_int_t |
565 ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) | 702 ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) |
566 { | 703 { |