Events: implemented kqueue notification mechanism.

This commit is contained in:
Valentin Bartenev 2015-03-14 17:37:16 +03:00
parent e10e7a4831
commit 2b3c01e995

View File

@ -17,6 +17,9 @@ typedef struct {
static ngx_int_t ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer); static ngx_int_t ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer);
#ifdef EVFILT_USER
static ngx_int_t ngx_kqueue_notify_init(ngx_log_t *log);
#endif
static void ngx_kqueue_done(ngx_cycle_t *cycle); 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, static ngx_int_t ngx_kqueue_add_event(ngx_event_t *ev, ngx_int_t event,
ngx_uint_t flags); ngx_uint_t flags);
@ -24,6 +27,9 @@ static ngx_int_t ngx_kqueue_del_event(ngx_event_t *ev, ngx_int_t event,
ngx_uint_t flags); ngx_uint_t flags);
static ngx_int_t ngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter, static ngx_int_t ngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter,
ngx_uint_t flags); ngx_uint_t flags);
#ifdef EVFILT_USER
static ngx_int_t ngx_kqueue_notify(ngx_event_handler_pt handler);
#endif
static ngx_int_t ngx_kqueue_process_changes(ngx_cycle_t *cycle, ngx_uint_t try); 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, static ngx_int_t ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
ngx_uint_t flags); ngx_uint_t flags);
@ -48,6 +54,11 @@ static struct kevent *change_list, *change_list0, *change_list1;
static struct kevent *event_list; static struct kevent *event_list;
static ngx_uint_t max_changes, nchanges, nevents; static ngx_uint_t max_changes, nchanges, nevents;
#ifdef EVFILT_USER
static ngx_event_t notify_event;
static struct kevent notify_kev;
#endif
#if (NGX_OLD_THREADS) #if (NGX_OLD_THREADS)
static ngx_mutex_t *list_mutex; static ngx_mutex_t *list_mutex;
static ngx_mutex_t *kevent_mutex; static ngx_mutex_t *kevent_mutex;
@ -89,7 +100,11 @@ ngx_event_module_t ngx_kqueue_module_ctx = {
ngx_kqueue_del_event, /* disable an event */ ngx_kqueue_del_event, /* disable an event */
NULL, /* add an connection */ NULL, /* add an connection */
NULL, /* delete an connection */ NULL, /* delete an connection */
#ifdef EVFILT_USER
ngx_kqueue_notify, /* trigger a notify */
#else
NULL, /* trigger a notify */ NULL, /* trigger a notify */
#endif
ngx_kqueue_process_changes, /* process the changes */ ngx_kqueue_process_changes, /* process the changes */
ngx_kqueue_process_events, /* process the events */ ngx_kqueue_process_events, /* process the events */
ngx_kqueue_init, /* init the events */ ngx_kqueue_init, /* init the events */
@ -134,6 +149,12 @@ ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer)
return NGX_ERROR; return NGX_ERROR;
} }
#ifdef EVFILT_USER
if (ngx_kqueue_notify_init(cycle->log) != NGX_OK) {
return NGX_ERROR;
}
#endif
#if (NGX_OLD_THREADS) #if (NGX_OLD_THREADS)
list_mutex = ngx_mutex_init(cycle->log, 0); list_mutex = ngx_mutex_init(cycle->log, 0);
@ -248,6 +269,37 @@ ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer)
} }
#ifdef EVFILT_USER
static ngx_int_t
ngx_kqueue_notify_init(ngx_log_t *log)
{
notify_kev.ident = 0;
notify_kev.filter = EVFILT_USER;
notify_kev.data = 0;
notify_kev.flags = EV_ADD|EV_CLEAR;
notify_kev.fflags = 0;
notify_kev.udata = 0;
if (kevent(ngx_kqueue, &notify_kev, 1, NULL, 0, NULL) == -1) {
ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
"kevent(EVFILT_USER, EV_ADD) failed");
return NGX_ERROR;
}
notify_event.active = 1;
notify_event.log = log;
notify_kev.flags = 0;
notify_kev.fflags = NOTE_TRIGGER;
notify_kev.udata = NGX_KQUEUE_UDATA_T ((uintptr_t) &notify_event);
return NGX_OK;
}
#endif
static void static void
ngx_kqueue_done(ngx_cycle_t *cycle) ngx_kqueue_done(ngx_cycle_t *cycle)
{ {
@ -488,6 +540,25 @@ ngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter, ngx_uint_t flags)
} }
#ifdef EVFILT_USER
static ngx_int_t
ngx_kqueue_notify(ngx_event_handler_pt handler)
{
notify_event.handler = handler;
if (kevent(ngx_kqueue, &notify_kev, 1, NULL, 0, NULL) == -1) {
ngx_log_error(NGX_LOG_ALERT, notify_event.log, ngx_errno,
"kevent(EVFILT_USER, NOTE_TRIGGER) failed");
return NGX_ERROR;
}
return NGX_OK;
}
#endif
static ngx_int_t static ngx_int_t
ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
ngx_uint_t flags) ngx_uint_t flags)
@ -648,6 +719,11 @@ ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
break; break;
#ifdef EVFILT_USER
case EVFILT_USER:
break;
#endif
default: default:
ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
"unexpected kevent() filter %d", "unexpected kevent() filter %d",