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;