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>