Annotation of embedaddon/nginx/src/event/modules/ngx_kqueue_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: typedef struct {
! 14: ngx_uint_t changes;
! 15: ngx_uint_t events;
! 16: } ngx_kqueue_conf_t;
! 17:
! 18:
! 19: static ngx_int_t ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer);
! 20: static void ngx_kqueue_done(ngx_cycle_t *cycle);
! 21: static ngx_int_t ngx_kqueue_add_event(ngx_event_t *ev, ngx_int_t event,
! 22: ngx_uint_t flags);
! 23: static ngx_int_t ngx_kqueue_del_event(ngx_event_t *ev, ngx_int_t event,
! 24: ngx_uint_t flags);
! 25: static ngx_int_t ngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter,
! 26: ngx_uint_t flags);
! 27: static ngx_int_t ngx_kqueue_process_changes(ngx_cycle_t *cycle, ngx_uint_t try);
! 28: static ngx_int_t ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
! 29: ngx_uint_t flags);
! 30: static ngx_inline void ngx_kqueue_dump_event(ngx_log_t *log,
! 31: struct kevent *kev);
! 32:
! 33: static void *ngx_kqueue_create_conf(ngx_cycle_t *cycle);
! 34: static char *ngx_kqueue_init_conf(ngx_cycle_t *cycle, void *conf);
! 35:
! 36:
! 37: int ngx_kqueue = -1;
! 38:
! 39: /*
! 40: * The "change_list" should be declared as ngx_thread_volatile.
! 41: * However, the use of the change_list is localized in kqueue functions and
! 42: * is protected by the mutex so even the "icc -ipo" should not build the code
! 43: * with the race condition. Thus we avoid the declaration to make a more
! 44: * readable code.
! 45: */
! 46:
! 47: static struct kevent *change_list, *change_list0, *change_list1;
! 48: static struct kevent *event_list;
! 49: static ngx_uint_t max_changes, nchanges, nevents;
! 50:
! 51: #if (NGX_THREADS)
! 52: static ngx_mutex_t *list_mutex;
! 53: static ngx_mutex_t *kevent_mutex;
! 54: #endif
! 55:
! 56:
! 57:
! 58: static ngx_str_t kqueue_name = ngx_string("kqueue");
! 59:
! 60: static ngx_command_t ngx_kqueue_commands[] = {
! 61:
! 62: { ngx_string("kqueue_changes"),
! 63: NGX_EVENT_CONF|NGX_CONF_TAKE1,
! 64: ngx_conf_set_num_slot,
! 65: 0,
! 66: offsetof(ngx_kqueue_conf_t, changes),
! 67: NULL },
! 68:
! 69: { ngx_string("kqueue_events"),
! 70: NGX_EVENT_CONF|NGX_CONF_TAKE1,
! 71: ngx_conf_set_num_slot,
! 72: 0,
! 73: offsetof(ngx_kqueue_conf_t, events),
! 74: NULL },
! 75:
! 76: ngx_null_command
! 77: };
! 78:
! 79:
! 80: ngx_event_module_t ngx_kqueue_module_ctx = {
! 81: &kqueue_name,
! 82: ngx_kqueue_create_conf, /* create configuration */
! 83: ngx_kqueue_init_conf, /* init configuration */
! 84:
! 85: {
! 86: ngx_kqueue_add_event, /* add an event */
! 87: ngx_kqueue_del_event, /* delete an event */
! 88: ngx_kqueue_add_event, /* enable an event */
! 89: ngx_kqueue_del_event, /* disable an event */
! 90: NULL, /* add an connection */
! 91: NULL, /* delete an connection */
! 92: ngx_kqueue_process_changes, /* process the changes */
! 93: ngx_kqueue_process_events, /* process the events */
! 94: ngx_kqueue_init, /* init the events */
! 95: ngx_kqueue_done /* done the events */
! 96: }
! 97:
! 98: };
! 99:
! 100: ngx_module_t ngx_kqueue_module = {
! 101: NGX_MODULE_V1,
! 102: &ngx_kqueue_module_ctx, /* module context */
! 103: ngx_kqueue_commands, /* module directives */
! 104: NGX_EVENT_MODULE, /* module type */
! 105: NULL, /* init master */
! 106: NULL, /* init module */
! 107: NULL, /* init process */
! 108: NULL, /* init thread */
! 109: NULL, /* exit thread */
! 110: NULL, /* exit process */
! 111: NULL, /* exit master */
! 112: NGX_MODULE_V1_PADDING
! 113: };
! 114:
! 115:
! 116: static ngx_int_t
! 117: ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer)
! 118: {
! 119: ngx_kqueue_conf_t *kcf;
! 120: struct timespec ts;
! 121: #if (NGX_HAVE_TIMER_EVENT)
! 122: struct kevent kev;
! 123: #endif
! 124:
! 125: kcf = ngx_event_get_conf(cycle->conf_ctx, ngx_kqueue_module);
! 126:
! 127: if (ngx_kqueue == -1) {
! 128: ngx_kqueue = kqueue();
! 129:
! 130: if (ngx_kqueue == -1) {
! 131: ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
! 132: "kqueue() failed");
! 133: return NGX_ERROR;
! 134: }
! 135:
! 136: #if (NGX_THREADS)
! 137:
! 138: list_mutex = ngx_mutex_init(cycle->log, 0);
! 139: if (list_mutex == NULL) {
! 140: return NGX_ERROR;
! 141: }
! 142:
! 143: kevent_mutex = ngx_mutex_init(cycle->log, 0);
! 144: if (kevent_mutex == NULL) {
! 145: return NGX_ERROR;
! 146: }
! 147:
! 148: #endif
! 149: }
! 150:
! 151: if (max_changes < kcf->changes) {
! 152: if (nchanges) {
! 153: ts.tv_sec = 0;
! 154: ts.tv_nsec = 0;
! 155:
! 156: if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)
! 157: == -1)
! 158: {
! 159: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
! 160: "kevent() failed");
! 161: return NGX_ERROR;
! 162: }
! 163: nchanges = 0;
! 164: }
! 165:
! 166: if (change_list0) {
! 167: ngx_free(change_list0);
! 168: }
! 169:
! 170: change_list0 = ngx_alloc(kcf->changes * sizeof(struct kevent),
! 171: cycle->log);
! 172: if (change_list0 == NULL) {
! 173: return NGX_ERROR;
! 174: }
! 175:
! 176: if (change_list1) {
! 177: ngx_free(change_list1);
! 178: }
! 179:
! 180: change_list1 = ngx_alloc(kcf->changes * sizeof(struct kevent),
! 181: cycle->log);
! 182: if (change_list1 == NULL) {
! 183: return NGX_ERROR;
! 184: }
! 185:
! 186: change_list = change_list0;
! 187: }
! 188:
! 189: max_changes = kcf->changes;
! 190:
! 191: if (nevents < kcf->events) {
! 192: if (event_list) {
! 193: ngx_free(event_list);
! 194: }
! 195:
! 196: event_list = ngx_alloc(kcf->events * sizeof(struct kevent), cycle->log);
! 197: if (event_list == NULL) {
! 198: return NGX_ERROR;
! 199: }
! 200: }
! 201:
! 202: ngx_event_flags = NGX_USE_ONESHOT_EVENT
! 203: |NGX_USE_KQUEUE_EVENT
! 204: |NGX_USE_VNODE_EVENT;
! 205:
! 206: #if (NGX_HAVE_TIMER_EVENT)
! 207:
! 208: if (timer) {
! 209: kev.ident = 0;
! 210: kev.filter = EVFILT_TIMER;
! 211: kev.flags = EV_ADD|EV_ENABLE;
! 212: kev.fflags = 0;
! 213: kev.data = timer;
! 214: kev.udata = 0;
! 215:
! 216: ts.tv_sec = 0;
! 217: ts.tv_nsec = 0;
! 218:
! 219: if (kevent(ngx_kqueue, &kev, 1, NULL, 0, &ts) == -1) {
! 220: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
! 221: "kevent(EVFILT_TIMER) failed");
! 222: return NGX_ERROR;
! 223: }
! 224:
! 225: ngx_event_flags |= NGX_USE_TIMER_EVENT;
! 226: }
! 227:
! 228: #endif
! 229:
! 230: #if (NGX_HAVE_CLEAR_EVENT)
! 231: ngx_event_flags |= NGX_USE_CLEAR_EVENT;
! 232: #else
! 233: ngx_event_flags |= NGX_USE_LEVEL_EVENT;
! 234: #endif
! 235:
! 236: #if (NGX_HAVE_LOWAT_EVENT)
! 237: ngx_event_flags |= NGX_USE_LOWAT_EVENT;
! 238: #endif
! 239:
! 240: nevents = kcf->events;
! 241:
! 242: ngx_io = ngx_os_io;
! 243:
! 244: ngx_event_actions = ngx_kqueue_module_ctx.actions;
! 245:
! 246: return NGX_OK;
! 247: }
! 248:
! 249:
! 250: static void
! 251: ngx_kqueue_done(ngx_cycle_t *cycle)
! 252: {
! 253: if (close(ngx_kqueue) == -1) {
! 254: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
! 255: "kqueue close() failed");
! 256: }
! 257:
! 258: ngx_kqueue = -1;
! 259:
! 260: #if (NGX_THREADS)
! 261: ngx_mutex_destroy(kevent_mutex);
! 262: ngx_mutex_destroy(list_mutex);
! 263: #endif
! 264:
! 265: ngx_free(change_list1);
! 266: ngx_free(change_list0);
! 267: ngx_free(event_list);
! 268:
! 269: change_list1 = NULL;
! 270: change_list0 = NULL;
! 271: change_list = NULL;
! 272: event_list = NULL;
! 273: max_changes = 0;
! 274: nchanges = 0;
! 275: nevents = 0;
! 276: }
! 277:
! 278:
! 279: static ngx_int_t
! 280: ngx_kqueue_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
! 281: {
! 282: ngx_int_t rc;
! 283: #if 0
! 284: ngx_event_t *e;
! 285: ngx_connection_t *c;
! 286: #endif
! 287:
! 288: ev->active = 1;
! 289: ev->disabled = 0;
! 290: ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1 : 0;
! 291:
! 292: ngx_mutex_lock(list_mutex);
! 293:
! 294: #if 0
! 295:
! 296: if (ev->index < nchanges
! 297: && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1)
! 298: == (uintptr_t) ev)
! 299: {
! 300: if (change_list[ev->index].flags == EV_DISABLE) {
! 301:
! 302: /*
! 303: * if the EV_DISABLE is still not passed to a kernel
! 304: * we will not pass it
! 305: */
! 306:
! 307: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
! 308: "kevent activated: %d: ft:%i",
! 309: ngx_event_ident(ev->data), event);
! 310:
! 311: if (ev->index < --nchanges) {
! 312: e = (ngx_event_t *)
! 313: ((uintptr_t) change_list[nchanges].udata & (uintptr_t) ~1);
! 314: change_list[ev->index] = change_list[nchanges];
! 315: e->index = ev->index;
! 316: }
! 317:
! 318: ngx_mutex_unlock(list_mutex);
! 319:
! 320: return NGX_OK;
! 321: }
! 322:
! 323: c = ev->data;
! 324:
! 325: ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
! 326: "previous event on #%d were not passed in kernel", c->fd);
! 327:
! 328: ngx_mutex_unlock(list_mutex);
! 329:
! 330: return NGX_ERROR;
! 331: }
! 332:
! 333: #endif
! 334:
! 335: rc = ngx_kqueue_set_event(ev, event, EV_ADD|EV_ENABLE|flags);
! 336:
! 337: ngx_mutex_unlock(list_mutex);
! 338:
! 339: return rc;
! 340: }
! 341:
! 342:
! 343: static ngx_int_t
! 344: ngx_kqueue_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
! 345: {
! 346: ngx_int_t rc;
! 347: ngx_event_t *e;
! 348:
! 349: ev->active = 0;
! 350: ev->disabled = 0;
! 351:
! 352: ngx_mutex_lock(list_mutex);
! 353:
! 354: if (ev->index < nchanges
! 355: && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1)
! 356: == (uintptr_t) ev)
! 357: {
! 358: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
! 359: "kevent deleted: %d: ft:%i",
! 360: ngx_event_ident(ev->data), event);
! 361:
! 362: /* if the event is still not passed to a kernel we will not pass it */
! 363:
! 364: nchanges--;
! 365:
! 366: if (ev->index < nchanges) {
! 367: e = (ngx_event_t *)
! 368: ((uintptr_t) change_list[nchanges].udata & (uintptr_t) ~1);
! 369: change_list[ev->index] = change_list[nchanges];
! 370: e->index = ev->index;
! 371: }
! 372:
! 373: ngx_mutex_unlock(list_mutex);
! 374:
! 375: return NGX_OK;
! 376: }
! 377:
! 378: /*
! 379: * when the file descriptor is closed the kqueue automatically deletes
! 380: * its filters so we do not need to delete explicitly the event
! 381: * before the closing the file descriptor.
! 382: */
! 383:
! 384: if (flags & NGX_CLOSE_EVENT) {
! 385: ngx_mutex_unlock(list_mutex);
! 386: return NGX_OK;
! 387: }
! 388:
! 389: if (flags & NGX_DISABLE_EVENT) {
! 390: ev->disabled = 1;
! 391:
! 392: } else {
! 393: flags |= EV_DELETE;
! 394: }
! 395:
! 396: rc = ngx_kqueue_set_event(ev, event, flags);
! 397:
! 398: ngx_mutex_unlock(list_mutex);
! 399:
! 400: return rc;
! 401: }
! 402:
! 403:
! 404: static ngx_int_t
! 405: ngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter, ngx_uint_t flags)
! 406: {
! 407: struct kevent *kev;
! 408: struct timespec ts;
! 409: ngx_connection_t *c;
! 410:
! 411: c = ev->data;
! 412:
! 413: ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
! 414: "kevent set event: %d: ft:%i fl:%04Xi",
! 415: c->fd, filter, flags);
! 416:
! 417: if (nchanges >= max_changes) {
! 418: ngx_log_error(NGX_LOG_WARN, ev->log, 0,
! 419: "kqueue change list is filled up");
! 420:
! 421: ts.tv_sec = 0;
! 422: ts.tv_nsec = 0;
! 423:
! 424: if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)
! 425: == -1)
! 426: {
! 427: ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent() failed");
! 428: return NGX_ERROR;
! 429: }
! 430:
! 431: nchanges = 0;
! 432: }
! 433:
! 434: kev = &change_list[nchanges];
! 435:
! 436: kev->ident = c->fd;
! 437: kev->filter = (short) filter;
! 438: kev->flags = (u_short) flags;
! 439: kev->udata = NGX_KQUEUE_UDATA_T ((uintptr_t) ev | ev->instance);
! 440:
! 441: if (filter == EVFILT_VNODE) {
! 442: kev->fflags = NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND
! 443: |NOTE_ATTRIB|NOTE_RENAME
! 444: #if (__FreeBSD__ == 4 && __FreeBSD_version >= 430000) \
! 445: || __FreeBSD_version >= 500018
! 446: |NOTE_REVOKE
! 447: #endif
! 448: ;
! 449: kev->data = 0;
! 450:
! 451: } else {
! 452: #if (NGX_HAVE_LOWAT_EVENT)
! 453: if (flags & NGX_LOWAT_EVENT) {
! 454: kev->fflags = NOTE_LOWAT;
! 455: kev->data = ev->available;
! 456:
! 457: } else {
! 458: kev->fflags = 0;
! 459: kev->data = 0;
! 460: }
! 461: #else
! 462: kev->fflags = 0;
! 463: kev->data = 0;
! 464: #endif
! 465: }
! 466:
! 467: ev->index = nchanges;
! 468: nchanges++;
! 469:
! 470: if (flags & NGX_FLUSH_EVENT) {
! 471: ts.tv_sec = 0;
! 472: ts.tv_nsec = 0;
! 473:
! 474: ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, 0, "kevent flush");
! 475:
! 476: if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)
! 477: == -1)
! 478: {
! 479: ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent() failed");
! 480: return NGX_ERROR;
! 481: }
! 482:
! 483: nchanges = 0;
! 484: }
! 485:
! 486: return NGX_OK;
! 487: }
! 488:
! 489:
! 490: static ngx_int_t
! 491: ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
! 492: ngx_uint_t flags)
! 493: {
! 494: int events, n;
! 495: ngx_int_t i, instance;
! 496: ngx_uint_t level;
! 497: ngx_err_t err;
! 498: ngx_event_t *ev, **queue;
! 499: struct timespec ts, *tp;
! 500:
! 501: if (ngx_threaded) {
! 502: if (ngx_kqueue_process_changes(cycle, 0) == NGX_ERROR) {
! 503: return NGX_ERROR;
! 504: }
! 505:
! 506: n = 0;
! 507:
! 508: } else {
! 509: n = (int) nchanges;
! 510: nchanges = 0;
! 511: }
! 512:
! 513: if (timer == NGX_TIMER_INFINITE) {
! 514: tp = NULL;
! 515:
! 516: } else {
! 517:
! 518: ts.tv_sec = timer / 1000;
! 519: ts.tv_nsec = (timer % 1000) * 1000000;
! 520:
! 521: /*
! 522: * 64-bit Darwin kernel has the bug: kernel level ts.tv_nsec is
! 523: * the int32_t while user level ts.tv_nsec is the long (64-bit),
! 524: * so on the big endian PowerPC all nanoseconds are lost.
! 525: */
! 526:
! 527: #if (NGX_DARWIN_KEVENT_BUG)
! 528: ts.tv_nsec <<= 32;
! 529: #endif
! 530:
! 531: tp = &ts;
! 532: }
! 533:
! 534: ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
! 535: "kevent timer: %M, changes: %d", timer, n);
! 536:
! 537: events = kevent(ngx_kqueue, change_list, n, event_list, (int) nevents, tp);
! 538:
! 539: err = (events == -1) ? ngx_errno : 0;
! 540:
! 541: if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) {
! 542: ngx_time_update();
! 543: }
! 544:
! 545: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
! 546: "kevent events: %d", events);
! 547:
! 548: if (err) {
! 549: if (err == NGX_EINTR) {
! 550:
! 551: if (ngx_event_timer_alarm) {
! 552: ngx_event_timer_alarm = 0;
! 553: return NGX_OK;
! 554: }
! 555:
! 556: level = NGX_LOG_INFO;
! 557:
! 558: } else {
! 559: level = NGX_LOG_ALERT;
! 560: }
! 561:
! 562: ngx_log_error(level, cycle->log, err, "kevent() failed");
! 563: return NGX_ERROR;
! 564: }
! 565:
! 566: if (events == 0) {
! 567: if (timer != NGX_TIMER_INFINITE) {
! 568: return NGX_OK;
! 569: }
! 570:
! 571: ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
! 572: "kevent() returned no events without timeout");
! 573: return NGX_ERROR;
! 574: }
! 575:
! 576: ngx_mutex_lock(ngx_posted_events_mutex);
! 577:
! 578: for (i = 0; i < events; i++) {
! 579:
! 580: ngx_kqueue_dump_event(cycle->log, &event_list[i]);
! 581:
! 582: if (event_list[i].flags & EV_ERROR) {
! 583: ngx_log_error(NGX_LOG_ALERT, cycle->log, event_list[i].data,
! 584: "kevent() error on %d filter:%d flags:%04Xd",
! 585: event_list[i].ident, event_list[i].filter,
! 586: event_list[i].flags);
! 587: continue;
! 588: }
! 589:
! 590: #if (NGX_HAVE_TIMER_EVENT)
! 591:
! 592: if (event_list[i].filter == EVFILT_TIMER) {
! 593: ngx_time_update();
! 594: continue;
! 595: }
! 596:
! 597: #endif
! 598:
! 599: ev = (ngx_event_t *) event_list[i].udata;
! 600:
! 601: switch (event_list[i].filter) {
! 602:
! 603: case EVFILT_READ:
! 604: case EVFILT_WRITE:
! 605:
! 606: instance = (uintptr_t) ev & 1;
! 607: ev = (ngx_event_t *) ((uintptr_t) ev & (uintptr_t) ~1);
! 608:
! 609: if (ev->closed || ev->instance != instance) {
! 610:
! 611: /*
! 612: * the stale event from a file descriptor
! 613: * that was just closed in this iteration
! 614: */
! 615:
! 616: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
! 617: "kevent: stale event %p", ev);
! 618: continue;
! 619: }
! 620:
! 621: if (ev->log && (ev->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
! 622: ngx_kqueue_dump_event(ev->log, &event_list[i]);
! 623: }
! 624:
! 625: if (ev->oneshot) {
! 626: ev->active = 0;
! 627: }
! 628:
! 629: #if (NGX_THREADS)
! 630:
! 631: if ((flags & NGX_POST_THREAD_EVENTS) && !ev->accept) {
! 632: ev->posted_ready = 1;
! 633: ev->posted_available = event_list[i].data;
! 634:
! 635: if (event_list[i].flags & EV_EOF) {
! 636: ev->posted_eof = 1;
! 637: ev->posted_errno = event_list[i].fflags;
! 638: }
! 639:
! 640: ngx_locked_post_event(ev, &ngx_posted_events);
! 641:
! 642: continue;
! 643: }
! 644:
! 645: #endif
! 646:
! 647: ev->available = event_list[i].data;
! 648:
! 649: if (event_list[i].flags & EV_EOF) {
! 650: ev->pending_eof = 1;
! 651: ev->kq_errno = event_list[i].fflags;
! 652: }
! 653:
! 654: ev->ready = 1;
! 655:
! 656: break;
! 657:
! 658: case EVFILT_VNODE:
! 659: ev->kq_vnode = 1;
! 660:
! 661: break;
! 662:
! 663: case EVFILT_AIO:
! 664: ev->complete = 1;
! 665: ev->ready = 1;
! 666:
! 667: break;
! 668:
! 669: default:
! 670: ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
! 671: "unexpected kevent() filter %d",
! 672: event_list[i].filter);
! 673: continue;
! 674: }
! 675:
! 676: if (flags & NGX_POST_EVENTS) {
! 677: queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events:
! 678: &ngx_posted_events);
! 679: ngx_locked_post_event(ev, queue);
! 680:
! 681: continue;
! 682: }
! 683:
! 684: ev->handler(ev);
! 685: }
! 686:
! 687: ngx_mutex_unlock(ngx_posted_events_mutex);
! 688:
! 689: return NGX_OK;
! 690: }
! 691:
! 692:
! 693: static ngx_int_t
! 694: ngx_kqueue_process_changes(ngx_cycle_t *cycle, ngx_uint_t try)
! 695: {
! 696: int n;
! 697: ngx_int_t rc;
! 698: ngx_err_t err;
! 699: struct timespec ts;
! 700: struct kevent *changes;
! 701:
! 702: ngx_mutex_lock(kevent_mutex);
! 703:
! 704: ngx_mutex_lock(list_mutex);
! 705:
! 706: if (nchanges == 0) {
! 707: ngx_mutex_unlock(list_mutex);
! 708: ngx_mutex_unlock(kevent_mutex);
! 709: return NGX_OK;
! 710: }
! 711:
! 712: changes = change_list;
! 713: if (change_list == change_list0) {
! 714: change_list = change_list1;
! 715: } else {
! 716: change_list = change_list0;
! 717: }
! 718:
! 719: n = (int) nchanges;
! 720: nchanges = 0;
! 721:
! 722: ngx_mutex_unlock(list_mutex);
! 723:
! 724: ts.tv_sec = 0;
! 725: ts.tv_nsec = 0;
! 726:
! 727: ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
! 728: "kevent changes: %d", n);
! 729:
! 730: if (kevent(ngx_kqueue, changes, n, NULL, 0, &ts) == -1) {
! 731: err = ngx_errno;
! 732: ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT,
! 733: cycle->log, err, "kevent() failed");
! 734: rc = NGX_ERROR;
! 735:
! 736: } else {
! 737: rc = NGX_OK;
! 738: }
! 739:
! 740: ngx_mutex_unlock(kevent_mutex);
! 741:
! 742: return rc;
! 743: }
! 744:
! 745:
! 746: static ngx_inline void
! 747: ngx_kqueue_dump_event(ngx_log_t *log, struct kevent *kev)
! 748: {
! 749: ngx_log_debug6(NGX_LOG_DEBUG_EVENT, log, 0,
! 750: (kev->ident > 0x8000000 && kev->ident != (unsigned) -1) ?
! 751: "kevent: %p: ft:%d fl:%04Xd ff:%08Xd d:%d ud:%p":
! 752: "kevent: %d: ft:%d fl:%04Xd ff:%08Xd d:%d ud:%p",
! 753: kev->ident, kev->filter,
! 754: kev->flags, kev->fflags,
! 755: kev->data, kev->udata);
! 756: }
! 757:
! 758:
! 759: static void *
! 760: ngx_kqueue_create_conf(ngx_cycle_t *cycle)
! 761: {
! 762: ngx_kqueue_conf_t *kcf;
! 763:
! 764: kcf = ngx_palloc(cycle->pool, sizeof(ngx_kqueue_conf_t));
! 765: if (kcf == NULL) {
! 766: return NULL;
! 767: }
! 768:
! 769: kcf->changes = NGX_CONF_UNSET;
! 770: kcf->events = NGX_CONF_UNSET;
! 771:
! 772: return kcf;
! 773: }
! 774:
! 775:
! 776: static char *
! 777: ngx_kqueue_init_conf(ngx_cycle_t *cycle, void *conf)
! 778: {
! 779: ngx_kqueue_conf_t *kcf = conf;
! 780:
! 781: ngx_conf_init_uint_value(kcf->changes, 512);
! 782: ngx_conf_init_uint_value(kcf->events, 512);
! 783:
! 784: return NGX_CONF_OK;
! 785: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>