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 = &notify_event;
401 notify_conn.log = log;
402
403 ee.events = EPOLLIN|EPOLLET;
404 ee.data.ptr = &notify_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 {