Mercurial > hg > nginx-quic
comparison src/event/modules/ngx_kqueue_module.c @ 39:83fa61cd3d2f
nginx-0.0.1-2002-12-24-20:30:59 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 24 Dec 2002 17:30:59 +0000 |
parents | 2ffaa35fba42 |
children | b288069a8696 |
comparison
equal
deleted
inserted
replaced
38:2ffaa35fba42 | 39:83fa61cd3d2f |
---|---|
14 #if (USE_KQUEUE) && !(HAVE_KQUEUE) | 14 #if (USE_KQUEUE) && !(HAVE_KQUEUE) |
15 #error "kqueue is not supported on this platform" | 15 #error "kqueue is not supported on this platform" |
16 #endif | 16 #endif |
17 | 17 |
18 | 18 |
19 /* STUB */ | |
20 #define KQUEUE_NCHANGES 512 | |
21 #define KQUEUE_NEVENTS 512 | |
22 | |
23 | |
19 /* should be per-thread */ | 24 /* should be per-thread */ |
20 static int kq; | 25 static int kq; |
21 static struct kevent *change_list, *event_list; | 26 static struct kevent *change_list, *event_list; |
22 static int nchanges, nevents; | 27 static unsigned int nchanges; |
28 static int nevents; | |
23 | 29 |
24 static ngx_event_t timer_queue; | 30 static ngx_event_t timer_queue; |
25 /* */ | 31 /* */ |
26 | 32 |
27 | 33 |
28 int ngx_kqueue_init(int max_connections, ngx_log_t *log) | 34 int ngx_kqueue_init(int max_connections, ngx_log_t *log) |
29 { | 35 { |
30 int size; | 36 int change_size, event_size; |
31 | 37 |
32 size = sizeof(struct kevent) * 512; | 38 nevents = KQUEUE_NEVENTS; |
33 nchanges = 0; | 39 nchanges = 0; |
34 nevents = 512; | 40 change_size = sizeof(struct kevent) * KQUEUE_NCHANGES; |
41 event_size = sizeof(struct kevent) * KQUEUE_NEVENTS; | |
35 | 42 |
36 kq = kqueue(); | 43 kq = kqueue(); |
37 | 44 |
38 if (kq == -1) { | 45 if (kq == -1) { |
39 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "kqueue() failed"); | 46 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "kqueue() failed"); |
40 return NGX_ERROR; | 47 return NGX_ERROR; |
41 } | 48 } |
42 | 49 |
43 ngx_test_null(change_list, ngx_alloc(size, log), NGX_ERROR); | 50 ngx_test_null(change_list, ngx_alloc(change_size, log), NGX_ERROR); |
44 ngx_test_null(event_list, ngx_alloc(size, log), NGX_ERROR); | 51 ngx_test_null(event_list, ngx_alloc(event_size, log), NGX_ERROR); |
45 | 52 |
46 timer_queue.timer_prev = &timer_queue; | 53 timer_queue.timer_prev = &timer_queue; |
47 timer_queue.timer_next = &timer_queue; | 54 timer_queue.timer_next = &timer_queue; |
48 | 55 |
49 #if !(USE_KQUEUE) | 56 #if !(USE_KQUEUE) |
57 } | 64 } |
58 | 65 |
59 | 66 |
60 int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags) | 67 int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags) |
61 { | 68 { |
69 ev->active = 1; | |
62 ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0; | 70 ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0; |
63 | 71 |
64 if (nchanges > 0 | 72 if (nchanges > 0 |
65 && ev->index < nchanges | 73 && ev->index < nchanges |
66 && change_list[ev->index].udata == ev) | 74 && change_list[ev->index].udata == ev) |
67 { | 75 { |
68 /* DEBUG */ | 76 #if (NGX_DEBUG_EVENT) |
69 ngx_connection_t *c = (ngx_connection_t *) ev->data; | 77 ngx_connection_t *c = (ngx_connection_t *) ev->data; |
70 ngx_log_debug(ev->log, "kqueue add event: %d: ft:%d" _ c->fd _ event); | 78 ngx_log_debug(ev->log, "kqueue add event: %d: ft:%d" _ c->fd _ event); |
71 | 79 #endif |
72 change_list[ev->index].filter = event; | 80 change_list[ev->index].filter = event; |
73 change_list[ev->index].flags = flags; | 81 change_list[ev->index].flags = flags; |
74 | 82 |
75 return NGX_OK; | 83 return NGX_OK; |
76 } | 84 } |
79 } | 87 } |
80 | 88 |
81 | 89 |
82 int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags) | 90 int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags) |
83 { | 91 { |
84 ngx_event_t *e; | 92 ngx_event_t *e; |
93 | |
94 ev->active = 0; | |
85 | 95 |
86 if (nchanges > 0 | 96 if (nchanges > 0 |
87 && ev->index < nchanges | 97 && ev->index < nchanges |
88 && change_list[ev->index].udata == ev) | 98 && change_list[ev->index].udata == ev) |
89 { | 99 { |
90 /* DEBUG */ | 100 #if (NGX_DEBUG_EVENT) |
91 ngx_connection_t *c = (ngx_connection_t *) ev->data; | 101 ngx_connection_t *c = (ngx_connection_t *) ev->data; |
92 ngx_log_debug(ev->log, "kqueue del event: %d: ft:%d" _ c->fd _ event); | 102 ngx_log_debug(ev->log, "kqueue del event: %d: ft:%d" _ c->fd _ event); |
93 | 103 #endif |
94 if (ev->index < --nchanges) { | 104 if (ev->index < --nchanges) { |
95 e = (ngx_event_t *) change_list[nchanges].udata; | 105 e = (ngx_event_t *) change_list[nchanges].udata; |
96 change_list[ev->index] = change_list[nchanges]; | 106 change_list[ev->index] = change_list[nchanges]; |
97 e->index = ev->index; | 107 e->index = ev->index; |
98 } | 108 } |
99 | 109 |
100 return NGX_OK; | 110 return NGX_OK; |
101 } | 111 } |
102 | 112 |
103 if (flags & NGX_CLOSE_EVENT) | 113 if (flags & NGX_CLOSE_EVENT) { |
104 return NGX_OK; | 114 return NGX_OK; |
115 } | |
105 | 116 |
106 return ngx_kqueue_set_event(ev, event, EV_DELETE); | 117 return ngx_kqueue_set_event(ev, event, EV_DELETE); |
107 } | 118 } |
108 | 119 |
109 | 120 |
110 int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags) | 121 int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags) |
111 { | 122 { |
112 struct timespec ts; | 123 struct timespec ts; |
113 ngx_connection_t *c; | 124 ngx_connection_t *c; |
114 | 125 |
115 c = (ngx_connection_t *) ev->data; | 126 c = (ngx_connection_t *) ev->data; |
116 | 127 |
128 #if (NGX_DEBUG_EVENT) | |
117 ngx_log_debug(ev->log, "kqueue set event: %d: ft:%d f:%08x" _ | 129 ngx_log_debug(ev->log, "kqueue set event: %d: ft:%d f:%08x" _ |
118 c->fd _ filter _ flags); | 130 c->fd _ filter _ flags); |
119 | 131 #endif |
120 if (nchanges >= nevents) { | 132 |
133 if (nchanges >= KQUEUE_NCHANGES) { | |
121 ngx_log_error(NGX_LOG_WARN, ev->log, 0, | 134 ngx_log_error(NGX_LOG_WARN, ev->log, 0, |
122 "kqueue change list is filled up"); | 135 "kqueue change list is filled up"); |
123 | 136 |
124 ts.tv_sec = 0; | 137 ts.tv_sec = 0; |
125 ts.tv_nsec = 0; | 138 ts.tv_nsec = 0; |
126 | 139 |
127 if (kevent(kq, change_list, nchanges, NULL, 0, &ts) == -1) { | 140 if (kevent(kq, change_list, nchanges, NULL, 0, &ts) == -1) { |
128 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent failed"); | 141 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent failed"); |
129 return NGX_ERROR; | 142 return NGX_ERROR; |
130 } | 143 } |
144 | |
131 nchanges = 0; | 145 nchanges = 0; |
132 } | 146 } |
133 | 147 |
134 change_list[nchanges].ident = c->fd; | 148 change_list[nchanges].ident = c->fd; |
135 change_list[nchanges].filter = filter; | 149 change_list[nchanges].filter = filter; |
166 timer = 0; | 180 timer = 0; |
167 delta = 0; | 181 delta = 0; |
168 tp = NULL; | 182 tp = NULL; |
169 } | 183 } |
170 | 184 |
185 #if (NGX_DEBUG_EVENT) | |
171 ngx_log_debug(log, "kevent timer: %d" _ timer); | 186 ngx_log_debug(log, "kevent timer: %d" _ timer); |
187 #endif | |
172 | 188 |
173 events = kevent(kq, change_list, nchanges, event_list, nevents, tp); | 189 events = kevent(kq, change_list, nchanges, event_list, nevents, tp); |
174 | 190 |
175 if (events == -1) { | 191 if (events == -1) { |
176 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "kevent failed"); | 192 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "kevent failed"); |
182 if (timer) { | 198 if (timer) { |
183 gettimeofday(&tv, NULL); | 199 gettimeofday(&tv, NULL); |
184 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; | 200 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; |
185 | 201 |
186 } else { | 202 } else { |
187 ngx_assert((events != 0), return NGX_ERROR, log, | 203 if (events == 0) { |
188 "kevent returns no events without timeout"); | 204 ngx_log_error(NGX_LOG_ALERT, log, 0, |
189 } | 205 "kevent returns no events without timeout"); |
190 | 206 return NGX_ERROR; |
207 } | |
208 } | |
209 | |
210 #if (NGX_DEBUG_EVENT) | |
191 ngx_log_debug(log, "kevent timer: %d, delta: %d" _ timer _ delta); | 211 ngx_log_debug(log, "kevent timer: %d, delta: %d" _ timer _ delta); |
192 | 212 #endif |
193 if (timer) { | |
194 if (delta >= timer) { | |
195 for ( ;; ) { | |
196 ev = timer_queue.timer_next; | |
197 | |
198 if (ev == &timer_queue || delta < ev->timer_delta) | |
199 break; | |
200 | |
201 delta -= ev->timer_delta; | |
202 ngx_del_timer(ev); | |
203 ev->timedout = 1; | |
204 if (ev->event_handler(ev) == NGX_ERROR) | |
205 ev->close_handler(ev); | |
206 } | |
207 | |
208 } else { | |
209 timer_queue.timer_next->timer_delta -= delta; | |
210 } | |
211 } | |
212 | 213 |
213 for (i = 0; i < events; i++) { | 214 for (i = 0; i < events; i++) { |
214 | 215 |
216 #if (NGX_DEBUG_EVENT) | |
215 ngx_log_debug(log, "kevent: %d: ft:%d f:%08x ff:%08x d:%d ud:%08x" _ | 217 ngx_log_debug(log, "kevent: %d: ft:%d f:%08x ff:%08x d:%d ud:%08x" _ |
216 event_list[i].ident _ event_list[i].filter _ | 218 event_list[i].ident _ event_list[i].filter _ |
217 event_list[i].flags _ event_list[i].fflags _ | 219 event_list[i].flags _ event_list[i].fflags _ |
218 event_list[i].data _ event_list[i].udata); | 220 event_list[i].data _ event_list[i].udata); |
221 #endif | |
219 | 222 |
220 if (event_list[i].flags & EV_ERROR) { | 223 if (event_list[i].flags & EV_ERROR) { |
221 ngx_log_error(NGX_LOG_ALERT, log, event_list[i].data, | 224 ngx_log_error(NGX_LOG_ALERT, log, event_list[i].data, |
222 "kevent error on %d", event_list[i].ident); | 225 "kevent error on %d", event_list[i].ident); |
223 continue; | 226 continue; |
224 } | 227 } |
225 | 228 |
226 ev = (ngx_event_t *) event_list[i].udata; | 229 ev = (ngx_event_t *) event_list[i].udata; |
227 | 230 |
231 if (!ev->active) { | |
232 continue; | |
233 } | |
234 | |
228 switch (event_list[i].filter) { | 235 switch (event_list[i].filter) { |
229 | 236 |
230 case EVFILT_READ: | 237 case EVFILT_READ: |
231 case EVFILT_WRITE: | 238 case EVFILT_WRITE: |
232 ev->ready = 1; | 239 ev->ready = 1; |
235 if (event_list[i].flags & EV_EOF) { | 242 if (event_list[i].flags & EV_EOF) { |
236 ev->eof = 1; | 243 ev->eof = 1; |
237 ev->error = event_list[i].fflags; | 244 ev->error = event_list[i].fflags; |
238 } | 245 } |
239 | 246 |
240 if (ev->oneshot) | 247 if (ev->oneshot) { |
241 ngx_del_timer(ev); | 248 ngx_del_timer(ev); |
242 | 249 } |
243 if (ev->event_handler(ev) == NGX_ERROR) | 250 |
251 if (ev->event_handler(ev) == NGX_ERROR) { | |
244 ev->close_handler(ev); | 252 ev->close_handler(ev); |
253 } | |
245 | 254 |
246 break; | 255 break; |
247 | 256 |
248 default: | 257 default: |
249 ngx_assert(0, /* void */, log, | 258 ngx_log_error(NGX_LOG_ALERT, log, 0, |
250 "unknown kevent filter %d" _ event_list[i].filter); | 259 "unknown kevent filter %d" _ event_list[i].filter); |
260 } | |
261 } | |
262 | |
263 if (timer && timer_queue.timer_next != &timer_queue) { | |
264 if (delta >= timer_queue.timer_next->timer_delta) { | |
265 for ( ;; ) { | |
266 ev = timer_queue.timer_next; | |
267 | |
268 if (ev == &timer_queue || delta < ev->timer_delta) { | |
269 break; | |
270 } | |
271 | |
272 delta -= ev->timer_delta; | |
273 | |
274 ngx_del_timer(ev); | |
275 ev->timedout = 1; | |
276 if (ev->event_handler(ev) == NGX_ERROR) { | |
277 ev->close_handler(ev); | |
278 } | |
279 } | |
280 | |
281 } else { | |
282 timer_queue.timer_next->timer_delta -= delta; | |
251 } | 283 } |
252 } | 284 } |
253 | 285 |
254 return NGX_OK; | 286 return NGX_OK; |
255 } | 287 } |
256 | 288 |
257 | 289 |
258 void ngx_kqueue_add_timer(ngx_event_t *ev, ngx_msec_t timer) | 290 void ngx_kqueue_add_timer(ngx_event_t *ev, ngx_msec_t timer) |
259 { | 291 { |
260 ngx_event_t *e; | 292 ngx_event_t *e; |
261 | 293 |
262 #if (NGX_DEBUG) | 294 #if (NGX_DEBUG_EVENT) |
263 ngx_connection_t *c = (ngx_connection_t *) ev->data; | 295 ngx_connection_t *c = (ngx_connection_t *) ev->data; |
264 ngx_log_debug(ev->log, "set timer: %d:%d" _ c->fd _ timer); | 296 ngx_log_debug(ev->log, "set timer: %d:%d" _ c->fd _ timer); |
265 #endif | 297 #endif |
266 ngx_assert((!ev->timer_next && !ev->timer_prev), return, ev->log, | 298 |
267 "timer already set"); | 299 if (ev->timer_next || ev->timer_prev) { |
300 ngx_log_error(NGX_LOG_ALERT, ev->log, 0, "timer already set"); | |
301 return; | |
302 } | |
268 | 303 |
269 for (e = timer_queue.timer_next; | 304 for (e = timer_queue.timer_next; |
270 e != &timer_queue && timer > e->timer_delta; | 305 e != &timer_queue && timer > e->timer_delta; |
271 e = e->timer_next) | 306 e = e->timer_next) |
307 { | |
272 timer -= e->timer_delta; | 308 timer -= e->timer_delta; |
309 } | |
273 | 310 |
274 ev->timer_delta = timer; | 311 ev->timer_delta = timer; |
275 | 312 |
276 ev->timer_next = e; | 313 ev->timer_next = e; |
277 ev->timer_prev = e->timer_prev; | 314 ev->timer_prev = e->timer_prev; |