Annotation of embedaddon/nginx/src/event/modules/ngx_devpoll_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: #if (NGX_TEST_BUILD_DEVPOLL)
                     14: 
                     15: /* Solaris declarations */
                     16: 
                     17: #define POLLREMOVE   0x0800
                     18: #define DP_POLL      0xD001
                     19: #define DP_ISPOLLED  0xD002
                     20: 
                     21: struct dvpoll {
                     22:     struct pollfd  *dp_fds;
                     23:     int             dp_nfds;
                     24:     int             dp_timeout;
                     25: };
                     26: 
                     27: #endif
                     28: 
                     29: 
                     30: typedef struct {
                     31:     ngx_uint_t      changes;
                     32:     ngx_uint_t      events;
                     33: } ngx_devpoll_conf_t;
                     34: 
                     35: 
                     36: static ngx_int_t ngx_devpoll_init(ngx_cycle_t *cycle, ngx_msec_t timer);
                     37: static void ngx_devpoll_done(ngx_cycle_t *cycle);
                     38: static ngx_int_t ngx_devpoll_add_event(ngx_event_t *ev, ngx_int_t event,
                     39:     ngx_uint_t flags);
                     40: static ngx_int_t ngx_devpoll_del_event(ngx_event_t *ev, ngx_int_t event,
                     41:     ngx_uint_t flags);
                     42: static ngx_int_t ngx_devpoll_set_event(ngx_event_t *ev, ngx_int_t event,
                     43:     ngx_uint_t flags);
                     44: static ngx_int_t ngx_devpoll_process_events(ngx_cycle_t *cycle,
                     45:     ngx_msec_t timer, ngx_uint_t flags);
                     46: 
                     47: static void *ngx_devpoll_create_conf(ngx_cycle_t *cycle);
                     48: static char *ngx_devpoll_init_conf(ngx_cycle_t *cycle, void *conf);
                     49: 
                     50: static int              dp = -1;
                     51: static struct pollfd   *change_list, *event_list;
                     52: static ngx_uint_t       nchanges, max_changes, nevents;
                     53: 
                     54: static ngx_event_t    **change_index;
                     55: 
                     56: 
                     57: static ngx_str_t      devpoll_name = ngx_string("/dev/poll");
                     58: 
                     59: static ngx_command_t  ngx_devpoll_commands[] = {
                     60: 
                     61:     { ngx_string("devpoll_changes"),
                     62:       NGX_EVENT_CONF|NGX_CONF_TAKE1,
                     63:       ngx_conf_set_num_slot,
                     64:       0,
                     65:       offsetof(ngx_devpoll_conf_t, changes),
                     66:       NULL },
                     67: 
                     68:     { ngx_string("devpoll_events"),
                     69:       NGX_EVENT_CONF|NGX_CONF_TAKE1,
                     70:       ngx_conf_set_num_slot,
                     71:       0,
                     72:       offsetof(ngx_devpoll_conf_t, events),
                     73:       NULL },
                     74: 
                     75:       ngx_null_command
                     76: };
                     77: 
                     78: 
                     79: ngx_event_module_t  ngx_devpoll_module_ctx = {
                     80:     &devpoll_name,
                     81:     ngx_devpoll_create_conf,               /* create configuration */
                     82:     ngx_devpoll_init_conf,                 /* init configuration */
                     83: 
                     84:     {
                     85:         ngx_devpoll_add_event,             /* add an event */
                     86:         ngx_devpoll_del_event,             /* delete an event */
                     87:         ngx_devpoll_add_event,             /* enable an event */
                     88:         ngx_devpoll_del_event,             /* disable an event */
                     89:         NULL,                              /* add an connection */
                     90:         NULL,                              /* delete an connection */
                     91:         NULL,                              /* process the changes */
                     92:         ngx_devpoll_process_events,        /* process the events */
                     93:         ngx_devpoll_init,                  /* init the events */
                     94:         ngx_devpoll_done,                  /* done the events */
                     95:     }
                     96: 
                     97: };
                     98: 
                     99: ngx_module_t  ngx_devpoll_module = {
                    100:     NGX_MODULE_V1,
                    101:     &ngx_devpoll_module_ctx,               /* module context */
                    102:     ngx_devpoll_commands,                  /* module directives */
                    103:     NGX_EVENT_MODULE,                      /* module type */
                    104:     NULL,                                  /* init master */
                    105:     NULL,                                  /* init module */
                    106:     NULL,                                  /* init process */
                    107:     NULL,                                  /* init thread */
                    108:     NULL,                                  /* exit thread */
                    109:     NULL,                                  /* exit process */
                    110:     NULL,                                  /* exit master */
                    111:     NGX_MODULE_V1_PADDING
                    112: };
                    113: 
                    114: 
                    115: static ngx_int_t
                    116: ngx_devpoll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
                    117: {
                    118:     size_t               n;
                    119:     ngx_devpoll_conf_t  *dpcf;
                    120: 
                    121:     dpcf = ngx_event_get_conf(cycle->conf_ctx, ngx_devpoll_module);
                    122: 
                    123:     if (dp == -1) {
                    124:         dp = open("/dev/poll", O_RDWR);
                    125: 
                    126:         if (dp == -1) {
                    127:             ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                    128:                           "open(/dev/poll) failed");
                    129:             return NGX_ERROR;
                    130:         }
                    131:     }
                    132: 
                    133:     if (max_changes < dpcf->changes) {
                    134:         if (nchanges) {
                    135:             n = nchanges * sizeof(struct pollfd);
                    136:             if (write(dp, change_list, n) != (ssize_t) n) {
                    137:                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                    138:                               "write(/dev/poll) failed");
                    139:                 return NGX_ERROR;
                    140:             }
                    141: 
                    142:             nchanges = 0;
                    143:         }
                    144: 
                    145:         if (change_list) {
                    146:             ngx_free(change_list);
                    147:         }
                    148: 
                    149:         change_list = ngx_alloc(sizeof(struct pollfd) * dpcf->changes,
                    150:                                 cycle->log);
                    151:         if (change_list == NULL) {
                    152:             return NGX_ERROR;
                    153:         }
                    154: 
                    155:         if (change_index) {
                    156:             ngx_free(change_index);
                    157:         }
                    158: 
                    159:         change_index = ngx_alloc(sizeof(ngx_event_t *) * dpcf->changes,
                    160:                                  cycle->log);
                    161:         if (change_index == NULL) {
                    162:             return NGX_ERROR;
                    163:         }
                    164:     }
                    165: 
                    166:     max_changes = dpcf->changes;
                    167: 
                    168:     if (nevents < dpcf->events) {
                    169:         if (event_list) {
                    170:             ngx_free(event_list);
                    171:         }
                    172: 
                    173:         event_list = ngx_alloc(sizeof(struct pollfd) * dpcf->events,
                    174:                                cycle->log);
                    175:         if (event_list == NULL) {
                    176:             return NGX_ERROR;
                    177:         }
                    178:     }
                    179: 
                    180:     nevents = dpcf->events;
                    181: 
                    182:     ngx_io = ngx_os_io;
                    183: 
                    184:     ngx_event_actions = ngx_devpoll_module_ctx.actions;
                    185: 
                    186:     ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_FD_EVENT;
                    187: 
                    188:     return NGX_OK;
                    189: }
                    190: 
                    191: 
                    192: static void
                    193: ngx_devpoll_done(ngx_cycle_t *cycle)
                    194: {
                    195:     if (close(dp) == -1) {
                    196:         ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                    197:                       "close(/dev/poll) failed");
                    198:     }
                    199: 
                    200:     dp = -1;
                    201: 
                    202:     ngx_free(change_list);
                    203:     ngx_free(event_list);
                    204:     ngx_free(change_index);
                    205: 
                    206:     change_list = NULL;
                    207:     event_list = NULL;
                    208:     change_index = NULL;
                    209:     max_changes = 0;
                    210:     nchanges = 0;
                    211:     nevents = 0;
                    212: }
                    213: 
                    214: 
                    215: static ngx_int_t
                    216: ngx_devpoll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
                    217: {
                    218: #if (NGX_DEBUG)
                    219:     ngx_connection_t *c;
                    220: #endif
                    221: 
                    222: #if (NGX_READ_EVENT != POLLIN)
                    223:     event = (event == NGX_READ_EVENT) ? POLLIN : POLLOUT;
                    224: #endif
                    225: 
                    226: #if (NGX_DEBUG)
                    227:     c = ev->data;
                    228:     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                    229:                    "devpoll add event: fd:%d ev:%04Xi", c->fd, event);
                    230: #endif
                    231: 
                    232:     ev->active = 1;
                    233: 
                    234:     return ngx_devpoll_set_event(ev, event, 0);
                    235: }
                    236: 
                    237: 
                    238: static ngx_int_t
                    239: ngx_devpoll_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
                    240: {
                    241:     ngx_event_t       *e;
                    242:     ngx_connection_t  *c;
                    243: 
                    244:     c = ev->data;
                    245: 
                    246: #if (NGX_READ_EVENT != POLLIN)
                    247:     event = (event == NGX_READ_EVENT) ? POLLIN : POLLOUT;
                    248: #endif
                    249: 
                    250:     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                    251:                    "devpoll del event: fd:%d ev:%04Xi", c->fd, event);
                    252: 
                    253:     if (ngx_devpoll_set_event(ev, POLLREMOVE, flags) == NGX_ERROR) {
                    254:         return NGX_ERROR;
                    255:     }
                    256: 
                    257:     ev->active = 0;
                    258: 
                    259:     if (flags & NGX_CLOSE_EVENT) {
                    260:         e = (event == POLLIN) ? c->write : c->read;
                    261: 
                    262:         if (e) {
                    263:             e->active = 0;
                    264:         }
                    265: 
                    266:         return NGX_OK;
                    267:     }
                    268: 
                    269:     /* restore the pair event if it exists */
                    270: 
                    271:     if (event == POLLIN) {
                    272:         e = c->write;
                    273:         event = POLLOUT;
                    274: 
                    275:     } else {
                    276:         e = c->read;
                    277:         event = POLLIN;
                    278:     }
                    279: 
                    280:     if (e && e->active) {
                    281:         return ngx_devpoll_set_event(e, event, 0);
                    282:     }
                    283: 
                    284:     return NGX_OK;
                    285: }
                    286: 
                    287: 
                    288: static ngx_int_t
                    289: ngx_devpoll_set_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
                    290: {
                    291:     size_t             n;
                    292:     ngx_connection_t  *c;
                    293: 
                    294:     c = ev->data;
                    295: 
                    296:     ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
                    297:                    "devpoll fd:%d ev:%04Xi fl:%04Xi", c->fd, event, flags);
                    298: 
                    299:     if (nchanges >= max_changes) {
                    300:         ngx_log_error(NGX_LOG_WARN, ev->log, 0,
                    301:                       "/dev/pool change list is filled up");
                    302: 
                    303:         n = nchanges * sizeof(struct pollfd);
                    304:         if (write(dp, change_list, n) != (ssize_t) n) {
                    305:             ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
                    306:                           "write(/dev/poll) failed");
                    307:             return NGX_ERROR;
                    308:         }
                    309: 
                    310:         nchanges = 0;
                    311:     }
                    312: 
                    313:     change_list[nchanges].fd = c->fd;
                    314:     change_list[nchanges].events = (short) event;
                    315:     change_list[nchanges].revents = 0;
                    316: 
                    317:     change_index[nchanges] = ev;
                    318:     ev->index = nchanges;
                    319: 
                    320:     nchanges++;
                    321: 
                    322:     if (flags & NGX_CLOSE_EVENT) {
                    323:         n = nchanges * sizeof(struct pollfd);
                    324:         if (write(dp, change_list, n) != (ssize_t) n) {
                    325:             ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno,
                    326:                           "write(/dev/poll) failed");
                    327:             return NGX_ERROR;
                    328:         }
                    329: 
                    330:         nchanges = 0;
                    331:     }
                    332: 
                    333:     return NGX_OK;
                    334: }
                    335: 
                    336: 
                    337: ngx_int_t
                    338: ngx_devpoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
                    339:     ngx_uint_t flags)
                    340: {
                    341:     int                 events, revents, rc;
                    342:     size_t              n;
                    343:     ngx_fd_t            fd;
                    344:     ngx_err_t           err;
                    345:     ngx_int_t           i;
                    346:     ngx_uint_t          level, instance;
                    347:     ngx_event_t        *rev, *wev, **queue;
                    348:     ngx_connection_t   *c;
                    349:     struct pollfd       pfd;
                    350:     struct dvpoll       dvp;
                    351: 
                    352:     /* NGX_TIMER_INFINITE == INFTIM */
                    353: 
                    354:     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    355:                    "devpoll timer: %M", timer);
                    356: 
                    357:     if (nchanges) {
                    358:         n = nchanges * sizeof(struct pollfd);
                    359:         if (write(dp, change_list, n) != (ssize_t) n) {
                    360:             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                    361:                           "write(/dev/poll) failed");
                    362:             return NGX_ERROR;
                    363:         }
                    364: 
                    365:         nchanges = 0;
                    366:     }
                    367: 
                    368:     dvp.dp_fds = event_list;
                    369:     dvp.dp_nfds = (int) nevents;
                    370:     dvp.dp_timeout = timer;
                    371:     events = ioctl(dp, DP_POLL, &dvp);
                    372: 
                    373:     err = (events == -1) ? ngx_errno : 0;
                    374: 
                    375:     if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
                    376:         ngx_time_update();
                    377:     }
                    378: 
                    379:     if (err) {
                    380:         if (err == NGX_EINTR) {
                    381: 
                    382:             if (ngx_event_timer_alarm) {
                    383:                 ngx_event_timer_alarm = 0;
                    384:                 return NGX_OK;
                    385:             }
                    386: 
                    387:             level = NGX_LOG_INFO;
                    388: 
                    389:         } else {
                    390:             level = NGX_LOG_ALERT;
                    391:         }
                    392: 
                    393:         ngx_log_error(level, cycle->log, err, "ioctl(DP_POLL) failed");
                    394:         return NGX_ERROR;
                    395:     }
                    396: 
                    397:     if (events == 0) {
                    398:         if (timer != NGX_TIMER_INFINITE) {
                    399:             return NGX_OK;
                    400:         }
                    401: 
                    402:         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                    403:                       "ioctl(DP_POLL) returned no events without timeout");
                    404:         return NGX_ERROR;
                    405:     }
                    406: 
                    407:     ngx_mutex_lock(ngx_posted_events_mutex);
                    408: 
                    409:     for (i = 0; i < events; i++) {
                    410: 
                    411:         fd = event_list[i].fd;
                    412:         revents = event_list[i].revents;
                    413: 
                    414:         c = ngx_cycle->files[fd];
                    415: 
                    416:         if (c == NULL || c->fd == -1) {
                    417: 
                    418:             pfd.fd = fd;
                    419:             pfd.events = 0;
                    420:             pfd.revents = 0;
                    421: 
                    422:             rc = ioctl(dp, DP_ISPOLLED, &pfd);
                    423: 
                    424:             switch (rc) {
                    425: 
                    426:             case -1:
                    427:                 ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                    428:                     "ioctl(DP_ISPOLLED) failed for socket %d, event",
                    429:                     fd, revents);
                    430:                 break;
                    431: 
                    432:             case 0:
                    433:                 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                    434:                     "phantom event %04Xd for closed and removed socket %d",
                    435:                     revents, fd);
                    436:                 break;
                    437: 
                    438:             default:
                    439:                 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                    440:                     "unexpected event %04Xd for closed and removed socket %d, ",
                    441:                     "ioctl(DP_ISPOLLED) returned rc:%d, fd:%d, event %04Xd",
                    442:                     revents, fd, rc, pfd.fd, pfd.revents);
                    443: 
                    444:                 pfd.fd = fd;
                    445:                 pfd.events = POLLREMOVE;
                    446:                 pfd.revents = 0;
                    447: 
                    448:                 if (write(dp, &pfd, sizeof(struct pollfd))
                    449:                     != (ssize_t) sizeof(struct pollfd))
                    450:                 {
                    451:                     ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                    452:                                   "write(/dev/poll) for %d failed, fd");
                    453:                 }
                    454: 
                    455:                 if (close(fd) == -1) {
                    456:                     ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                    457:                                   "close(%d) failed", fd);
                    458:                 }
                    459: 
                    460:                 break;
                    461:             }
                    462: 
                    463:             continue;
                    464:         }
                    465: 
                    466:         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    467:                        "devpoll: fd:%d, ev:%04Xd, rev:%04Xd",
                    468:                        fd, event_list[i].events, revents);
                    469: 
                    470:         if (revents & (POLLERR|POLLHUP|POLLNVAL)) {
                    471:             ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    472:                           "ioctl(DP_POLL) error fd:%d ev:%04Xd rev:%04Xd",
                    473:                           fd, event_list[i].events, revents);
                    474:         }
                    475: 
                    476:         if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
                    477:             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                    478:                           "strange ioctl(DP_POLL) events "
                    479:                           "fd:%d ev:%04Xd rev:%04Xd",
                    480:                           fd, event_list[i].events, revents);
                    481:         }
                    482: 
                    483:         if ((revents & (POLLERR|POLLHUP|POLLNVAL))
                    484:              && (revents & (POLLIN|POLLOUT)) == 0)
                    485:         {
                    486:             /*
                    487:              * if the error events were returned without POLLIN or POLLOUT,
                    488:              * then add these flags to handle the events at least in one
                    489:              * active handler
                    490:              */
                    491: 
                    492:             revents |= POLLIN|POLLOUT;
                    493:         }
                    494: 
                    495:         rev = c->read;
                    496: 
                    497:         if ((revents & POLLIN) && rev->active) {
                    498: 
                    499:             if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) {
                    500:                 rev->posted_ready = 1;
                    501: 
                    502:             } else {
                    503:                 rev->ready = 1;
                    504:             }
                    505: 
                    506:             if (flags & NGX_POST_EVENTS) {
                    507:                 queue = (ngx_event_t **) (rev->accept ?
                    508:                                &ngx_posted_accept_events : &ngx_posted_events);
                    509: 
                    510:                 ngx_locked_post_event(rev, queue);
                    511: 
                    512:             } else {
                    513:                 instance = rev->instance;
                    514: 
                    515:                 rev->handler(rev);
                    516: 
                    517:                 if (c->fd == -1 || rev->instance != instance) {
                    518:                     continue;
                    519:                 }
                    520:             }
                    521:         }
                    522: 
                    523:         wev = c->write;
                    524: 
                    525:         if ((revents & POLLOUT) && wev->active) {
                    526: 
                    527:             if (flags & NGX_POST_THREAD_EVENTS) {
                    528:                 wev->posted_ready = 1;
                    529: 
                    530:             } else {
                    531:                 wev->ready = 1;
                    532:             }
                    533: 
                    534:             if (flags & NGX_POST_EVENTS) {
                    535:                 ngx_locked_post_event(wev, &ngx_posted_events);
                    536: 
                    537:             } else {
                    538:                 wev->handler(wev);
                    539:             }
                    540:         }
                    541:     }
                    542: 
                    543:     ngx_mutex_unlock(ngx_posted_events_mutex);
                    544: 
                    545:     return NGX_OK;
                    546: }
                    547: 
                    548: 
                    549: static void *
                    550: ngx_devpoll_create_conf(ngx_cycle_t *cycle)
                    551: {
                    552:     ngx_devpoll_conf_t  *dpcf;
                    553: 
                    554:     dpcf = ngx_palloc(cycle->pool, sizeof(ngx_devpoll_conf_t));
                    555:     if (dpcf == NULL) {
                    556:         return NULL;
                    557:     }
                    558: 
                    559:     dpcf->changes = NGX_CONF_UNSET;
                    560:     dpcf->events = NGX_CONF_UNSET;
                    561: 
                    562:     return dpcf;
                    563: }
                    564: 
                    565: 
                    566: static char *
                    567: ngx_devpoll_init_conf(ngx_cycle_t *cycle, void *conf)
                    568: {
                    569:     ngx_devpoll_conf_t *dpcf = conf;
                    570: 
                    571:     ngx_conf_init_uint_value(dpcf->changes, 32);
                    572:     ngx_conf_init_uint_value(dpcf->events, 32);
                    573: 
                    574:     return NGX_CONF_OK;
                    575: }

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