Mercurial > hg > nginx-ranges
comparison src/event/modules/ngx_epoll_module.c @ 529:86dad910eeb6 NGINX_0_8_11
nginx 0.8.11
*) Change: directive "gzip_disable msie6" enables gzipping for
MSIE 6.0 SV1.
*) Feature: file AIO support on FreeBSD and Linux.
*) Feature: the "directio_alignment" directive.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Fri, 28 Aug 2009 00:00:00 +0400 |
parents | f39b9e29530d |
children | be4f34123024 |
comparison
equal
deleted
inserted
replaced
528:15b5cddc5190 | 529:86dad910eeb6 |
---|---|
41 struct epoll_event { | 41 struct epoll_event { |
42 uint32_t events; | 42 uint32_t events; |
43 epoll_data_t data; | 43 epoll_data_t data; |
44 }; | 44 }; |
45 | 45 |
46 int epoll_create(int size); | |
47 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); | |
48 int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout); | |
49 | |
50 int epoll_create(int size) | 46 int epoll_create(int size) |
51 { | 47 { |
52 return -1; | 48 return -1; |
53 } | 49 } |
54 | 50 |
60 int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout) | 56 int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout) |
61 { | 57 { |
62 return -1; | 58 return -1; |
63 } | 59 } |
64 | 60 |
61 #if (NGX_HAVE_FILE_AIO) | |
62 | |
63 #define SYS_io_setup 245 | |
64 #define SYS_io_destroy 246 | |
65 #define SYS_io_getevents 247 | |
66 #define SYS_eventfd 323 | |
67 | |
68 typedef u_int aio_context_t; | |
69 | |
70 struct io_event { | |
71 uint64_t data; /* the data field from the iocb */ | |
72 uint64_t obj; /* what iocb this event came from */ | |
73 int64_t res; /* result code for this event */ | |
74 int64_t res2; /* secondary result */ | |
75 }; | |
76 | |
77 | |
78 int eventfd(u_int initval) | |
79 { | |
80 return -1; | |
81 } | |
82 | |
83 #endif | |
65 #endif | 84 #endif |
66 | 85 |
67 | 86 |
68 typedef struct { | 87 typedef struct { |
69 ngx_uint_t events; | 88 ngx_uint_t events; |
80 static ngx_int_t ngx_epoll_del_connection(ngx_connection_t *c, | 99 static ngx_int_t ngx_epoll_del_connection(ngx_connection_t *c, |
81 ngx_uint_t flags); | 100 ngx_uint_t flags); |
82 static ngx_int_t ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, | 101 static ngx_int_t ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, |
83 ngx_uint_t flags); | 102 ngx_uint_t flags); |
84 | 103 |
104 #if (NGX_HAVE_FILE_AIO) | |
105 static void ngx_epoll_eventfd_handler(ngx_event_t *ev); | |
106 #endif | |
107 | |
85 static void *ngx_epoll_create_conf(ngx_cycle_t *cycle); | 108 static void *ngx_epoll_create_conf(ngx_cycle_t *cycle); |
86 static char *ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf); | 109 static char *ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf); |
87 | 110 |
88 static int ep = -1; | 111 static int ep = -1; |
89 static struct epoll_event *event_list; | 112 static struct epoll_event *event_list; |
90 static ngx_uint_t nevents; | 113 static ngx_uint_t nevents; |
91 | 114 |
115 #if (NGX_HAVE_FILE_AIO) | |
116 | |
117 int ngx_eventfd = -1; | |
118 aio_context_t ngx_aio_ctx = 0; | |
119 | |
120 static ngx_event_t ngx_eventfd_event; | |
121 static ngx_connection_t ngx_eventfd_conn; | |
122 | |
123 #endif | |
92 | 124 |
93 static ngx_str_t epoll_name = ngx_string("epoll"); | 125 static ngx_str_t epoll_name = ngx_string("epoll"); |
94 | 126 |
95 static ngx_command_t ngx_epoll_commands[] = { | 127 static ngx_command_t ngx_epoll_commands[] = { |
96 | 128 |
138 NULL, /* exit master */ | 170 NULL, /* exit master */ |
139 NGX_MODULE_V1_PADDING | 171 NGX_MODULE_V1_PADDING |
140 }; | 172 }; |
141 | 173 |
142 | 174 |
175 #if (NGX_HAVE_FILE_AIO) | |
176 | |
177 /* | |
178 * We call io_setup(), io_destroy() io_submit(), and io_getevents() directly | |
179 * as syscalls instead of libaio usage, because the library header file | |
180 * supports eventfd() since 0.3.107 version only. | |
181 * | |
182 * Also we do not use eventfd() in glibc, because glibc supports it | |
183 * since 2.8 version and glibc maps two syscalls eventfd() and eventfd2() | |
184 * into single eventfd() function with different number of parameters. | |
185 */ | |
186 | |
187 static long | |
188 io_setup(u_int nr_reqs, aio_context_t *ctx) | |
189 { | |
190 return syscall(SYS_io_setup, nr_reqs, ctx); | |
191 } | |
192 | |
193 | |
194 static int | |
195 io_destroy(aio_context_t ctx) | |
196 { | |
197 return syscall(SYS_io_destroy, ctx); | |
198 } | |
199 | |
200 | |
201 static long | |
202 io_getevents(aio_context_t ctx, long min_nr, long nr, struct io_event *events, | |
203 struct timespec *tmo) | |
204 { | |
205 return syscall(SYS_io_getevents, ctx, min_nr, nr, events, tmo); | |
206 } | |
207 | |
208 #endif | |
209 | |
210 | |
143 static ngx_int_t | 211 static ngx_int_t |
144 ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer) | 212 ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer) |
145 { | 213 { |
146 ngx_epoll_conf_t *epcf; | 214 ngx_epoll_conf_t *epcf; |
147 | 215 |
153 if (ep == -1) { | 221 if (ep == -1) { |
154 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | 222 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, |
155 "epoll_create() failed"); | 223 "epoll_create() failed"); |
156 return NGX_ERROR; | 224 return NGX_ERROR; |
157 } | 225 } |
226 | |
227 #if (NGX_HAVE_FILE_AIO) | |
228 { | |
229 int n; | |
230 struct epoll_event ee; | |
231 | |
232 ngx_eventfd = syscall(SYS_eventfd, 0); | |
233 | |
234 if (ngx_eventfd == -1) { | |
235 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
236 "eventfd() failed"); | |
237 return NGX_ERROR; | |
238 } | |
239 | |
240 n = 1; | |
241 | |
242 if (ioctl(ngx_eventfd, FIONBIO, &n) == -1) { | |
243 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
244 "ioctl(eventfd, FIONBIO) failed"); | |
245 } | |
246 | |
247 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | |
248 "eventfd: %d", ngx_eventfd); | |
249 | |
250 n = io_setup(1024, &ngx_aio_ctx); | |
251 | |
252 if (n != 0) { | |
253 ngx_log_error(NGX_LOG_EMERG, cycle->log, -n, "io_setup() failed"); | |
254 return NGX_ERROR; | |
255 } | |
256 | |
257 ngx_eventfd_event.data = &ngx_eventfd_conn; | |
258 ngx_eventfd_event.handler = ngx_epoll_eventfd_handler; | |
259 ngx_eventfd_event.log = cycle->log; | |
260 ngx_eventfd_event.active = 1; | |
261 ngx_eventfd_conn.fd = ngx_eventfd; | |
262 ngx_eventfd_conn.read = &ngx_eventfd_event; | |
263 ngx_eventfd_conn.log = cycle->log; | |
264 | |
265 ee.events = EPOLLIN|EPOLLET; | |
266 ee.data.ptr = &ngx_eventfd_conn; | |
267 | |
268 if (epoll_ctl(ep, EPOLL_CTL_ADD, ngx_eventfd, &ee) == -1) { | |
269 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, | |
270 "epoll_ctl(EPOLL_CTL_ADD, eventfd) failed"); | |
271 return NGX_ERROR; | |
272 } | |
273 } | |
274 #endif | |
158 } | 275 } |
159 | 276 |
160 if (nevents < epcf->events) { | 277 if (nevents < epcf->events) { |
161 if (event_list) { | 278 if (event_list) { |
162 ngx_free(event_list); | 279 ngx_free(event_list); |
194 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | 311 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, |
195 "epoll close() failed"); | 312 "epoll close() failed"); |
196 } | 313 } |
197 | 314 |
198 ep = -1; | 315 ep = -1; |
316 | |
317 #if (NGX_HAVE_FILE_AIO) | |
318 | |
319 if (io_destroy(ngx_aio_ctx) != 0) { | |
320 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, | |
321 "io_destroy() failed"); | |
322 } | |
323 | |
324 ngx_aio_ctx = 0; | |
325 | |
326 #endif | |
199 | 327 |
200 ngx_free(event_list); | 328 ngx_free(event_list); |
201 | 329 |
202 event_list = NULL; | 330 event_list = NULL; |
203 nevents = 0; | 331 nevents = 0; |
399 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, | 527 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, |
400 "epoll timer: %M", timer); | 528 "epoll timer: %M", timer); |
401 | 529 |
402 events = epoll_wait(ep, event_list, (int) nevents, timer); | 530 events = epoll_wait(ep, event_list, (int) nevents, timer); |
403 | 531 |
404 if (events == -1) { | 532 err = (events == -1) ? ngx_errno : 0; |
405 err = ngx_errno; | |
406 } else { | |
407 err = 0; | |
408 } | |
409 | 533 |
410 if (flags & NGX_UPDATE_TIME) { | 534 if (flags & NGX_UPDATE_TIME) { |
411 ngx_time_update(0, 0); | 535 ngx_time_update(0, 0); |
412 } | 536 } |
413 | 537 |
543 | 667 |
544 return NGX_OK; | 668 return NGX_OK; |
545 } | 669 } |
546 | 670 |
547 | 671 |
672 #if (NGX_HAVE_FILE_AIO) | |
673 | |
674 static void | |
675 ngx_epoll_eventfd_handler(ngx_event_t *ev) | |
676 { | |
677 int n; | |
678 long i, events; | |
679 uint64_t ready; | |
680 ngx_err_t err; | |
681 ngx_event_t *e; | |
682 ngx_event_aio_t *aio; | |
683 struct io_event event[64]; | |
684 struct timespec ts; | |
685 | |
686 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "eventfd handler"); | |
687 | |
688 n = read(ngx_eventfd, &ready, 8); | |
689 | |
690 err = ngx_errno; | |
691 | |
692 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, "eventfd: %d", n); | |
693 | |
694 if (n != 8) { | |
695 if (n == -1) { | |
696 if (err == NGX_EAGAIN) { | |
697 return; | |
698 } | |
699 | |
700 ngx_log_error(NGX_LOG_ALERT, ev->log, err, "read(eventfd) failed"); | |
701 return; | |
702 } | |
703 | |
704 ngx_log_error(NGX_LOG_ALERT, ev->log, 0, | |
705 "read(eventfd) returned only %d bytes", n); | |
706 return; | |
707 } | |
708 | |
709 ts.tv_sec = 0; | |
710 ts.tv_nsec = 0; | |
711 | |
712 while (ready) { | |
713 | |
714 events = io_getevents(ngx_aio_ctx, 1, 64, event, &ts); | |
715 | |
716 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, | |
717 "io_getevents: %l", events); | |
718 | |
719 if (events > 0) { | |
720 ready -= events; | |
721 | |
722 for (i = 0; i < events; i++) { | |
723 | |
724 ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ev->log, 0, | |
725 "io_event: %uXL %uXL %L %L", | |
726 event[i].data, event[i].obj, | |
727 event[i].res, event[i].res2); | |
728 | |
729 e = (ngx_event_t *) (uintptr_t) event[i].data; | |
730 | |
731 e->complete = 1; | |
732 e->active = 0; | |
733 e->ready = 1; | |
734 | |
735 aio = e->data; | |
736 aio->res = event[i].res; | |
737 | |
738 ngx_post_event(e, &ngx_posted_events); | |
739 } | |
740 | |
741 continue; | |
742 } | |
743 | |
744 if (events == 0) { | |
745 return; | |
746 } | |
747 | |
748 /* events < 0 */ | |
749 ngx_log_error(NGX_LOG_ALERT, ev->log, -events, "io_getevents() failed"); | |
750 return; | |
751 } | |
752 } | |
753 | |
754 #endif | |
755 | |
756 | |
548 static void * | 757 static void * |
549 ngx_epoll_create_conf(ngx_cycle_t *cycle) | 758 ngx_epoll_create_conf(ngx_cycle_t *cycle) |
550 { | 759 { |
551 ngx_epoll_conf_t *epcf; | 760 ngx_epoll_conf_t *epcf; |
552 | 761 |