Mercurial > hg > nginx
comparison src/event/modules/ngx_kqueue_module.c @ 91:637625a2acdb
nginx-0.0.1-2003-05-19-20:39:14 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 19 May 2003 16:39:14 +0000 |
parents | 37530da31268 |
children | 19cc647ecd91 |
comparison
equal
deleted
inserted
replaced
90:37530da31268 | 91:637625a2acdb |
---|---|
1 | |
1 /* | 2 /* |
2 * Copyright (C) 2002-2003 Igor Sysoev, http://sysoev.ru | 3 * Copyright (C) 2002-2003 Igor Sysoev, http://sysoev.ru |
3 */ | 4 */ |
4 | 5 |
5 | 6 |
6 #include <ngx_config.h> | 7 #include <ngx_config.h> |
7 #include <ngx_core.h> | 8 #include <ngx_core.h> |
8 #include <ngx_types.h> | |
9 #include <ngx_log.h> | |
10 #include <ngx_connection.h> | 9 #include <ngx_connection.h> |
11 #include <ngx_event.h> | 10 #include <ngx_event.h> |
12 #include <ngx_event_timer.h> | |
13 #include <ngx_conf_file.h> | |
14 #include <ngx_kqueue_module.h> | 11 #include <ngx_kqueue_module.h> |
15 | 12 |
16 | 13 |
17 /* STUB */ | 14 static int ngx_kqueue_init(ngx_log_t *log); |
18 #define KQUEUE_NCHANGES 512 | 15 static void ngx_kqueue_done(ngx_log_t *log); |
19 #define KQUEUE_NEVENTS 512 | 16 static int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags); |
20 | 17 static int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags); |
21 | 18 static int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags); |
22 static int ngx_kqueue_changes; | 19 static int ngx_kqueue_process_events(ngx_log_t *log); |
23 static int ngx_kqueue_events; | 20 |
24 | 21 static void *ngx_kqueue_create_conf(ngx_pool_t *pool); |
25 | 22 static char *ngx_kqueue_init_conf(ngx_pool_t *pool, void *conf); |
26 /* should be per-thread if threads are used without thread pool */ | 23 |
27 #if 1 | 24 |
28 int kq; | 25 int ngx_kqueue; |
29 #else | 26 |
30 static int kq; | 27 static struct kevent *change_list, *event_list; |
31 #endif | 28 static u_int max_changes, nchanges; |
32 static struct kevent *change_list, *event_list; | 29 static int nevents; |
33 static unsigned int nchanges; | 30 |
34 static int nevents; | 31 |
35 | 32 static ngx_str_t kqueue_name = ngx_string("kqueue"); |
36 static ngx_event_t *timer_queue; | |
37 /* */ | |
38 | |
39 | |
40 static ngx_str_t kqueue_name = ngx_string("kqueue"); | |
41 | 33 |
42 static ngx_command_t ngx_kqueue_commands[] = { | 34 static ngx_command_t ngx_kqueue_commands[] = { |
43 | 35 |
44 {ngx_string("kqueue_changes"), | 36 {ngx_string("kqueue_changes"), |
45 NGX_EVENT_CONF|NGX_CONF_TAKE1, | 37 NGX_EVENT_CONF|NGX_CONF_TAKE1, |
46 ngx_conf_set_num_slot, | 38 ngx_conf_set_num_slot, |
47 0, | 39 0, |
48 addressof(ngx_kqueue_changes), | 40 offsetof(ngx_kqueue_conf_t, changes), |
49 NULL}, | 41 NULL}, |
50 | 42 |
51 {ngx_string("kqueue_events"), | 43 {ngx_string("kqueue_events"), |
52 NGX_EVENT_CONF|NGX_CONF_TAKE1, | 44 NGX_EVENT_CONF|NGX_CONF_TAKE1, |
53 ngx_conf_set_num_slot, | 45 ngx_conf_set_num_slot, |
54 0, | 46 0, |
55 addressof(ngx_kqueue_events), | 47 offsetof(ngx_kqueue_conf_t, events), |
56 NULL}, | 48 NULL}, |
57 | 49 |
58 {ngx_string(""), 0, NULL, 0, 0, NULL} | 50 {ngx_string(""), 0, NULL, 0, 0, NULL} |
59 }; | 51 }; |
60 | 52 |
53 | |
54 ngx_event_module_t ngx_kqueue_module_ctx = { | |
55 NGX_EVENT_MODULE, | |
56 &kqueue_name, | |
57 ngx_kqueue_create_conf, /* create configuration */ | |
58 ngx_kqueue_init_conf, /* init configuration */ | |
59 | |
60 { | |
61 ngx_kqueue_add_event, /* add an event */ | |
62 ngx_kqueue_del_event, /* delete an event */ | |
63 ngx_kqueue_add_event, /* enable an event */ | |
64 ngx_kqueue_del_event, /* disable an event */ | |
65 NULL, /* add an connection */ | |
66 NULL, /* delete an connection */ | |
67 ngx_kqueue_process_events, /* process the events */ | |
68 ngx_kqueue_init, /* init the events */ | |
69 ngx_kqueue_done, /* done the events */ | |
70 } | |
71 | |
72 }; | |
73 | |
61 ngx_module_t ngx_kqueue_module = { | 74 ngx_module_t ngx_kqueue_module = { |
62 &kqueue_name, /* module context */ | 75 &ngx_kqueue_module_ctx, /* module context */ |
63 0, /* module index */ | 76 0, /* module index */ |
64 ngx_kqueue_commands, /* module directives */ | 77 ngx_kqueue_commands, /* module directives */ |
65 NGX_EVENT_MODULE_TYPE, /* module type */ | 78 NGX_EVENT_MODULE_TYPE, /* module type */ |
66 NULL /* init module */ | 79 NULL /* init module */ |
67 }; | 80 }; |
68 | 81 |
69 | 82 |
70 | 83 static int ngx_kqueue_init(ngx_log_t *log) |
71 int ngx_kqueue_init(int max_connections, ngx_log_t *log) | 84 { |
72 { | 85 ngx_kqueue_conf_t *kcf; |
73 int change_size, event_size; | 86 |
74 | 87 kcf = ngx_event_get_conf(ngx_kqueue_module_ctx); |
75 nevents = KQUEUE_NEVENTS; | 88 |
89 ngx_log_debug(log, "CH: %d" _ kcf->changes); | |
90 ngx_log_debug(log, "EV: %d" _ kcf->events); | |
91 | |
92 max_changes = kcf->changes; | |
93 nevents = kcf->events; | |
76 nchanges = 0; | 94 nchanges = 0; |
77 change_size = sizeof(struct kevent) * KQUEUE_NCHANGES; | 95 |
78 event_size = sizeof(struct kevent) * KQUEUE_NEVENTS; | 96 ngx_kqueue = kqueue(); |
79 | 97 |
80 kq = kqueue(); | 98 if (ngx_kqueue == -1) { |
81 | |
82 if (kq == -1) { | |
83 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "kqueue() failed"); | 99 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "kqueue() failed"); |
84 return NGX_ERROR; | 100 return NGX_ERROR; |
85 } | 101 } |
86 | 102 |
87 ngx_test_null(change_list, ngx_alloc(change_size, log), NGX_ERROR); | 103 ngx_test_null(change_list, |
88 ngx_test_null(event_list, ngx_alloc(event_size, log), NGX_ERROR); | 104 ngx_alloc(kcf->changes * sizeof(struct kevent), log), |
89 | 105 NGX_ERROR); |
90 timer_queue = ngx_event_init_timer(log); | 106 ngx_test_null(event_list, |
91 if (timer_queue == NULL) { | 107 ngx_alloc(kcf->events * sizeof(struct kevent), log), |
108 NGX_ERROR); | |
109 | |
110 if (ngx_event_timer_init(log) == NGX_ERROR) { | |
92 return NGX_ERROR; | 111 return NGX_ERROR; |
93 } | 112 } |
94 | 113 |
95 ngx_event_actions.add = ngx_kqueue_add_event; | 114 ngx_event_actions = ngx_kqueue_module_ctx.actions; |
96 ngx_event_actions.del = ngx_kqueue_del_event; | |
97 ngx_event_actions.timer = ngx_event_add_timer; | |
98 ngx_event_actions.process = ngx_kqueue_process_events; | |
99 | |
100 #if (HAVE_AIO_EVENT) | |
101 | |
102 ngx_event_flags = NGX_HAVE_AIO_EVENT; | |
103 | |
104 #else | |
105 | 115 |
106 ngx_event_flags = NGX_HAVE_LEVEL_EVENT | 116 ngx_event_flags = NGX_HAVE_LEVEL_EVENT |
107 |NGX_HAVE_ONESHOT_EVENT | 117 |NGX_HAVE_ONESHOT_EVENT |
108 | |
109 #if (HAVE_CLEAR_EVENT) | 118 #if (HAVE_CLEAR_EVENT) |
110 |NGX_HAVE_CLEAR_EVENT | 119 |NGX_HAVE_CLEAR_EVENT |
111 #else | 120 #else |
112 |NGX_USE_LEVEL_EVENT | 121 |NGX_USE_LEVEL_EVENT |
113 #endif | 122 #endif |
114 | |
115 #if (HAVE_LOWAT_EVENT) | 123 #if (HAVE_LOWAT_EVENT) |
116 |NGX_HAVE_LOWAT_EVENT | 124 |NGX_HAVE_LOWAT_EVENT |
117 #endif | 125 #endif |
118 | |
119 |NGX_HAVE_KQUEUE_EVENT; | 126 |NGX_HAVE_KQUEUE_EVENT; |
120 | 127 |
121 ngx_write_chain_proc = ngx_freebsd_write_chain; | |
122 | |
123 #endif | |
124 | |
125 return NGX_OK; | 128 return NGX_OK; |
126 } | 129 } |
127 | 130 |
128 | 131 |
129 void ngx_kqueue_done(ngx_log_t *log) | 132 static void ngx_kqueue_done(ngx_log_t *log) |
130 { | 133 { |
131 if (close(kq) == -1) { | 134 if (close(ngx_kqueue) == -1) { |
132 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "kqueue close() failed"); | 135 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "kqueue close() failed"); |
133 } | 136 } |
134 } | 137 |
135 | 138 ngx_event_timer_done(log); |
136 | 139 |
137 int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags) | 140 ngx_free(change_list); |
138 { | 141 ngx_free(event_list); |
142 } | |
143 | |
144 | |
145 static int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags) | |
146 { | |
147 ngx_connection_t *c; | |
148 | |
139 ev->active = 1; | 149 ev->active = 1; |
140 ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0; | 150 ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0; |
141 | 151 |
142 /* The event addition or change should be always passed to a kernel | |
143 because there can be case when event was passed to a kernel then | |
144 added again to the change_list and then deleted from the change_list | |
145 by ngx_kqueue_del_event() so the first event still remains in a kernel */ | |
146 | |
147 #if 0 | |
148 | |
149 if (nchanges > 0 | 152 if (nchanges > 0 |
150 && ev->index < nchanges | 153 && ev->index < nchanges |
151 && change_list[ev->index].udata == ev) | 154 && (void *) ((uintptr_t) change_list[ev->index].udata & ~1) == ev) |
152 { | 155 { |
153 #if (NGX_DEBUG_EVENT) | 156 c = ev->data; |
154 ngx_connection_t *c = (ngx_connection_t *) ev->data; | 157 ngx_log_error(NGX_LOG_ALERT, ev->log, 0, |
155 ngx_log_debug(ev->log, "kqueue add event: %d: ft:%d" _ c->fd _ event); | 158 "previous event were not passed in kernel", c->fd); |
156 #endif | 159 |
157 | 160 return NGX_ERROR; |
158 /* if the event is still not passed to a kernel we change it */ | 161 } |
159 | |
160 change_list[ev->index].filter = event; | |
161 change_list[ev->index].flags = flags; | |
162 | |
163 return NGX_OK; | |
164 } | |
165 | |
166 #endif | |
167 | 162 |
168 return ngx_kqueue_set_event(ev, event, EV_ADD | flags); | 163 return ngx_kqueue_set_event(ev, event, EV_ADD | flags); |
169 } | 164 } |
170 | 165 |
171 | 166 |
172 int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags) | 167 static int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags) |
173 { | 168 { |
174 ngx_event_t *e; | 169 ngx_event_t *e; |
175 | 170 |
176 ev->active = 0; | 171 ev->active = 0; |
177 | 172 |
179 && ev->index < nchanges | 174 && ev->index < nchanges |
180 && (void *) ((uintptr_t) change_list[ev->index].udata & ~1) == ev) | 175 && (void *) ((uintptr_t) change_list[ev->index].udata & ~1) == ev) |
181 { | 176 { |
182 #if (NGX_DEBUG_EVENT) | 177 #if (NGX_DEBUG_EVENT) |
183 ngx_connection_t *c = (ngx_connection_t *) ev->data; | 178 ngx_connection_t *c = (ngx_connection_t *) ev->data; |
184 ngx_log_debug(ev->log, "kqueue del event: %d: ft:%d" _ c->fd _ event); | 179 ngx_log_debug(ev->log, "kqueue event deleted: %d: ft:%d" _ |
180 c->fd _ event); | |
185 #endif | 181 #endif |
186 | 182 |
187 /* if the event is still not passed to a kernel we will not pass it */ | 183 /* if the event is still not passed to a kernel we will not pass it */ |
188 | 184 |
189 if (ev->index < --nchanges) { | 185 if (ev->index < --nchanges) { |
205 | 201 |
206 return ngx_kqueue_set_event(ev, event, EV_DELETE); | 202 return ngx_kqueue_set_event(ev, event, EV_DELETE); |
207 } | 203 } |
208 | 204 |
209 | 205 |
210 int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags) | 206 static int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags) |
211 { | 207 { |
212 struct timespec ts; | 208 struct timespec ts; |
213 ngx_connection_t *c; | 209 ngx_connection_t *c; |
214 | 210 |
215 c = (ngx_connection_t *) ev->data; | 211 c = ev->data; |
216 | 212 |
217 #if (NGX_DEBUG_EVENT) | 213 #if (NGX_DEBUG_EVENT) |
218 ngx_log_debug(ev->log, "kqueue set event: %d: ft:%d f:%08x" _ | 214 ngx_log_debug(ev->log, "kqueue set event: %d: ft:%d f:%08x" _ |
219 c->fd _ filter _ flags); | 215 c->fd _ filter _ flags); |
220 #endif | 216 #endif |
221 | 217 |
222 if (nchanges >= KQUEUE_NCHANGES) { | 218 if (nchanges >= max_changes) { |
223 ngx_log_error(NGX_LOG_WARN, ev->log, 0, | 219 ngx_log_error(NGX_LOG_WARN, ev->log, 0, |
224 "kqueue change list is filled up"); | 220 "kqueue change list is filled up"); |
225 | 221 |
226 ts.tv_sec = 0; | 222 ts.tv_sec = 0; |
227 ts.tv_nsec = 0; | 223 ts.tv_nsec = 0; |
228 | 224 |
229 if (kevent(kq, change_list, nchanges, NULL, 0, &ts) == -1) { | 225 if (kevent(ngx_kqueue, change_list, nchanges, NULL, 0, &ts) == -1) { |
230 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent failed"); | 226 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "kevent failed"); |
231 return NGX_ERROR; | 227 return NGX_ERROR; |
232 } | 228 } |
233 | 229 |
234 nchanges = 0; | 230 nchanges = 0; |
263 | 259 |
264 return NGX_OK; | 260 return NGX_OK; |
265 } | 261 } |
266 | 262 |
267 | 263 |
268 int ngx_kqueue_process_events(ngx_log_t *log) | 264 static int ngx_kqueue_process_events(ngx_log_t *log) |
269 { | 265 { |
270 int events, instance, i; | 266 int events, instance, i; |
271 ngx_msec_t timer, delta; | 267 ngx_msec_t timer, delta; |
272 ngx_event_t *ev; | 268 ngx_event_t *ev; |
273 struct timeval tv; | 269 struct timeval tv; |
290 | 286 |
291 #if (NGX_DEBUG_EVENT) | 287 #if (NGX_DEBUG_EVENT) |
292 ngx_log_debug(log, "kevent timer: %d" _ timer); | 288 ngx_log_debug(log, "kevent timer: %d" _ timer); |
293 #endif | 289 #endif |
294 | 290 |
295 events = kevent(kq, change_list, nchanges, event_list, nevents, tp); | 291 events = kevent(ngx_kqueue, change_list, nchanges, event_list, nevents, tp); |
296 | 292 |
297 if (events == -1) { | 293 if (events == -1) { |
298 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "kevent failed"); | 294 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "kevent failed"); |
299 return NGX_ERROR; | 295 return NGX_ERROR; |
300 } | 296 } |
303 | 299 |
304 if (timer) { | 300 if (timer) { |
305 gettimeofday(&tv, NULL); | 301 gettimeofday(&tv, NULL); |
306 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; | 302 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; |
307 | 303 |
308 /* Expired timers must be deleted before the events processing | 304 /* The expired timers must be handled before a processing of the events |
309 because the new timers can be added during the processing */ | 305 because the new timers can be added during a processing */ |
310 | 306 |
311 ngx_event_expire_timers(delta); | 307 ngx_event_expire_timers(delta); |
312 | 308 |
313 } else { | 309 } else { |
314 if (events == 0) { | 310 if (events == 0) { |
368 if (event_list[i].flags & EV_EOF) { | 364 if (event_list[i].flags & EV_EOF) { |
369 ev->eof = 1; | 365 ev->eof = 1; |
370 ev->error = event_list[i].fflags; | 366 ev->error = event_list[i].fflags; |
371 } | 367 } |
372 | 368 |
373 if (ev->oneshot) { | 369 if (ev->oneshot && ev->timer_set) { |
374 ngx_del_timer(ev); | 370 ngx_del_timer(ev); |
371 ev->timer_set = 0; | |
375 } | 372 } |
376 | 373 |
377 /* fall through */ | 374 /* fall through */ |
378 | 375 |
379 case EVFILT_AIO: | 376 case EVFILT_AIO: |
390 } | 387 } |
391 } | 388 } |
392 | 389 |
393 return NGX_OK; | 390 return NGX_OK; |
394 } | 391 } |
392 | |
393 | |
394 static void *ngx_kqueue_create_conf(ngx_pool_t *pool) | |
395 { | |
396 ngx_kqueue_conf_t *kcf; | |
397 | |
398 ngx_test_null(kcf, ngx_palloc(pool, sizeof(ngx_kqueue_conf_t)), | |
399 NGX_CONF_ERROR); | |
400 | |
401 kcf->changes = NGX_CONF_UNSET; | |
402 kcf->events = NGX_CONF_UNSET; | |
403 | |
404 return kcf; | |
405 } | |
406 | |
407 | |
408 static char *ngx_kqueue_init_conf(ngx_pool_t *pool, void *conf) | |
409 { | |
410 ngx_kqueue_conf_t *kcf = conf; | |
411 | |
412 ngx_conf_init_value(kcf->changes, 512); | |
413 ngx_conf_init_value(kcf->events, 512); | |
414 | |
415 return NGX_CONF_OK; | |
416 } |