comparison src/event/modules/ngx_epoll_module.c @ 640:eb208e0cf44d NGINX_1_1_4

nginx 1.1.4 *) Feature: the ngx_http_upstream_keepalive module. *) Feature: the "proxy_http_version" directive. *) Feature: the "fastcgi_keep_conn" directive. *) Feature: the "worker_aio_requests" directive. *) Bugfix: if nginx was built --with-file-aio it could not be run on Linux kernel which did not support AIO. *) Bugfix: in Linux AIO error processing. Thanks to Hagai Avrahami. *) Bugfix: reduced memory consumption for long-lived requests. *) Bugfix: the module ngx_http_mp4_module did not support 64-bit MP4 "co64" atom.
author Igor Sysoev <http://sysoev.ru>
date Tue, 20 Sep 2011 00:00:00 +0400
parents 8dc007eddbcf
children 4d05413aebad
comparison
equal deleted inserted replaced
639:b516b4e38bc9 640:eb208e0cf44d
84 #endif 84 #endif
85 85
86 86
87 typedef struct { 87 typedef struct {
88 ngx_uint_t events; 88 ngx_uint_t events;
89 ngx_uint_t aio_requests;
89 } ngx_epoll_conf_t; 90 } ngx_epoll_conf_t;
90 91
91 92
92 static ngx_int_t ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer); 93 static ngx_int_t ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer);
93 static void ngx_epoll_done(ngx_cycle_t *cycle); 94 static void ngx_epoll_done(ngx_cycle_t *cycle);
129 { ngx_string("epoll_events"), 130 { ngx_string("epoll_events"),
130 NGX_EVENT_CONF|NGX_CONF_TAKE1, 131 NGX_EVENT_CONF|NGX_CONF_TAKE1,
131 ngx_conf_set_num_slot, 132 ngx_conf_set_num_slot,
132 0, 133 0,
133 offsetof(ngx_epoll_conf_t, events), 134 offsetof(ngx_epoll_conf_t, events),
135 NULL },
136
137 { ngx_string("worker_aio_requests"),
138 NGX_EVENT_CONF|NGX_CONF_TAKE1,
139 ngx_conf_set_num_slot,
140 0,
141 offsetof(ngx_epoll_conf_t, aio_requests),
134 NULL }, 142 NULL },
135 143
136 ngx_null_command 144 ngx_null_command
137 }; 145 };
138 146
182 * Also we do not use eventfd() in glibc, because glibc supports it 190 * 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() 191 * since 2.8 version and glibc maps two syscalls eventfd() and eventfd2()
184 * into single eventfd() function with different number of parameters. 192 * into single eventfd() function with different number of parameters.
185 */ 193 */
186 194
187 static long 195 static int
188 io_setup(u_int nr_reqs, aio_context_t *ctx) 196 io_setup(u_int nr_reqs, aio_context_t *ctx)
189 { 197 {
190 return syscall(SYS_io_setup, nr_reqs, ctx); 198 return syscall(SYS_io_setup, nr_reqs, ctx);
191 } 199 }
192 200
196 { 204 {
197 return syscall(SYS_io_destroy, ctx); 205 return syscall(SYS_io_destroy, ctx);
198 } 206 }
199 207
200 208
201 static long 209 static int
202 io_getevents(aio_context_t ctx, long min_nr, long nr, struct io_event *events, 210 io_getevents(aio_context_t ctx, long min_nr, long nr, struct io_event *events,
203 struct timespec *tmo) 211 struct timespec *tmo)
204 { 212 {
205 return syscall(SYS_io_getevents, ctx, min_nr, nr, events, tmo); 213 return syscall(SYS_io_getevents, ctx, min_nr, nr, events, tmo);
214 }
215
216
217 static void
218 ngx_epoll_aio_init(ngx_cycle_t *cycle, ngx_epoll_conf_t *epcf)
219 {
220 int n;
221 struct epoll_event ee;
222
223 ngx_eventfd = syscall(SYS_eventfd, 0);
224
225 if (ngx_eventfd == -1) {
226 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
227 "eventfd() failed");
228 ngx_file_aio = 0;
229 return;
230 }
231
232 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
233 "eventfd: %d", ngx_eventfd);
234
235 n = 1;
236
237 if (ioctl(ngx_eventfd, FIONBIO, &n) == -1) {
238 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
239 "ioctl(eventfd, FIONBIO) failed");
240 goto failed;
241 }
242
243 if (io_setup(epcf->aio_requests, &ngx_aio_ctx) == -1) {
244 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
245 "io_setup() failed");
246 goto failed;
247 }
248
249 ngx_eventfd_event.data = &ngx_eventfd_conn;
250 ngx_eventfd_event.handler = ngx_epoll_eventfd_handler;
251 ngx_eventfd_event.log = cycle->log;
252 ngx_eventfd_event.active = 1;
253 ngx_eventfd_conn.fd = ngx_eventfd;
254 ngx_eventfd_conn.read = &ngx_eventfd_event;
255 ngx_eventfd_conn.log = cycle->log;
256
257 ee.events = EPOLLIN|EPOLLET;
258 ee.data.ptr = &ngx_eventfd_conn;
259
260 if (epoll_ctl(ep, EPOLL_CTL_ADD, ngx_eventfd, &ee) != -1) {
261 return;
262 }
263
264 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
265 "epoll_ctl(EPOLL_CTL_ADD, eventfd) failed");
266
267 if (io_destroy(ngx_aio_ctx) == -1) {
268 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
269 "io_destroy() failed");
270 }
271
272 failed:
273
274 if (close(ngx_eventfd) == -1) {
275 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
276 "eventfd close() failed");
277 }
278
279 ngx_eventfd = -1;
280 ngx_aio_ctx = 0;
281 ngx_file_aio = 0;
206 } 282 }
207 283
208 #endif 284 #endif
209 285
210 286
223 "epoll_create() failed"); 299 "epoll_create() failed");
224 return NGX_ERROR; 300 return NGX_ERROR;
225 } 301 }
226 302
227 #if (NGX_HAVE_FILE_AIO) 303 #if (NGX_HAVE_FILE_AIO)
228 { 304
229 int n; 305 ngx_epoll_aio_init(cycle, epcf);
230 struct epoll_event ee; 306
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 307 #endif
275 } 308 }
276 309
277 if (nevents < epcf->events) { 310 if (nevents < epcf->events) {
278 if (event_list) { 311 if (event_list) {
314 347
315 ep = -1; 348 ep = -1;
316 349
317 #if (NGX_HAVE_FILE_AIO) 350 #if (NGX_HAVE_FILE_AIO)
318 351
319 if (io_destroy(ngx_aio_ctx) != 0) { 352 if (ngx_eventfd != -1) {
320 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, 353
321 "io_destroy() failed"); 354 if (io_destroy(ngx_aio_ctx) == -1) {
355 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
356 "io_destroy() failed");
357 }
358
359 if (close(ngx_eventfd) == -1) {
360 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
361 "eventfd close() failed");
362 }
363
364 ngx_eventfd = -1;
322 } 365 }
323 366
324 ngx_aio_ctx = 0; 367 ngx_aio_ctx = 0;
325 368
326 #endif 369 #endif
665 #if (NGX_HAVE_FILE_AIO) 708 #if (NGX_HAVE_FILE_AIO)
666 709
667 static void 710 static void
668 ngx_epoll_eventfd_handler(ngx_event_t *ev) 711 ngx_epoll_eventfd_handler(ngx_event_t *ev)
669 { 712 {
670 int n; 713 int n, events;
671 long i, events; 714 long i;
672 uint64_t ready; 715 uint64_t ready;
673 ngx_err_t err; 716 ngx_err_t err;
674 ngx_event_t *e; 717 ngx_event_t *e;
675 ngx_event_aio_t *aio; 718 ngx_event_aio_t *aio;
676 struct io_event event[64]; 719 struct io_event event[64];
736 779
737 if (events == 0) { 780 if (events == 0) {
738 return; 781 return;
739 } 782 }
740 783
741 /* events < 0 */ 784 /* events == -1 */
742 ngx_log_error(NGX_LOG_ALERT, ev->log, -events, "io_getevents() failed"); 785 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
786 "io_getevents() failed");
743 return; 787 return;
744 } 788 }
745 } 789 }
746 790
747 #endif 791 #endif
756 if (epcf == NULL) { 800 if (epcf == NULL) {
757 return NULL; 801 return NULL;
758 } 802 }
759 803
760 epcf->events = NGX_CONF_UNSET; 804 epcf->events = NGX_CONF_UNSET;
805 epcf->aio_requests = NGX_CONF_UNSET;
761 806
762 return epcf; 807 return epcf;
763 } 808 }
764 809
765 810
767 ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf) 812 ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf)
768 { 813 {
769 ngx_epoll_conf_t *epcf = conf; 814 ngx_epoll_conf_t *epcf = conf;
770 815
771 ngx_conf_init_uint_value(epcf->events, 512); 816 ngx_conf_init_uint_value(epcf->events, 512);
817 ngx_conf_init_uint_value(epcf->aio_requests, 32);
772 818
773 return NGX_CONF_OK; 819 return NGX_CONF_OK;
774 } 820 }