comparison src/event/modules/ngx_epoll_module.c @ 3052:6060225e9261

FreeBSD and Linux AIO support
author Igor Sysoev <igor@sysoev.ru>
date Fri, 28 Aug 2009 08:12:35 +0000
parents a1d54c705f38
children 0299cf5856fc
comparison
equal deleted inserted replaced
3051:26dfc0fa22c8 3052:6060225e9261
56 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)
57 { 57 {
58 return -1; 58 return -1;
59 } 59 }
60 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
61 #endif 84 #endif
62 85
63 86
64 typedef struct { 87 typedef struct {
65 ngx_uint_t events; 88 ngx_uint_t events;
76 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,
77 ngx_uint_t flags); 100 ngx_uint_t flags);
78 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,
79 ngx_uint_t flags); 102 ngx_uint_t flags);
80 103
104 #if (NGX_HAVE_FILE_AIO)
105 static void ngx_epoll_eventfd_handler(ngx_event_t *ev);
106 #endif
107
81 static void *ngx_epoll_create_conf(ngx_cycle_t *cycle); 108 static void *ngx_epoll_create_conf(ngx_cycle_t *cycle);
82 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);
83 110
84 static int ep = -1; 111 static int ep = -1;
85 static struct epoll_event *event_list; 112 static struct epoll_event *event_list;
86 static ngx_uint_t nevents; 113 static ngx_uint_t nevents;
87 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
88 124
89 static ngx_str_t epoll_name = ngx_string("epoll"); 125 static ngx_str_t epoll_name = ngx_string("epoll");
90 126
91 static ngx_command_t ngx_epoll_commands[] = { 127 static ngx_command_t ngx_epoll_commands[] = {
92 128
134 NULL, /* exit master */ 170 NULL, /* exit master */
135 NGX_MODULE_V1_PADDING 171 NGX_MODULE_V1_PADDING
136 }; 172 };
137 173
138 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
139 static ngx_int_t 211 static ngx_int_t
140 ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer) 212 ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
141 { 213 {
142 ngx_epoll_conf_t *epcf; 214 ngx_epoll_conf_t *epcf;
143 215
149 if (ep == -1) { 221 if (ep == -1) {
150 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, 222 ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
151 "epoll_create() failed"); 223 "epoll_create() failed");
152 return NGX_ERROR; 224 return NGX_ERROR;
153 } 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
154 } 275 }
155 276
156 if (nevents < epcf->events) { 277 if (nevents < epcf->events) {
157 if (event_list) { 278 if (event_list) {
158 ngx_free(event_list); 279 ngx_free(event_list);
190 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, 311 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
191 "epoll close() failed"); 312 "epoll close() failed");
192 } 313 }
193 314
194 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
195 327
196 ngx_free(event_list); 328 ngx_free(event_list);
197 329
198 event_list = NULL; 330 event_list = NULL;
199 nevents = 0; 331 nevents = 0;
535 667
536 return NGX_OK; 668 return NGX_OK;
537 } 669 }
538 670
539 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
540 static void * 757 static void *
541 ngx_epoll_create_conf(ngx_cycle_t *cycle) 758 ngx_epoll_create_conf(ngx_cycle_t *cycle)
542 { 759 {
543 ngx_epoll_conf_t *epcf; 760 ngx_epoll_conf_t *epcf;
544 761