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>