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 }