1e18a033bSKonstantin Ananyev
2e18a033bSKonstantin Ananyev/*
3e18a033bSKonstantin Ananyev * Copyright (C) Igor Sysoev
4e18a033bSKonstantin Ananyev * Copyright (C) Nginx, Inc.
5e18a033bSKonstantin Ananyev */
6e18a033bSKonstantin Ananyev
7e18a033bSKonstantin Ananyev
8e18a033bSKonstantin Ananyev#include <ngx_config.h>
9e18a033bSKonstantin Ananyev#include <ngx_core.h>
10e18a033bSKonstantin Ananyev#include <ngx_event.h>
11e18a033bSKonstantin Ananyev
12e18a033bSKonstantin Ananyev
13e18a033bSKonstantin Ananyevtypedef struct {
14e18a033bSKonstantin Ananyev    ngx_uint_t  changes;
15e18a033bSKonstantin Ananyev    ngx_uint_t  events;
16e18a033bSKonstantin Ananyev} ngx_kqueue_conf_t;
17e18a033bSKonstantin Ananyev
18e18a033bSKonstantin Ananyev
19e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer);
20e18a033bSKonstantin Ananyev#ifdef EVFILT_USER
21e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_kqueue_notify_init(ngx_log_t *log);
22e18a033bSKonstantin Ananyev#endif
23e18a033bSKonstantin Ananyevstatic void ngx_kqueue_done(ngx_cycle_t *cycle);
24e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_kqueue_add_event(ngx_event_t *ev, ngx_int_t event,
25e18a033bSKonstantin Ananyev    ngx_uint_t flags);
26e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_kqueue_del_event(ngx_event_t *ev, ngx_int_t event,
27e18a033bSKonstantin Ananyev    ngx_uint_t flags);
28e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter,
29e18a033bSKonstantin Ananyev    ngx_uint_t flags);
30e18a033bSKonstantin Ananyev#ifdef EVFILT_USER
31e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_kqueue_notify(ngx_event_handler_pt handler);
32e18a033bSKonstantin Ananyev#endif
33e18a033bSKonstantin Ananyevstatic ngx_int_t ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
34e18a033bSKonstantin Ananyev    ngx_uint_t flags);
35e18a033bSKonstantin Ananyevstatic ngx_inline void ngx_kqueue_dump_event(ngx_log_t *log,
36e18a033bSKonstantin Ananyev    struct kevent *kev);
37e18a033bSKonstantin Ananyev
38e18a033bSKonstantin Ananyevstatic void *ngx_kqueue_create_conf(ngx_cycle_t *cycle);
39e18a033bSKonstantin Ananyevstatic char *ngx_kqueue_init_conf(ngx_cycle_t *cycle, void *conf);
40e18a033bSKonstantin Ananyev
41e18a033bSKonstantin Ananyev
42e18a033bSKonstantin Ananyevint                    ngx_kqueue = -1;
43e18a033bSKonstantin Ananyev
44e18a033bSKonstantin Ananyevstatic struct kevent  *change_list;
45e18a033bSKonstantin Ananyevstatic struct kevent  *event_list;
46e18a033bSKonstantin Ananyevstatic ngx_uint_t      max_changes, nchanges, nevents;
47e18a033bSKonstantin Ananyev
48e18a033bSKonstantin Ananyev#ifdef EVFILT_USER
49e18a033bSKonstantin Ananyevstatic ngx_event_t     notify_event;
50e18a033bSKonstantin Ananyevstatic struct kevent   notify_kev;
51e18a033bSKonstantin Ananyev#endif
52e18a033bSKonstantin Ananyev
53e18a033bSKonstantin Ananyev
54e18a033bSKonstantin Ananyevstatic ngx_str_t      kqueue_name = ngx_string("kqueue");
55e18a033bSKonstantin Ananyev
56e18a033bSKonstantin Ananyevstatic ngx_command_t  ngx_kqueue_commands[] = {
57e18a033bSKonstantin Ananyev
58e18a033bSKonstantin Ananyev    { ngx_string("kqueue_changes"),
59e18a033bSKonstantin Ananyev      NGX_EVENT_CONF|NGX_CONF_TAKE1,
60e18a033bSKonstantin Ananyev      ngx_conf_set_num_slot,
61e18a033bSKonstantin Ananyev      0,
62e18a033bSKonstantin Ananyev      offsetof(ngx_kqueue_conf_t, changes),
63e18a033bSKonstantin Ananyev      NULL },
64e18a033bSKonstantin Ananyev
65e18a033bSKonstantin Ananyev    { ngx_string("kqueue_events"),
66e18a033bSKonstantin Ananyev      NGX_EVENT_CONF|NGX_CONF_TAKE1,
67e18a033bSKonstantin Ananyev      ngx_conf_set_num_slot,
68e18a033bSKonstantin Ananyev      0,
69e18a033bSKonstantin Ananyev      offsetof(ngx_kqueue_conf_t, events),
70e18a033bSKonstantin Ananyev      NULL },
71e18a033bSKonstantin Ananyev
72e18a033bSKonstantin Ananyev      ngx_null_command
73e18a033bSKonstantin Ananyev};
74e18a033bSKonstantin Ananyev
75e18a033bSKonstantin Ananyev
76e18a033bSKonstantin Ananyevstatic ngx_event_module_t  ngx_kqueue_module_ctx = {
77e18a033bSKonstantin Ananyev    &kqueue_name,
78e18a033bSKonstantin Ananyev    ngx_kqueue_create_conf,                /* create configuration */
79e18a033bSKonstantin Ananyev    ngx_kqueue_init_conf,                  /* init configuration */
80e18a033bSKonstantin Ananyev
81e18a033bSKonstantin Ananyev    {
82e18a033bSKonstantin Ananyev        ngx_kqueue_add_event,              /* add an event */
83e18a033bSKonstantin Ananyev        ngx_kqueue_del_event,              /* delete an event */
84e18a033bSKonstantin Ananyev        ngx_kqueue_add_event,              /* enable an event */
85e18a033bSKonstantin Ananyev        ngx_kqueue_del_event,              /* disable an event */
86e18a033bSKonstantin Ananyev        NULL,                              /* add an connection */
87e18a033bSKonstantin Ananyev        NULL,                              /* delete an connection */
88e18a033bSKonstantin Ananyev#ifdef EVFILT_USER
89e18a033bSKonstantin Ananyev        ngx_kqueue_notify,                 /* trigger a notify */
90e18a033bSKonstantin Ananyev#else
91e18a033bSKonstantin Ananyev        NULL,                              /* trigger a notify */
92e18a033bSKonstantin Ananyev#endif
93e18a033bSKonstantin Ananyev        ngx_kqueue_process_events,         /* process the events */
94e18a033bSKonstantin Ananyev        ngx_kqueue_init,                   /* init the events */
95e18a033bSKonstantin Ananyev        ngx_kqueue_done                    /* done the events */
96e18a033bSKonstantin Ananyev    }
97e18a033bSKonstantin Ananyev
98e18a033bSKonstantin Ananyev};
99e18a033bSKonstantin Ananyev
100e18a033bSKonstantin Ananyevngx_module_t  ngx_kqueue_module = {
101e18a033bSKonstantin Ananyev    NGX_MODULE_V1,
102e18a033bSKonstantin Ananyev    &ngx_kqueue_module_ctx,                /* module context */
103e18a033bSKonstantin Ananyev    ngx_kqueue_commands,                   /* module directives */
104e18a033bSKonstantin Ananyev    NGX_EVENT_MODULE,                      /* module type */
105e18a033bSKonstantin Ananyev    NULL,                                  /* init master */
106e18a033bSKonstantin Ananyev    NULL,                                  /* init module */
107e18a033bSKonstantin Ananyev    NULL,                                  /* init process */
108e18a033bSKonstantin Ananyev    NULL,                                  /* init thread */
109e18a033bSKonstantin Ananyev    NULL,                                  /* exit thread */
110e18a033bSKonstantin Ananyev    NULL,                                  /* exit process */
111e18a033bSKonstantin Ananyev    NULL,                                  /* exit master */
112e18a033bSKonstantin Ananyev    NGX_MODULE_V1_PADDING
113e18a033bSKonstantin Ananyev};
114e18a033bSKonstantin Ananyev
115e18a033bSKonstantin Ananyev
116e18a033bSKonstantin Ananyevstatic ngx_int_t
117e18a033bSKonstantin Ananyevngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer)
118e18a033bSKonstantin Ananyev{
119e18a033bSKonstantin Ananyev    ngx_kqueue_conf_t  *kcf;
120e18a033bSKonstantin Ananyev    struct timespec     ts;
121e18a033bSKonstantin Ananyev#if (NGX_HAVE_TIMER_EVENT)
122e18a033bSKonstantin Ananyev    struct kevent       kev;
123e18a033bSKonstantin Ananyev#endif
124e18a033bSKonstantin Ananyev
125e18a033bSKonstantin Ananyev    kcf = ngx_event_get_conf(cycle->conf_ctx, ngx_kqueue_module);
126e18a033bSKonstantin Ananyev
127e18a033bSKonstantin Ananyev    if (ngx_kqueue == -1) {
128e18a033bSKonstantin Ananyev        ngx_kqueue = kqueue();
129e18a033bSKonstantin Ananyev
130e18a033bSKonstantin Ananyev        if (ngx_kqueue == -1) {
131e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
132e18a033bSKonstantin Ananyev                          "kqueue() failed");
133e18a033bSKonstantin Ananyev            return NGX_ERROR;
134e18a033bSKonstantin Ananyev        }
135e18a033bSKonstantin Ananyev
136e18a033bSKonstantin Ananyev#ifdef EVFILT_USER
137e18a033bSKonstantin Ananyev        if (ngx_kqueue_notify_init(cycle->log) != NGX_OK) {
138e18a033bSKonstantin Ananyev            return NGX_ERROR;
139e18a033bSKonstantin Ananyev        }
140e18a033bSKonstantin Ananyev#endif
141e18a033bSKonstantin Ananyev    }
142e18a033bSKonstantin Ananyev
143e18a033bSKonstantin Ananyev    if (max_changes < kcf->changes) {
144e18a033bSKonstantin Ananyev        if (nchanges) {
145e18a033bSKonstantin Ananyev            ts.tv_sec = 0;
146e18a033bSKonstantin Ananyev            ts.tv_nsec = 0;
147e18a033bSKonstantin Ananyev
148e18a033bSKonstantin Ananyev            if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)
149e18a033bSKonstantin Ananyev                == -1)
150e18a033bSKonstantin Ananyev            {
151e18a033bSKonstantin Ananyev                ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
152e18a033bSKonstantin Ananyev                              "kevent() failed");
153e18a033bSKonstantin Ananyev                return NGX_ERROR;
154e18a033bSKonstantin Ananyev            }
155e18a033bSKonstantin Ananyev            nchanges = 0;
156e18a033bSKonstantin Ananyev        }
157e18a033bSKonstantin Ananyev
158e18a033bSKonstantin Ananyev        if (change_list) {
159e18a033bSKonstantin Ananyev            ngx_free(change_list);
160e18a033bSKonstantin Ananyev        }
161e18a033bSKonstantin Ananyev
162e18a033bSKonstantin Ananyev        change_list = ngx_alloc(kcf->changes * sizeof(struct kevent),
163e18a033bSKonstantin Ananyev                                cycle->log);
164e18a033bSKonstantin Ananyev        if (change_list == NULL) {
165e18a033bSKonstantin Ananyev            return NGX_ERROR;
166e18a033bSKonstantin Ananyev        }
167e18a033bSKonstantin Ananyev    }
168e18a033bSKonstantin Ananyev
169e18a033bSKonstantin Ananyev    max_changes = kcf->changes;
170e18a033bSKonstantin Ananyev
171e18a033bSKonstantin Ananyev    if (nevents < kcf->events) {
172e18a033bSKonstantin Ananyev        if (event_list) {
173e18a033bSKonstantin Ananyev            ngx_free(event_list);
174e18a033bSKonstantin Ananyev        }
175e18a033bSKonstantin Ananyev
176e18a033bSKonstantin Ananyev        event_list = ngx_alloc(kcf->events * sizeof(struct kevent), cycle->log);
177e18a033bSKonstantin Ananyev        if (event_list == NULL) {
178e18a033bSKonstantin Ananyev            return NGX_ERROR;
179e18a033bSKonstantin Ananyev        }
180e18a033bSKonstantin Ananyev    }
181e18a033bSKonstantin Ananyev
182e18a033bSKonstantin Ananyev    ngx_event_flags = NGX_USE_ONESHOT_EVENT
183e18a033bSKonstantin Ananyev                      |NGX_USE_KQUEUE_EVENT
184e18a033bSKonstantin Ananyev                      |NGX_USE_VNODE_EVENT;
185e18a033bSKonstantin Ananyev
186e18a033bSKonstantin Ananyev#if (NGX_HAVE_TIMER_EVENT)
187e18a033bSKonstantin Ananyev
188e18a033bSKonstantin Ananyev    if (timer) {
189e18a033bSKonstantin Ananyev        kev.ident = 0;
190e18a033bSKonstantin Ananyev        kev.filter = EVFILT_TIMER;
191e18a033bSKonstantin Ananyev        kev.flags = EV_ADD|EV_ENABLE;
192e18a033bSKonstantin Ananyev        kev.fflags = 0;
193e18a033bSKonstantin Ananyev        kev.data = timer;
194e18a033bSKonstantin Ananyev        kev.udata = 0;
195e18a033bSKonstantin Ananyev
196e18a033bSKonstantin Ananyev        ts.tv_sec = 0;
197e18a033bSKonstantin Ananyev        ts.tv_nsec = 0;
198e18a033bSKonstantin Ananyev
199e18a033bSKonstantin Ananyev        if (kevent(ngx_kqueue, &kev, 1, NULL, 0, &ts) == -1) {
200e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
201e18a033bSKonstantin Ananyev                          "kevent(EVFILT_TIMER) failed");
202e18a033bSKonstantin Ananyev            return NGX_ERROR;
203e18a033bSKonstantin Ananyev        }
204e18a033bSKonstantin Ananyev
205e18a033bSKonstantin Ananyev        ngx_event_flags |= NGX_USE_TIMER_EVENT;
206e18a033bSKonstantin Ananyev    }
207e18a033bSKonstantin Ananyev
208e18a033bSKonstantin Ananyev#endif
209e18a033bSKonstantin Ananyev
210e18a033bSKonstantin Ananyev#if (NGX_HAVE_CLEAR_EVENT)
211e18a033bSKonstantin Ananyev    ngx_event_flags |= NGX_USE_CLEAR_EVENT;
212e18a033bSKonstantin Ananyev#else
213e18a033bSKonstantin Ananyev    ngx_event_flags |= NGX_USE_LEVEL_EVENT;
214e18a033bSKonstantin Ananyev#endif
215e18a033bSKonstantin Ananyev
216e18a033bSKonstantin Ananyev#if (NGX_HAVE_LOWAT_EVENT)
217e18a033bSKonstantin Ananyev    ngx_event_flags |= NGX_USE_LOWAT_EVENT;
218e18a033bSKonstantin Ananyev#endif
219e18a033bSKonstantin Ananyev
220e18a033bSKonstantin Ananyev    nevents = kcf->events;
221e18a033bSKonstantin Ananyev
222e18a033bSKonstantin Ananyev    ngx_io = ngx_os_io;
223e18a033bSKonstantin Ananyev
224e18a033bSKonstantin Ananyev    ngx_event_actions = ngx_kqueue_module_ctx.actions;
225e18a033bSKonstantin Ananyev
226e18a033bSKonstantin Ananyev    return NGX_OK;
227e18a033bSKonstantin Ananyev}
228e18a033bSKonstantin Ananyev
229e18a033bSKonstantin Ananyev
230e18a033bSKonstantin Ananyev#ifdef EVFILT_USER
231e18a033bSKonstantin Ananyev
232e18a033bSKonstantin Ananyevstatic ngx_int_t
233e18a033bSKonstantin Ananyevngx_kqueue_notify_init(ngx_log_t *log)
234e18a033bSKonstantin Ananyev{
235e18a033bSKonstantin Ananyev    notify_kev.ident = 0;
236e18a033bSKonstantin Ananyev    notify_kev.filter = EVFILT_USER;
237e18a033bSKonstantin Ananyev    notify_kev.data = 0;
238e18a033bSKonstantin Ananyev    notify_kev.flags = EV_ADD|EV_CLEAR;
239e18a033bSKonstantin Ananyev    notify_kev.fflags = 0;
240e18a033bSKonstantin Ananyev    notify_kev.udata = 0;
241e18a033bSKonstantin Ananyev
242e18a033bSKonstantin Ananyev    if (kevent(ngx_kqueue, &notify_kev, 1, NULL, 0, NULL) == -1) {
243e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
244e18a033bSKonstantin Ananyev                      "kevent(EVFILT_USER, EV_ADD) failed");
245e18a033bSKonstantin Ananyev        return NGX_ERROR;
246e18a033bSKonstantin Ananyev    }
247e18a033bSKonstantin Ananyev
248e18a033bSKonstantin Ananyev    notify_event.active = 1;
249e18a033bSKonstantin Ananyev    notify_event.log = log;
250e18a033bSKonstantin Ananyev
251e18a033bSKonstantin Ananyev    notify_kev.flags = 0;
252e18a033bSKonstantin Ananyev    notify_kev.fflags = NOTE_TRIGGER;
253e18a033bSKonstantin Ananyev    notify_kev.udata = NGX_KQUEUE_UDATA_T ((uintptr_t) &notify_event);
254e18a033bSKonstantin Ananyev
255e18a033bSKonstantin Ananyev    return NGX_OK;
256e18a033bSKonstantin Ananyev}
257e18a033bSKonstantin Ananyev
258e18a033bSKonstantin Ananyev#endif
259e18a033bSKonstantin Ananyev
260e18a033bSKonstantin Ananyev
261e18a033bSKonstantin Ananyevstatic void
262e18a033bSKonstantin Ananyevngx_kqueue_done(ngx_cycle_t *cycle)
263e18a033bSKonstantin Ananyev{
264e18a033bSKonstantin Ananyev    if (close(ngx_kqueue) == -1) {
265e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
266e18a033bSKonstantin Ananyev                      "kqueue close() failed");
267e18a033bSKonstantin Ananyev    }
268e18a033bSKonstantin Ananyev
269e18a033bSKonstantin Ananyev    ngx_kqueue = -1;
270e18a033bSKonstantin Ananyev
271e18a033bSKonstantin Ananyev    ngx_free(change_list);
272e18a033bSKonstantin Ananyev    ngx_free(event_list);
273e18a033bSKonstantin Ananyev
274e18a033bSKonstantin Ananyev    change_list = NULL;
275e18a033bSKonstantin Ananyev    event_list = NULL;
276e18a033bSKonstantin Ananyev    max_changes = 0;
277e18a033bSKonstantin Ananyev    nchanges = 0;
278e18a033bSKonstantin Ananyev    nevents = 0;
279e18a033bSKonstantin Ananyev}
280e18a033bSKonstantin Ananyev
281e18a033bSKonstantin Ananyev
282e18a033bSKonstantin Ananyevstatic ngx_int_t
283e18a033bSKonstantin Ananyevngx_kqueue_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
284e18a033bSKonstantin Ananyev{
285e18a033bSKonstantin Ananyev    ngx_int_t          rc;
286e18a033bSKonstantin Ananyev#if 0
287e18a033bSKonstantin Ananyev    ngx_event_t       *e;
288e18a033bSKonstantin Ananyev    ngx_connection_t  *c;
289e18a033bSKonstantin Ananyev#endif
290e18a033bSKonstantin Ananyev
291e18a033bSKonstantin Ananyev    ev->active = 1;
292e18a033bSKonstantin Ananyev    ev->disabled = 0;
293e18a033bSKonstantin Ananyev    ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1 : 0;
294e18a033bSKonstantin Ananyev
295e18a033bSKonstantin Ananyev#if 0
296e18a033bSKonstantin Ananyev
297e18a033bSKonstantin Ananyev    if (ev->index < nchanges
298e18a033bSKonstantin Ananyev        && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1)
299e18a033bSKonstantin Ananyev            == (uintptr_t) ev)
300e18a033bSKonstantin Ananyev    {
301e18a033bSKonstantin Ananyev        if (change_list[ev->index].flags == EV_DISABLE) {
302e18a033bSKonstantin Ananyev
303e18a033bSKonstantin Ananyev            /*
304e18a033bSKonstantin Ananyev             * if the EV_DISABLE is still not passed to a kernel
305e18a033bSKonstantin Ananyev             * we will not pass it
306e18a033bSKonstantin Ananyev             */
307e18a033bSKonstantin Ananyev
308e18a033bSKonstantin Ananyev            ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
309e18a033bSKonstantin Ananyev                           "kevent activated: %d: ft:%i",
310e18a033bSKonstantin Ananyev                           ngx_event_ident(ev->data), event);
311e18a033bSKonstantin Ananyev
312e18a033bSKonstantin Ananyev            if (ev->index < --nchanges) {
313e18a033bSKonstantin Ananyev                e = (ngx_event_t *)
314e18a033bSKonstantin Ananyev                    ((uintptr_t) change_list[nchanges].udata & (uintptr_t) ~1);
315e18a033bSKonstantin Ananyev                change_list[ev->index] = change_list[nchanges];
316e18a033bSKonstantin Ananyev                e->index = ev->index;
317e18a033bSKonstantin Ananyev            }
318e18a033bSKonstantin Ananyev
319e18a033bSKonstantin Ananyev            return NGX_OK;
320e18a033bSKonstantin Ananyev        }
321e18a033bSKonstantin Ananyev
322e18a033bSKonstantin Ananyev        c = ev->data;
323e18a033bSKonstantin Ananyev
324e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
325e18a033bSKonstantin Ananyev                      "previous event on #%d were not passed in kernel", c->fd);
326e18a033bSKonstantin Ananyev
327e18a033bSKonstantin Ananyev        return NGX_ERROR;
328e18a033bSKonstantin Ananyev    }
329e18a033bSKonstantin Ananyev
330e18a033bSKonstantin Ananyev#endif
331e18a033bSKonstantin Ananyev
332e18a033bSKonstantin Ananyev    rc = ngx_kqueue_set_event(ev, event, EV_ADD|EV_ENABLE|flags);
333e18a033bSKonstantin Ananyev
334e18a033bSKonstantin Ananyev    return rc;
335e18a033bSKonstantin Ananyev}
336e18a033bSKonstantin Ananyev
337e18a033bSKonstantin Ananyev
338e18a033bSKonstantin Ananyevstatic ngx_int_t
339e18a033bSKonstantin Ananyevngx_kqueue_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
340e18a033bSKonstantin Ananyev{
341e18a033bSKonstantin Ananyev    ngx_int_t     rc;
342e18a033bSKonstantin Ananyev    ngx_event_t  *e;
343e18a033bSKonstantin Ananyev
344e18a033bSKonstantin Ananyev    ev->active = 0;
345e18a033bSKonstantin Ananyev    ev->disabled = 0;
346e18a033bSKonstantin Ananyev
347e18a033bSKonstantin Ananyev    if (ev->index < nchanges
348e18a033bSKonstantin Ananyev        && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1)
349e18a033bSKonstantin Ananyev            == (uintptr_t) ev)
350e18a033bSKonstantin Ananyev    {
351e18a033bSKonstantin Ananyev        ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
352e18a033bSKonstantin Ananyev                       "kevent deleted: %d: ft:%i",
353e18a033bSKonstantin Ananyev                       ngx_event_ident(ev->data), event);
354e18a033bSKonstantin Ananyev
355e18a033bSKonstantin Ananyev        /* if the event is still not passed to a kernel we will not pass it */
356e18a033bSKonstantin Ananyev
357e18a033bSKonstantin Ananyev        nchanges--;
358e18a033bSKonstantin Ananyev
359e18a033bSKonstantin Ananyev        if (ev->index < nchanges) {
360e18a033bSKonstantin Ananyev            e = (ngx_event_t *)
361e18a033bSKonstantin Ananyev                    ((uintptr_t) change_list[nchanges].udata & (uintptr_t) ~1);
362e18a033bSKonstantin Ananyev            change_list[ev->index] = change_list[nchanges];
363e18a033bSKonstantin Ananyev            e->index = ev->index;
364e18a033bSKonstantin Ananyev        }
365e18a033bSKonstantin Ananyev
366e18a033bSKonstantin Ananyev        return NGX_OK;
367e18a033bSKonstantin Ananyev    }
368e18a033bSKonstantin Ananyev
369e18a033bSKonstantin Ananyev    /*
370e18a033bSKonstantin Ananyev     * when the file descriptor is closed the kqueue automatically deletes
371e18a033bSKonstantin Ananyev     * its filters so we do not need to delete explicitly the event
372e18a033bSKonstantin Ananyev     * before the closing the file descriptor.
373e18a033bSKonstantin Ananyev     */
374e18a033bSKonstantin Ananyev
375e18a033bSKonstantin Ananyev    if (flags & NGX_CLOSE_EVENT) {
376e18a033bSKonstantin Ananyev        return NGX_OK;
377e18a033bSKonstantin Ananyev    }
378e18a033bSKonstantin Ananyev
379e18a033bSKonstantin Ananyev    if (flags & NGX_DISABLE_EVENT) {
380e18a033bSKonstantin Ananyev        ev->disabled = 1;
381e18a033bSKonstantin Ananyev
382e18a033bSKonstantin Ananyev    } else {
383e18a033bSKonstantin Ananyev        flags |= EV_DELETE;
384e18a033bSKonstantin Ananyev    }
385e18a033bSKonstantin Ananyev
386e18a033bSKonstantin Ananyev    rc = ngx_kqueue_set_event(ev, event, flags);
387e18a033bSKonstantin Ananyev
388e18a033bSKonstantin Ananyev    return rc;
389e18a033bSKonstantin Ananyev}
390e18a033bSKonstantin Ananyev
391e18a033bSKonstantin Ananyev
392e18a033bSKonstantin Ananyevstatic ngx_int_t
393e18a033bSKonstantin Ananyevngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter, ngx_uint_t flags)
394e18a033bSKonstantin Ananyev{
395e18a033bSKonstantin Ananyev    struct kevent     *kev;
396e18a033bSKonstantin Ananyev    struct timespec    ts;
397e18a033bSKonstantin Ananyev    ngx_connection_t  *c;
398e18a033bSKonstantin Ananyev
399e18a033bSKonstantin Ananyev    c = ev->data;
400e18a033bSKonstantin Ananyev
401e18a033bSKonstantin Ananyev    ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
402e18a033bSKonstantin Ananyev                   "kevent set event: %d: ft:%i fl:%04Xi",
403e18a033bSKonstantin Ananyev                   c->fd, filter, flags);
404e18a033bSKonstantin Ananyev
405e18a033bSKonstantin Ananyev    if (nchanges >= max_changes) {
406e18a033bSKonstantin Ananyev        ngx_log_error(NGX_LOG_WARN, ev->log, 0,
407e18a033bSKonstantin Ananyev                      "kqueue change list is filled up");
408e18a033bSKonstantin Ananyev
409e18a033bSKonstantin Ananyev        ts.tv_sec = 0;
410e18a033bSKonstantin Ananyev        ts.tv_nsec = 0;
411e18a033bSKonstantin Ananyev
412e18a033bSKonstantin Ananyev        if (kevent(ngx_kqueue, change_list, (int) nchanges, NULL, 0, &ts)
413e18a033bSKonstantin Ananyev            == -1)
414e18a033bSKonstantin Ananyev        {
415e18a033bSKonstantin Ananyev            ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent() failed");
416e18a033bSKonstantin Ananyev            return NGX_ERROR;
417e18a033bSKonstantin Ananyev        }
418e18a033bSKonstantin Ananyev
419