Annotation of embedaddon/nginx/src/event/modules/ngx_epoll_module.c, revision 1.1
1.1 ! misho 1:
! 2: /*
! 3: * Copyright (C) Igor Sysoev
! 4: * Copyright (C) Nginx, Inc.
! 5: */
! 6:
! 7:
! 8: #include <ngx_config.h>
! 9: #include <ngx_core.h>
! 10: #include <ngx_event.h>
! 11:
! 12:
! 13: #if (NGX_TEST_BUILD_EPOLL)
! 14:
! 15: /* epoll declarations */
! 16:
! 17: #define EPOLLIN 0x001
! 18: #define EPOLLPRI 0x002
! 19: #define EPOLLOUT 0x004
! 20: #define EPOLLRDNORM 0x040
! 21: #define EPOLLRDBAND 0x080
! 22: #define EPOLLWRNORM 0x100
! 23: #define EPOLLWRBAND 0x200
! 24: #define EPOLLMSG 0x400
! 25: #define EPOLLERR 0x008
! 26: #define EPOLLHUP 0x010
! 27:
! 28: #define EPOLLET 0x80000000
! 29: #define EPOLLONESHOT 0x40000000
! 30:
! 31: #define EPOLL_CTL_ADD 1
! 32: #define EPOLL_CTL_DEL 2
! 33: #define EPOLL_CTL_MOD 3
! 34:
! 35: typedef union epoll_data {
! 36: void *ptr;
! 37: int fd;
! 38: uint32_t u32;
! 39: uint64_t u64;
! 40: } epoll_data_t;
! 41:
! 42: struct epoll_event {
! 43: uint32_t events;
! 44: epoll_data_t data;
! 45: };
! 46:
! 47:
! 48: int epoll_create(int size);
! 49:
! 50: int epoll_create(int size)
! 51: {
! 52: return -1;
! 53: }
! 54:
! 55:
! 56: int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
! 57:
! 58: int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
! 59: {
! 60: return -1;
! 61: }
! 62:
! 63:
! 64: int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout);
! 65:
! 66: int epoll_wait(int epfd, struct epoll_event *events, int nevents, int timeout)
! 67: {
! 68: return -1;
! 69: }
! 70:
! 71: #if (NGX_HAVE_FILE_AIO)
! 72:
! 73: #define SYS_io_setup 245
! 74: #define SYS_io_destroy 246
! 75: #define SYS_io_getevents 247
! 76: #define SYS_eventfd 323
! 77:
! 78: typedef u_int aio_context_t;
! 79:
! 80: struct io_event {
! 81: uint64_t data; /* the data field from the iocb */
! 82: uint64_t obj; /* what iocb this event came from */
! 83: int64_t res; /* result code for this event */
! 84: int64_t res2; /* secondary result */
! 85: };
! 86:
! 87:
! 88: #endif
! 89: #endif
! 90:
! 91:
! 92: typedef struct {
! 93: ngx_uint_t events;
! 94: ngx_uint_t aio_requests;
! 95: } ngx_epoll_conf_t;
! 96:
! 97:
! 98: static ngx_int_t ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer);
! 99: static void ngx_epoll_done(ngx_cycle_t *cycle);
! 100: static ngx_int_t ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event,
! 101: ngx_uint_t flags);
! 102: static ngx_int_t ngx_epoll_del_event(ngx_event_t *ev, ngx_int_t event,
! 103: ngx_uint_t flags);
! 104: static ngx_int_t ngx_epoll_add_connection(ngx_connection_t *c);
! 105: static ngx_int_t ngx_epoll_del_connection(ngx_connection_t *c,
! 106: ngx_uint_t flags);
! 107: static ngx_int_t ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
! 108: ngx_uint_t flags);
! 109:
! 110: #if (NGX_HAVE_FILE_AIO)
! 111: static void ngx_epoll_eventfd_handler(ngx_event_t *ev);
! 112: #endif
! 113:
! 114: static void *ngx_epoll_create_conf(ngx_cycle_t *cycle);
! 115: static char *ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf);
! 116:
! 117: static int ep = -1;
! 118: static struct epoll_event *event_list;
! 119: static ngx_uint_t nevents;
! 120:
! 121: #if (NGX_HAVE_FILE_AIO)
! 122:
! 123: int ngx_eventfd = -1;
! 124: aio_context_t ngx_aio_ctx = 0;
! 125:
! 126: static ngx_event_t ngx_eventfd_event;
! 127: static ngx_connection_t ngx_eventfd_conn;
! 128:
! 129: #endif
! 130:
! 131: static ngx_str_t epoll_name = ngx_string("epoll");
! 132:
! 133: static ngx_command_t ngx_epoll_commands[] = {
! 134:
! 135: { ngx_string("epoll_events"),
! 136: NGX_EVENT_CONF|NGX_CONF_TAKE1,
! 137: ngx_conf_set_num_slot,
! 138: 0,
! 139: offsetof(ngx_epoll_conf_t, events),
! 140: NULL },
! 141:
! 142: { ngx_string("worker_aio_requests"),
! 143: NGX_EVENT_CONF|NGX_CONF_TAKE1,
! 144: ngx_conf_set_num_slot,
! 145: 0,
! 146: offsetof(ngx_epoll_conf_t, aio_requests),
! 147: NULL },
! 148:
! 149: ngx_null_command
! 150: };
! 151:
! 152:
! 153: ngx_event_module_t ngx_epoll_module_ctx = {
! 154: &epoll_name,
! 155: ngx_epoll_create_conf, /* create configuration */
! 156: ngx_epoll_init_conf, /* init configuration */
! 157:
! 158: {
! 159: ngx_epoll_add_event, /* add an event */
! 160: ngx_epoll_del_event, /* delete an event */
! 161: ngx_epoll_add_event, /* enable an event */
! 162: ngx_epoll_del_event, /* disable an event */
! 163: ngx_epoll_add_connection, /* add an connection */
! 164: ngx_epoll_del_connection, /* delete an connection */
! 165: NULL, /* process the changes */
! 166: ngx_epoll_process_events, /* process the events */
! 167: ngx_epoll_init, /* init the events */
! 168: ngx_epoll_done, /* done the events */
! 169: }
! 170: };
! 171:
! 172: ngx_module_t ngx_epoll_module = {
! 173: NGX_MODULE_V1,
! 174: &ngx_epoll_module_ctx, /* module context */
! 175: ngx_epoll_commands, /* module directives */
! 176: NGX_EVENT_MODULE, /* module type */
! 177: NULL, /* init master */
! 178: NULL, /* init module */
! 179: NULL, /* init process */
! 180: NULL, /* init thread */
! 181: NULL, /* exit thread */
! 182: NULL, /* exit process */
! 183: NULL, /* exit master */
! 184: NGX_MODULE_V1_PADDING
! 185: };
! 186:
! 187:
! 188: #if (NGX_HAVE_FILE_AIO)
! 189:
! 190: /*
! 191: * We call io_setup(), io_destroy() io_submit(), and io_getevents() directly
! 192: * as syscalls instead of libaio usage, because the library header file
! 193: * supports eventfd() since 0.3.107 version only.
! 194: *
! 195: * Also we do not use eventfd() in glibc, because glibc supports it
! 196: * since 2.8 version and glibc maps two syscalls eventfd() and eventfd2()
! 197: * into single eventfd() function with different number of parameters.
! 198: */
! 199:
! 200: static int
! 201: io_setup(u_int nr_reqs, aio_context_t *ctx)
! 202: {
! 203: return syscall(SYS_io_setup, nr_reqs, ctx);
! 204: }
! 205:
! 206:
! 207: static int
! 208: io_destroy(aio_context_t ctx)
! 209: {
! 210: return syscall(SYS_io_destroy, ctx);
! 211: }
! 212:
! 213:
! 214: static int
! 215: io_getevents(aio_context_t ctx, long min_nr, long nr, struct io_event *events,
! 216: struct timespec *tmo)
! 217: {
! 218: return syscall(SYS_io_getevents, ctx, min_nr, nr, events, tmo);
! 219: }
! 220:
! 221:
! 222: static void
! 223: ngx_epoll_aio_init(ngx_cycle_t *cycle, ngx_epoll_conf_t *epcf)
! 224: {
! 225: int n;
! 226: struct epoll_event ee;
! 227:
! 228: ngx_eventfd = syscall(SYS_eventfd, 0);
! 229:
! 230: if (ngx_eventfd == -1) {
! 231: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
! 232: "eventfd() failed");
! 233: ngx_file_aio = 0;
! 234: return;
! 235: }
! 236:
! 237: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
! 238: "eventfd: %d", ngx_eventfd);
! 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: goto failed;
! 246: }
! 247:
! 248: if (io_setup(epcf->aio_requests, &ngx_aio_ctx) == -1) {
! 249: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
! 250: "io_setup() failed");
! 251: goto failed;
! 252: }
! 253:
! 254: ngx_eventfd_event.data = &ngx_eventfd_conn;
! 255: ngx_eventfd_event.handler = ngx_epoll_eventfd_handler;
! 256: ngx_eventfd_event.log = cycle->log;
! 257: ngx_eventfd_event.active = 1;
! 258: ngx_eventfd_conn.fd = ngx_eventfd;
! 259: ngx_eventfd_conn.read = &ngx_eventfd_event;
! 260: ngx_eventfd_conn.log = cycle->log;
! 261:
! 262: ee.events = EPOLLIN|EPOLLET;
! 263: ee.data.ptr = &ngx_eventfd_conn;
! 264:
! 265: if (epoll_ctl(ep, EPOLL_CTL_ADD, ngx_eventfd, &ee) != -1) {
! 266: return;
! 267: }
! 268:
! 269: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
! 270: "epoll_ctl(EPOLL_CTL_ADD, eventfd) failed");
! 271:
! 272: if (io_destroy(ngx_aio_ctx) == -1) {
! 273: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
! 274: "io_destroy() failed");
! 275: }
! 276:
! 277: failed:
! 278:
! 279: if (close(ngx_eventfd) == -1) {
! 280: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
! 281: "eventfd close() failed");
! 282: }
! 283:
! 284: ngx_eventfd = -1;
! 285: ngx_aio_ctx = 0;
! 286: ngx_file_aio = 0;
! 287: }
! 288:
! 289: #endif
! 290:
! 291:
! 292: static ngx_int_t
! 293: ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
! 294: {
! 295: ngx_epoll_conf_t *epcf;
! 296:
! 297: epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_epoll_module);
! 298:
! 299: if (ep == -1) {
! 300: ep = epoll_create(cycle->connection_n / 2);
! 301:
! 302: if (ep == -1) {
! 303: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
! 304: "epoll_create() failed");
! 305: return NGX_ERROR;
! 306: }
! 307:
! 308: #if (NGX_HAVE_FILE_AIO)
! 309:
! 310: ngx_epoll_aio_init(cycle, epcf);
! 311:
! 312: #endif
! 313: }
! 314:
! 315: if (nevents < epcf->events) {
! 316: if (event_list) {
! 317: ngx_free(event_list);
! 318: }
! 319:
! 320: event_list = ngx_alloc(sizeof(struct epoll_event) * epcf->events,
! 321: cycle->log);
! 322: if (event_list == NULL) {
! 323: return NGX_ERROR;
! 324: }
! 325: }
! 326:
! 327: nevents = epcf->events;
! 328:
! 329: ngx_io = ngx_os_io;
! 330:
! 331: ngx_event_actions = ngx_epoll_module_ctx.actions;
! 332:
! 333: #if (NGX_HAVE_CLEAR_EVENT)
! 334: ngx_event_flags = NGX_USE_CLEAR_EVENT
! 335: #else
! 336: ngx_event_flags = NGX_USE_LEVEL_EVENT
! 337: #endif
! 338: |NGX_USE_GREEDY_EVENT
! 339: |NGX_USE_EPOLL_EVENT;
! 340:
! 341: return NGX_OK;
! 342: }
! 343:
! 344:
! 345: static void
! 346: ngx_epoll_done(ngx_cycle_t *cycle)
! 347: {
! 348: if (close(ep) == -1) {
! 349: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
! 350: "epoll close() failed");
! 351: }
! 352:
! 353: ep = -1;
! 354:
! 355: #if (NGX_HAVE_FILE_AIO)
! 356:
! 357: if (ngx_eventfd != -1) {
! 358:
! 359: if (io_destroy(ngx_aio_ctx) == -1) {
! 360: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
! 361: "io_destroy() failed");
! 362: }
! 363:
! 364: if (close(ngx_eventfd) == -1) {
! 365: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
! 366: "eventfd close() failed");
! 367: }
! 368:
! 369: ngx_eventfd = -1;
! 370: }
! 371:
! 372: ngx_aio_ctx = 0;
! 373:
! 374: #endif
! 375:
! 376: ngx_free(event_list);
! 377:
! 378: event_list = NULL;
! 379: nevents = 0;
! 380: }
! 381:
! 382:
! 383: static ngx_int_t
! 384: ngx_epoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
! 385: {
! 386: int op;
! 387: uint32_t events, prev;
! 388: ngx_event_t *e;
! 389: ngx_connection_t *c;
! 390: struct epoll_event ee;
! 391:
! 392: c = ev->data;
! 393:
! 394: events = (uint32_t) event;
! 395:
! 396: if (event == NGX_READ_EVENT) {
! 397: e = c->write;
! 398: prev = EPOLLOUT;
! 399: #if (NGX_READ_EVENT != EPOLLIN)
! 400: events = EPOLLIN;
! 401: #endif
! 402:
! 403: } else {
! 404: e = c->read;
! 405: prev = EPOLLIN;
! 406: #if (NGX_WRITE_EVENT != EPOLLOUT)
! 407: events = EPOLLOUT;
! 408: #endif
! 409: }
! 410:
! 411: if (e->active) {
! 412: op = EPOLL_CTL_MOD;
! 413: events |= prev;
! 414:
! 415: } else {
! 416: op = EPOLL_CTL_ADD;
! 417: }
! 418:
! 419: ee.events = events | (uint32_t) flags;
! 420: ee.data.ptr = (void *) ((uintptr_t) c | ev->instance);
! 421:
! 422: ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
! 423: "epoll add event: fd:%d op:%d ev:%08XD",
! 424: c->fd, op, ee.events);
! 425:
! 426: if (epoll_ctl(ep, op, c->fd, &ee) == -1) {
! 427: ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
! 428: "epoll_ctl(%d, %d) failed", op, c->fd);
! 429: return NGX_ERROR;
! 430: }
! 431:
! 432: ev->active = 1;
! 433: #if 0
! 434: ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1 : 0;
! 435: #endif
! 436:
! 437: return NGX_OK;
! 438: }
! 439:
! 440:
! 441: static ngx_int_t
! 442: ngx_epoll_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
! 443: {
! 444: int op;
! 445: uint32_t prev;
! 446: ngx_event_t *e;
! 447: ngx_connection_t *c;
! 448: struct epoll_event ee;
! 449:
! 450: /*
! 451: * when the file descriptor is closed, the epoll automatically deletes
! 452: * it from its queue, so we do not need to delete explicitly the event
! 453: * before the closing the file descriptor
! 454: */
! 455:
! 456: if (flags & NGX_CLOSE_EVENT) {
! 457: ev->active = 0;
! 458: return NGX_OK;
! 459: }
! 460:
! 461: c = ev->data;
! 462:
! 463: if (event == NGX_READ_EVENT) {
! 464: e = c->write;
! 465: prev = EPOLLOUT;
! 466:
! 467: } else {
! 468: e = c->read;
! 469: prev = EPOLLIN;
! 470: }
! 471:
! 472: if (e->active) {
! 473: op = EPOLL_CTL_MOD;
! 474: ee.events = prev | (uint32_t) flags;
! 475: ee.data.ptr = (void *) ((uintptr_t) c | ev->instance);
! 476:
! 477: } else {
! 478: op = EPOLL_CTL_DEL;
! 479: ee.events = 0;
! 480: ee.data.ptr = NULL;
! 481: }
! 482:
! 483: ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
! 484: "epoll del event: fd:%d op:%d ev:%08XD",
! 485: c->fd, op, ee.events);
! 486:
! 487: if (epoll_ctl(ep, op, c->fd, &ee) == -1) {
! 488: ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
! 489: "epoll_ctl(%d, %d) failed", op, c->fd);
! 490: return NGX_ERROR;
! 491: }
! 492:
! 493: ev->active = 0;
! 494:
! 495: return NGX_OK;
! 496: }
! 497:
! 498:
! 499: static ngx_int_t
! 500: ngx_epoll_add_connection(ngx_connection_t *c)
! 501: {
! 502: struct epoll_event ee;
! 503:
! 504: ee.events = EPOLLIN|EPOLLOUT|EPOLLET;
! 505: ee.data.ptr = (void *) ((uintptr_t) c | c->read->instance);
! 506:
! 507: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0,
! 508: "epoll add connection: fd:%d ev:%08XD", c->fd, ee.events);
! 509:
! 510: if (epoll_ctl(ep, EPOLL_CTL_ADD, c->fd, &ee) == -1) {
! 511: ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
! 512: "epoll_ctl(EPOLL_CTL_ADD, %d) failed", c->fd);
! 513: return NGX_ERROR;
! 514: }
! 515:
! 516: c->read->active = 1;
! 517: c->write->active = 1;
! 518:
! 519: return NGX_OK;
! 520: }
! 521:
! 522:
! 523: static ngx_int_t
! 524: ngx_epoll_del_connection(ngx_connection_t *c, ngx_uint_t flags)
! 525: {
! 526: int op;
! 527: struct epoll_event ee;
! 528:
! 529: /*
! 530: * when the file descriptor is closed the epoll automatically deletes
! 531: * it from its queue so we do not need to delete explicitly the event
! 532: * before the closing the file descriptor
! 533: */
! 534:
! 535: if (flags & NGX_CLOSE_EVENT) {
! 536: c->read->active = 0;
! 537: c->write->active = 0;
! 538: return NGX_OK;
! 539: }
! 540:
! 541: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
! 542: "epoll del connection: fd:%d", c->fd);
! 543:
! 544: op = EPOLL_CTL_DEL;
! 545: ee.events = 0;
! 546: ee.data.ptr = NULL;
! 547:
! 548: if (epoll_ctl(ep, op, c->fd, &ee) == -1) {
! 549: ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
! 550: "epoll_ctl(%d, %d) failed", op, c->fd);
! 551: return NGX_ERROR;
! 552: }
! 553:
! 554: c->read->active = 0;
! 555: c->write->active = 0;
! 556:
! 557: return NGX_OK;
! 558: }
! 559:
! 560:
! 561: static ngx_int_t
! 562: ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
! 563: {
! 564: int events;
! 565: uint32_t revents;
! 566: ngx_int_t instance, i;
! 567: ngx_uint_t level;
! 568: ngx_err_t err;
! 569: ngx_event_t *rev, *wev, **queue;
! 570: ngx_connection_t *c;
! 571:
! 572: /* NGX_TIMER_INFINITE == INFTIM */
! 573:
! 574: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
! 575: "epoll timer: %M", timer);
! 576:
! 577: events = epoll_wait(ep, event_list, (int) nevents, timer);
! 578:
! 579: err = (events == -1) ? ngx_errno : 0;
! 580:
! 581: if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
! 582: ngx_time_update();
! 583: }
! 584:
! 585: if (err) {
! 586: if (err == NGX_EINTR) {
! 587:
! 588: if (ngx_event_timer_alarm) {
! 589: ngx_event_timer_alarm = 0;
! 590: return NGX_OK;
! 591: }
! 592:
! 593: level = NGX_LOG_INFO;
! 594:
! 595: } else {
! 596: level = NGX_LOG_ALERT;
! 597: }
! 598:
! 599: ngx_log_error(level, cycle->log, err, "epoll_wait() failed");
! 600: return NGX_ERROR;
! 601: }
! 602:
! 603: if (events == 0) {
! 604: if (timer != NGX_TIMER_INFINITE) {
! 605: return NGX_OK;
! 606: }
! 607:
! 608: ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
! 609: "epoll_wait() returned no events without timeout");
! 610: return NGX_ERROR;
! 611: }
! 612:
! 613: ngx_mutex_lock(ngx_posted_events_mutex);
! 614:
! 615: for (i = 0; i < events; i++) {
! 616: c = event_list[i].data.ptr;
! 617:
! 618: instance = (uintptr_t) c & 1;
! 619: c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);
! 620:
! 621: rev = c->read;
! 622:
! 623: if (c->fd == -1 || rev->instance != instance) {
! 624:
! 625: /*
! 626: * the stale event from a file descriptor
! 627: * that was just closed in this iteration
! 628: */
! 629:
! 630: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
! 631: "epoll: stale event %p", c);
! 632: continue;
! 633: }
! 634:
! 635: revents = event_list[i].events;
! 636:
! 637: ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
! 638: "epoll: fd:%d ev:%04XD d:%p",
! 639: c->fd, revents, event_list[i].data.ptr);
! 640:
! 641: if (revents & (EPOLLERR|EPOLLHUP)) {
! 642: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
! 643: "epoll_wait() error on fd:%d ev:%04XD",
! 644: c->fd, revents);
! 645: }
! 646:
! 647: #if 0
! 648: if (revents & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) {
! 649: ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
! 650: "strange epoll_wait() events fd:%d ev:%04XD",
! 651: c->fd, revents);
! 652: }
! 653: #endif
! 654:
! 655: if ((revents & (EPOLLERR|EPOLLHUP))
! 656: && (revents & (EPOLLIN|EPOLLOUT)) == 0)
! 657: {
! 658: /*
! 659: * if the error events were returned without EPOLLIN or EPOLLOUT,
! 660: * then add these flags to handle the events at least in one
! 661: * active handler
! 662: */
! 663:
! 664: revents |= EPOLLIN|EPOLLOUT;
! 665: }
! 666:
! 667: if ((revents & EPOLLIN) && rev->active) {
! 668:
! 669: if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) {
! 670: rev->posted_ready = 1;
! 671:
! 672: } else {
! 673: rev->ready = 1;
! 674: }
! 675:
! 676: if (flags & NGX_POST_EVENTS) {
! 677: queue = (ngx_event_t **) (rev->accept ?
! 678: &ngx_posted_accept_events : &ngx_posted_events);
! 679:
! 680: ngx_locked_post_event(rev, queue);
! 681:
! 682: } else {
! 683: rev->handler(rev);
! 684: }
! 685: }
! 686:
! 687: wev = c->write;
! 688:
! 689: if ((revents & EPOLLOUT) && wev->active) {
! 690:
! 691: if (c->fd == -1 || wev->instance != instance) {
! 692:
! 693: /*
! 694: * the stale event from a file descriptor
! 695: * that was just closed in this iteration
! 696: */
! 697:
! 698: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
! 699: "epoll: stale event %p", c);
! 700: continue;
! 701: }
! 702:
! 703: if (flags & NGX_POST_THREAD_EVENTS) {
! 704: wev->posted_ready = 1;
! 705:
! 706: } else {
! 707: wev->ready = 1;
! 708: }
! 709:
! 710: if (flags & NGX_POST_EVENTS) {
! 711: ngx_locked_post_event(wev, &ngx_posted_events);
! 712:
! 713: } else {
! 714: wev->handler(wev);
! 715: }
! 716: }
! 717: }
! 718:
! 719: ngx_mutex_unlock(ngx_posted_events_mutex);
! 720:
! 721: return NGX_OK;
! 722: }
! 723:
! 724:
! 725: #if (NGX_HAVE_FILE_AIO)
! 726:
! 727: static void
! 728: ngx_epoll_eventfd_handler(ngx_event_t *ev)
! 729: {
! 730: int n, events;
! 731: long i;
! 732: uint64_t ready;
! 733: ngx_err_t err;
! 734: ngx_event_t *e;
! 735: ngx_event_aio_t *aio;
! 736: struct io_event event[64];
! 737: struct timespec ts;
! 738:
! 739: ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "eventfd handler");
! 740:
! 741: n = read(ngx_eventfd, &ready, 8);
! 742:
! 743: err = ngx_errno;
! 744:
! 745: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, "eventfd: %d", n);
! 746:
! 747: if (n != 8) {
! 748: if (n == -1) {
! 749: if (err == NGX_EAGAIN) {
! 750: return;
! 751: }
! 752:
! 753: ngx_log_error(NGX_LOG_ALERT, ev->log, err, "read(eventfd) failed");
! 754: return;
! 755: }
! 756:
! 757: ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
! 758: "read(eventfd) returned only %d bytes", n);
! 759: return;
! 760: }
! 761:
! 762: ts.tv_sec = 0;
! 763: ts.tv_nsec = 0;
! 764:
! 765: while (ready) {
! 766:
! 767: events = io_getevents(ngx_aio_ctx, 1, 64, event, &ts);
! 768:
! 769: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
! 770: "io_getevents: %l", events);
! 771:
! 772: if (events > 0) {
! 773: ready -= events;
! 774:
! 775: for (i = 0; i < events; i++) {
! 776:
! 777: ngx_log_debug4(NGX_LOG_DEBUG_EVENT, ev->log, 0,
! 778: "io_event: %uXL %uXL %L %L",
! 779: event[i].data, event[i].obj,
! 780: event[i].res, event[i].res2);
! 781:
! 782: e = (ngx_event_t *) (uintptr_t) event[i].data;
! 783:
! 784: e->complete = 1;
! 785: e->active = 0;
! 786: e->ready = 1;
! 787:
! 788: aio = e->data;
! 789: aio->res = event[i].res;
! 790:
! 791: ngx_post_event(e, &ngx_posted_events);
! 792: }
! 793:
! 794: continue;
! 795: }
! 796:
! 797: if (events == 0) {
! 798: return;
! 799: }
! 800:
! 801: /* events == -1 */
! 802: ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
! 803: "io_getevents() failed");
! 804: return;
! 805: }
! 806: }
! 807:
! 808: #endif
! 809:
! 810:
! 811: static void *
! 812: ngx_epoll_create_conf(ngx_cycle_t *cycle)
! 813: {
! 814: ngx_epoll_conf_t *epcf;
! 815:
! 816: epcf = ngx_palloc(cycle->pool, sizeof(ngx_epoll_conf_t));
! 817: if (epcf == NULL) {
! 818: return NULL;
! 819: }
! 820:
! 821: epcf->events = NGX_CONF_UNSET;
! 822: epcf->aio_requests = NGX_CONF_UNSET;
! 823:
! 824: return epcf;
! 825: }
! 826:
! 827:
! 828: static char *
! 829: ngx_epoll_init_conf(ngx_cycle_t *cycle, void *conf)
! 830: {
! 831: ngx_epoll_conf_t *epcf = conf;
! 832:
! 833: ngx_conf_init_uint_value(epcf->events, 512);
! 834: ngx_conf_init_uint_value(epcf->aio_requests, 32);
! 835:
! 836: return NGX_CONF_OK;
! 837: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>