comparison src/event/modules/ngx_epoll_module.c @ 518: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
517:15b5cddc5190 518: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