Annotation of embedaddon/nginx/src/event/modules/ngx_poll_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: static ngx_int_t ngx_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer);
        !            14: static void ngx_poll_done(ngx_cycle_t *cycle);
        !            15: static ngx_int_t ngx_poll_add_event(ngx_event_t *ev, ngx_int_t event,
        !            16:     ngx_uint_t flags);
        !            17: static ngx_int_t ngx_poll_del_event(ngx_event_t *ev, ngx_int_t event,
        !            18:     ngx_uint_t flags);
        !            19: static ngx_int_t ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
        !            20:     ngx_uint_t flags);
        !            21: static char *ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf);
        !            22: 
        !            23: 
        !            24: static struct pollfd  *event_list;
        !            25: static ngx_int_t       nevents;
        !            26: 
        !            27: 
        !            28: static ngx_str_t    poll_name = ngx_string("poll");
        !            29: 
        !            30: ngx_event_module_t  ngx_poll_module_ctx = {
        !            31:     &poll_name,
        !            32:     NULL,                                  /* create configuration */
        !            33:     ngx_poll_init_conf,                    /* init configuration */
        !            34: 
        !            35:     {
        !            36:         ngx_poll_add_event,                /* add an event */
        !            37:         ngx_poll_del_event,                /* delete an event */
        !            38:         ngx_poll_add_event,                /* enable an event */
        !            39:         ngx_poll_del_event,                /* disable an event */
        !            40:         NULL,                              /* add an connection */
        !            41:         NULL,                              /* delete an connection */
        !            42:         NULL,                              /* process the changes */
        !            43:         ngx_poll_process_events,           /* process the events */
        !            44:         ngx_poll_init,                     /* init the events */
        !            45:         ngx_poll_done                      /* done the events */
        !            46:     }
        !            47: 
        !            48: };
        !            49: 
        !            50: ngx_module_t  ngx_poll_module = {
        !            51:     NGX_MODULE_V1,
        !            52:     &ngx_poll_module_ctx,                  /* module context */
        !            53:     NULL,                                  /* module directives */
        !            54:     NGX_EVENT_MODULE,                      /* module type */
        !            55:     NULL,                                  /* init master */
        !            56:     NULL,                                  /* init module */
        !            57:     NULL,                                  /* init process */
        !            58:     NULL,                                  /* init thread */
        !            59:     NULL,                                  /* exit thread */
        !            60:     NULL,                                  /* exit process */
        !            61:     NULL,                                  /* exit master */
        !            62:     NGX_MODULE_V1_PADDING
        !            63: };
        !            64: 
        !            65: 
        !            66: 
        !            67: static ngx_int_t
        !            68: ngx_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
        !            69: {
        !            70:     struct pollfd   *list;
        !            71: 
        !            72:     if (event_list == NULL) {
        !            73:         nevents = 0;
        !            74:     }
        !            75: 
        !            76:     if (ngx_process >= NGX_PROCESS_WORKER
        !            77:         || cycle->old_cycle == NULL
        !            78:         || cycle->old_cycle->connection_n < cycle->connection_n)
        !            79:     {
        !            80:         list = ngx_alloc(sizeof(struct pollfd) * cycle->connection_n,
        !            81:                          cycle->log);
        !            82:         if (list == NULL) {
        !            83:             return NGX_ERROR;
        !            84:         }
        !            85: 
        !            86:         if (event_list) {
        !            87:             ngx_memcpy(list, event_list, sizeof(ngx_event_t *) * nevents);
        !            88:             ngx_free(event_list);
        !            89:         }
        !            90: 
        !            91:         event_list = list;
        !            92:     }
        !            93: 
        !            94:     ngx_io = ngx_os_io;
        !            95: 
        !            96:     ngx_event_actions = ngx_poll_module_ctx.actions;
        !            97: 
        !            98:     ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_FD_EVENT;
        !            99: 
        !           100:     return NGX_OK;
        !           101: }
        !           102: 
        !           103: 
        !           104: static void
        !           105: ngx_poll_done(ngx_cycle_t *cycle)
        !           106: {
        !           107:     ngx_free(event_list);
        !           108: 
        !           109:     event_list = NULL;
        !           110: }
        !           111: 
        !           112: 
        !           113: static ngx_int_t
        !           114: ngx_poll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
        !           115: {
        !           116:     ngx_event_t       *e;
        !           117:     ngx_connection_t  *c;
        !           118: 
        !           119:     c = ev->data;
        !           120: 
        !           121:     ev->active = 1;
        !           122: 
        !           123:     if (ev->index != NGX_INVALID_INDEX) {
        !           124:         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
        !           125:                       "poll event fd:%d ev:%i is already set", c->fd, event);
        !           126:         return NGX_OK;
        !           127:     }
        !           128: 
        !           129:     if (event == NGX_READ_EVENT) {
        !           130:         e = c->write;
        !           131: #if (NGX_READ_EVENT != POLLIN)
        !           132:         event = POLLIN;
        !           133: #endif
        !           134: 
        !           135:     } else {
        !           136:         e = c->read;
        !           137: #if (NGX_WRITE_EVENT != POLLOUT)
        !           138:         event = POLLOUT;
        !           139: #endif
        !           140:     }
        !           141: 
        !           142:     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
        !           143:                    "poll add event: fd:%d ev:%i", c->fd, event);
        !           144: 
        !           145:     if (e == NULL || e->index == NGX_INVALID_INDEX) {
        !           146:         event_list[nevents].fd = c->fd;
        !           147:         event_list[nevents].events = (short) event;
        !           148:         event_list[nevents].revents = 0;
        !           149: 
        !           150:         ev->index = nevents;
        !           151:         nevents++;
        !           152: 
        !           153:     } else {
        !           154:         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
        !           155:                        "poll add index: %i", e->index);
        !           156: 
        !           157:         event_list[e->index].events |= (short) event;
        !           158:         ev->index = e->index;
        !           159:     }
        !           160: 
        !           161:     return NGX_OK;
        !           162: }
        !           163: 
        !           164: 
        !           165: static ngx_int_t
        !           166: ngx_poll_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
        !           167: {
        !           168:     ngx_event_t       *e;
        !           169:     ngx_connection_t  *c;
        !           170: 
        !           171:     c = ev->data;
        !           172: 
        !           173:     ev->active = 0;
        !           174: 
        !           175:     if (ev->index == NGX_INVALID_INDEX) {
        !           176:         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
        !           177:                       "poll event fd:%d ev:%i is already deleted",
        !           178:                       c->fd, event);
        !           179:         return NGX_OK;
        !           180:     }
        !           181: 
        !           182:     if (event == NGX_READ_EVENT) {
        !           183:         e = c->write;
        !           184: #if (NGX_READ_EVENT != POLLIN)
        !           185:         event = POLLIN;
        !           186: #endif
        !           187: 
        !           188:     } else {
        !           189:         e = c->read;
        !           190: #if (NGX_WRITE_EVENT != POLLOUT)
        !           191:         event = POLLOUT;
        !           192: #endif
        !           193:     }
        !           194: 
        !           195:     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
        !           196:                    "poll del event: fd:%d ev:%i", c->fd, event);
        !           197: 
        !           198:     if (e == NULL || e->index == NGX_INVALID_INDEX) {
        !           199:         nevents--;
        !           200: 
        !           201:         if (ev->index < (ngx_uint_t) nevents) {
        !           202: 
        !           203:             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
        !           204:                            "index: copy event %ui to %i", nevents, ev->index);
        !           205: 
        !           206:             event_list[ev->index] = event_list[nevents];
        !           207: 
        !           208:             c = ngx_cycle->files[event_list[nevents].fd];
        !           209: 
        !           210:             if (c->fd == -1) {
        !           211:                 ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
        !           212:                               "unexpected last event");
        !           213: 
        !           214:             } else {
        !           215:                 if (c->read->index == (ngx_uint_t) nevents) {
        !           216:                     c->read->index = ev->index;
        !           217:                 }
        !           218: 
        !           219:                 if (c->write->index == (ngx_uint_t) nevents) {
        !           220:                     c->write->index = ev->index;
        !           221:                 }
        !           222:             }
        !           223:         }
        !           224: 
        !           225:     } else {
        !           226:         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
        !           227:                        "poll del index: %i", e->index);
        !           228: 
        !           229:         event_list[e->index].events &= (short) ~event;
        !           230:     }
        !           231: 
        !           232:     ev->index = NGX_INVALID_INDEX;
        !           233: 
        !           234:     return NGX_OK;
        !           235: }
        !           236: 
        !           237: 
        !           238: static ngx_int_t
        !           239: ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
        !           240: {
        !           241:     int                 ready, revents;
        !           242:     ngx_err_t           err;
        !           243:     ngx_int_t           i, nready;
        !           244:     ngx_uint_t          found, level;
        !           245:     ngx_event_t        *ev, **queue;
        !           246:     ngx_connection_t   *c;
        !           247: 
        !           248:     /* NGX_TIMER_INFINITE == INFTIM */
        !           249: 
        !           250: #if (NGX_DEBUG0)
        !           251:     if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
        !           252:         for (i = 0; i < nevents; i++) {
        !           253:             ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
        !           254:                            "poll: %d: fd:%d ev:%04Xd",
        !           255:                            i, event_list[i].fd, event_list[i].events);
        !           256:         }
        !           257:     }
        !           258: #endif
        !           259: 
        !           260:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "poll timer: %M", timer);
        !           261: 
        !           262:     ready = poll(event_list, (u_int) nevents, (int) timer);
        !           263: 
        !           264:     err = (ready == -1) ? ngx_errno : 0;
        !           265: 
        !           266:     if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
        !           267:         ngx_time_update();
        !           268:     }
        !           269: 
        !           270:     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
        !           271:                    "poll ready %d of %d", ready, nevents);
        !           272: 
        !           273:     if (err) {
        !           274:         if (err == NGX_EINTR) {
        !           275: 
        !           276:             if (ngx_event_timer_alarm) {
        !           277:                 ngx_event_timer_alarm = 0;
        !           278:                 return NGX_OK;
        !           279:             }
        !           280: 
        !           281:             level = NGX_LOG_INFO;
        !           282: 
        !           283:         } else {
        !           284:             level = NGX_LOG_ALERT;
        !           285:         }
        !           286: 
        !           287:         ngx_log_error(level, cycle->log, err, "poll() failed");
        !           288:         return NGX_ERROR;
        !           289:     }
        !           290: 
        !           291:     if (ready == 0) {
        !           292:         if (timer != NGX_TIMER_INFINITE) {
        !           293:             return NGX_OK;
        !           294:         }
        !           295: 
        !           296:         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
        !           297:                       "poll() returned no events without timeout");
        !           298:         return NGX_ERROR;
        !           299:     }
        !           300: 
        !           301:     ngx_mutex_lock(ngx_posted_events_mutex);
        !           302: 
        !           303:     nready = 0;
        !           304: 
        !           305:     for (i = 0; i < nevents && ready; i++) {
        !           306: 
        !           307:         revents = event_list[i].revents;
        !           308: 
        !           309: #if 1
        !           310:         ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
        !           311:                        "poll: %d: fd:%d ev:%04Xd rev:%04Xd",
        !           312:                        i, event_list[i].fd, event_list[i].events, revents);
        !           313: #else
        !           314:         if (revents) {
        !           315:             ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
        !           316:                            "poll: %d: fd:%d ev:%04Xd rev:%04Xd",
        !           317:                            i, event_list[i].fd, event_list[i].events, revents);
        !           318:         }
        !           319: #endif
        !           320: 
        !           321:         if (revents & POLLNVAL) {
        !           322:             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
        !           323:                           "poll() error fd:%d ev:%04Xd rev:%04Xd",
        !           324:                           event_list[i].fd, event_list[i].events, revents);
        !           325:         }
        !           326: 
        !           327:         if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
        !           328:             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
        !           329:                           "strange poll() events fd:%d ev:%04Xd rev:%04Xd",
        !           330:                           event_list[i].fd, event_list[i].events, revents);
        !           331:         }
        !           332: 
        !           333:         if (event_list[i].fd == -1) {
        !           334:             /*
        !           335:              * the disabled event, a workaround for our possible bug,
        !           336:              * see the comment below
        !           337:              */
        !           338:             continue;
        !           339:         }
        !           340: 
        !           341:         c = ngx_cycle->files[event_list[i].fd];
        !           342: 
        !           343:         if (c->fd == -1) {
        !           344:             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected event");
        !           345: 
        !           346:             /*
        !           347:              * it is certainly our fault and it should be investigated,
        !           348:              * in the meantime we disable this event to avoid a CPU spinning
        !           349:              */
        !           350: 
        !           351:             if (i == nevents - 1) {
        !           352:                 nevents--;
        !           353:             } else {
        !           354:                 event_list[i].fd = -1;
        !           355:             }
        !           356: 
        !           357:             continue;
        !           358:         }
        !           359: 
        !           360:         if ((revents & (POLLERR|POLLHUP|POLLNVAL))
        !           361:              && (revents & (POLLIN|POLLOUT)) == 0)
        !           362:         {
        !           363:             /*
        !           364:              * if the error events were returned without POLLIN or POLLOUT,
        !           365:              * then add these flags to handle the events at least in one
        !           366:              * active handler
        !           367:              */
        !           368: 
        !           369:             revents |= POLLIN|POLLOUT;
        !           370:         }
        !           371: 
        !           372:         found = 0;
        !           373: 
        !           374:         if ((revents & POLLIN) && c->read->active) {
        !           375:             found = 1;
        !           376: 
        !           377:             ev = c->read;
        !           378: 
        !           379:             if ((flags & NGX_POST_THREAD_EVENTS) && !ev->accept) {
        !           380:                 ev->posted_ready = 1;
        !           381: 
        !           382:             } else {
        !           383:                 ev->ready = 1;
        !           384:             }
        !           385: 
        !           386:             queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events:
        !           387:                                                    &ngx_posted_events);
        !           388:             ngx_locked_post_event(ev, queue);
        !           389:         }
        !           390: 
        !           391:         if ((revents & POLLOUT) && c->write->active) {
        !           392:             found = 1;
        !           393:             ev = c->write;
        !           394: 
        !           395:             if (flags & NGX_POST_THREAD_EVENTS) {
        !           396:                 ev->posted_ready = 1;
        !           397: 
        !           398:             } else {
        !           399:                 ev->ready = 1;
        !           400:             }
        !           401: 
        !           402:             ngx_locked_post_event(ev, &ngx_posted_events);
        !           403:         }
        !           404: 
        !           405:         if (found) {
        !           406:             ready--;
        !           407:             continue;
        !           408:         }
        !           409:     }
        !           410: 
        !           411:     ngx_mutex_unlock(ngx_posted_events_mutex);
        !           412: 
        !           413:     if (ready != 0) {
        !           414:         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "poll ready != events");
        !           415:     }
        !           416: 
        !           417:     return nready;
        !           418: }
        !           419: 
        !           420: 
        !           421: static char *
        !           422: ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf)
        !           423: {
        !           424:     ngx_event_conf_t  *ecf;
        !           425: 
        !           426:     ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
        !           427: 
        !           428:     if (ecf->use != ngx_poll_module.ctx_index) {
        !           429:         return NGX_CONF_OK;
        !           430:     }
        !           431: 
        !           432: #if (NGX_THREADS)
        !           433: 
        !           434:     ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
        !           435:                   "poll() is not supported in the threaded mode");
        !           436:     return NGX_CONF_ERROR;
        !           437: 
        !           438: #else
        !           439: 
        !           440:     return NGX_CONF_OK;
        !           441: 
        !           442: #endif
        !           443: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>