⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ngx_kqueue_module.c

📁 Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) Igor Sysoev */#include <ngx_config.h>#include <ngx_core.h>#include <ngx_event.h>#include <ngx_kqueue_module.h>typedef struct {    ngx_uint_t  changes;    ngx_uint_t  events;} ngx_kqueue_conf_t;static ngx_int_t ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer);static void ngx_kqueue_done(ngx_cycle_t *cycle);static ngx_int_t ngx_kqueue_add_event(ngx_event_t *ev, ngx_int_t event,    ngx_uint_t flags);static ngx_int_t ngx_kqueue_del_event(ngx_event_t *ev, ngx_int_t event,    ngx_uint_t flags);static ngx_int_t ngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter,    ngx_uint_t flags);static ngx_int_t ngx_kqueue_process_changes(ngx_cycle_t *cycle, ngx_uint_t try);static ngx_int_t ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,    ngx_uint_t flags);static ngx_inline void ngx_kqueue_dump_event(ngx_log_t *log,    struct kevent *kev);static void *ngx_kqueue_create_conf(ngx_cycle_t *cycle);static char *ngx_kqueue_init_conf(ngx_cycle_t *cycle, void *conf);int                    ngx_kqueue = -1;/* * The "change_list" should be declared as ngx_thread_volatile. * However, the use of the change_list is localized in kqueue functions and * is protected by the mutex so even the "icc -ipo" should not build the code * with the race condition.  Thus we avoid the declaration to make a more * readable code. */static struct kevent  *change_list, *change_list0, *change_list1;static struct kevent  *event_list;static ngx_uint_t      max_changes, nchanges, nevents;#if (NGX_THREADS)static ngx_mutex_t    *list_mutex;static ngx_mutex_t    *kevent_mutex;#endifstatic ngx_str_t      kqueue_name = ngx_string("kqueue");static ngx_command_t  ngx_kqueue_commands[] = {    { ngx_string("kqueue_changes"),      NGX_EVENT_CONF|NGX_CONF_TAKE1,      ngx_conf_set_num_slot,      0,      offsetof(ngx_kqueue_conf_t, changes),      NULL },    { ngx_string("kqueue_events"),      NGX_EVENT_CONF|NGX_CONF_TAKE1,      ngx_conf_set_num_slot,      0,      offsetof(ngx_kqueue_conf_t, events),      NULL },      ngx_null_command};ngx_event_module_t  ngx_kqueue_module_ctx = {    &kqueue_name,    ngx_kqueue_create_conf,                /* create configuration */    ngx_kqueue_init_conf,                  /* init configuration */    {        ngx_kqueue_add_event,              /* add an event */        ngx_kqueue_del_event,              /* delete an event */        ngx_kqueue_add_event,              /* enable an event */        ngx_kqueue_del_event,              /* disable an event */        NULL,                              /* add an connection */        NULL,                              /* delete an connection */        ngx_kqueue_process_changes,        /* process the changes */        ngx_kqueue_process_events,         /* process the events */        ngx_kqueue_init,                   /* init the events */        ngx_kqueue_done                    /* done the events */    }};ngx_module_t  ngx_kqueue_module = {    NGX_MODULE_V1,    &ngx_kqueue_module_ctx,                /* module context */    ngx_kqueue_commands,                   /* module directives */    NGX_EVENT_MODULE,                      /* module type */    NULL,                                  /* init master */    NULL,                                  /* init module */    NULL,                                  /* init process */    NULL,                                  /* init thread */    NULL,                                  /* exit thread */    NULL,                                  /* exit process */    NULL,                                  /* exit master */    NGX_MODULE_V1_PADDING};static ngx_int_tngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer){    ngx_kqueue_conf_t  *kcf;    struct timespec     ts;#if (NGX_HAVE_TIMER_EVENT)    struct kevent       kev;#endif    kcf = ngx_event_get_conf(cycle->conf_ctx, ngx_kqueue_module);    if (ngx_kqueue == -1) {        ngx_kqueue = kqueue();        if (ngx_kqueue == -1) {            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,                          "kqueue() failed");            return NGX_ERROR;        }#if (NGX_THREADS)        list_mutex = ngx_mutex_init(cycle->log, 0);        if (list_mutex == NULL) {            return NGX_ERROR;        }        kevent_mutex = ngx_mutex_init(cycle->log, 0);        if (kevent_mutex == NULL) {            return NGX_ERROR;        }#endif    }    if (max_changes < kcf->changes) {        if (nchanges) {            ts.tv_sec = 0;            ts.tv_nsec = 0;            if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)                == -1)            {                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,                              "kevent() failed");                return NGX_ERROR;            }            nchanges = 0;        }        if (change_list0) {            ngx_free(change_list0);        }        change_list0 = ngx_alloc(kcf->changes * sizeof(struct kevent),                                 cycle->log);        if (change_list0 == NULL) {            return NGX_ERROR;        }        if (change_list1) {            ngx_free(change_list1);        }        change_list1 = ngx_alloc(kcf->changes * sizeof(struct kevent),                                 cycle->log);        if (change_list1 == NULL) {            return NGX_ERROR;        }        change_list = change_list0;    }    max_changes = kcf->changes;    if (nevents < kcf->events) {        if (event_list) {            ngx_free(event_list);        }        event_list = ngx_alloc(kcf->events * sizeof(struct kevent), cycle->log);        if (event_list == NULL) {            return NGX_ERROR;        }    }    ngx_event_flags = 0;#if (NGX_HAVE_TIMER_EVENT)    if (timer) {        kev.ident = 0;        kev.filter = EVFILT_TIMER;        kev.flags = EV_ADD|EV_ENABLE;        kev.fflags = 0;        kev.data = timer;        kev.udata = 0;        ts.tv_sec = 0;        ts.tv_nsec = 0;        if (kevent(ngx_kqueue, &kev, 1, NULL, 0, &ts) == -1) {            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,                          "kevent(EVFILT_TIMER) failed");            return NGX_ERROR;        }        ngx_event_flags |= NGX_USE_TIMER_EVENT;    }#endif    ngx_event_flags |= NGX_USE_ONESHOT_EVENT|NGX_USE_KQUEUE_EVENT;#if (NGX_HAVE_CLEAR_EVENT)    ngx_event_flags |= NGX_USE_CLEAR_EVENT;#else    ngx_event_flags |= NGX_USE_LEVEL_EVENT;#endif#if (NGX_HAVE_LOWAT_EVENT)    ngx_event_flags |= NGX_USE_LOWAT_EVENT;#endif    nevents = kcf->events;    ngx_io = ngx_os_io;    ngx_event_actions = ngx_kqueue_module_ctx.actions;    return NGX_OK;}static voidngx_kqueue_done(ngx_cycle_t *cycle){    if (close(ngx_kqueue) == -1) {        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,                      "kqueue close() failed");    }    ngx_kqueue = -1;#if (NGX_THREADS)    ngx_mutex_destroy(kevent_mutex);    ngx_mutex_destroy(list_mutex);#endif    ngx_free(change_list1);    ngx_free(change_list0);    ngx_free(event_list);    change_list1 = NULL;    change_list0 = NULL;    change_list = NULL;    event_list = NULL;    max_changes = 0;    nchanges = 0;    nevents = 0;}static ngx_int_tngx_kqueue_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags){    ngx_int_t          rc;#if 0    ngx_event_t       *e;    ngx_connection_t  *c;#endif    ev->active = 1;    ev->disabled = 0;    ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1 : 0;    ngx_mutex_lock(list_mutex);#if 0    if (ev->index < nchanges        && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1)            == (uintptr_t) ev)    {        if (change_list[ev->index].flags == EV_DISABLE) {            /*             * if the EV_DISABLE is still not passed to a kernel             * we will not pass it             */            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,                           "kevent activated: %d: ft:%i",                           ngx_event_ident(ev->data), event);            if (ev->index < --nchanges) {                e = (ngx_event_t *)                    ((uintptr_t) change_list[nchanges].udata & (uintptr_t) ~1);                change_list[ev->index] = change_list[nchanges];                e->index = ev->index;            }            ngx_mutex_unlock(list_mutex);            return NGX_OK;        }        c = ev->data;        ngx_log_error(NGX_LOG_ALERT, ev->log, 0,                      "previous event on #%d were not passed in kernel", c->fd);        ngx_mutex_unlock(list_mutex);        return NGX_ERROR;    }#endif    rc = ngx_kqueue_set_event(ev, event, EV_ADD|EV_ENABLE|flags);    ngx_mutex_unlock(list_mutex);    return rc;}static ngx_int_tngx_kqueue_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags){    ngx_int_t     rc;    ngx_event_t  *e;    ev->active = 0;    ev->disabled = 0;    ngx_mutex_lock(list_mutex);    if (ev->index < nchanges        && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1)            == (uintptr_t) ev)    {        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,                       "kevent deleted: %d: ft:%i",                       ngx_event_ident(ev->data), event);        /* if the event is still not passed to a kernel we will not pass it */        nchanges--;        if (ev->index < nchanges) {            e = (ngx_event_t *)                    ((uintptr_t) change_list[nchanges].udata & (uintptr_t) ~1);            change_list[ev->index] = change_list[nchanges];            e->index = ev->index;        }        ngx_mutex_unlock(list_mutex);        return NGX_OK;    }    /*     * when the file descriptor is closed the kqueue automatically deletes     * its filters so we do not need to delete explicity the event     * before the closing the file descriptor.     */    if (flags & NGX_CLOSE_EVENT) {        ngx_mutex_unlock(list_mutex);        return NGX_OK;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -