Annotation of embedaddon/nginx/src/event/modules/ngx_poll_module.c, revision 1.1.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>