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>