Mercurial > hg > nginx-quic
comparison src/event/modules/ngx_kqueue_module.c @ 0:4eff17414a43
nginx-0.0.1-2002-08-06-20:39:45 import
The first code that uses "ngx_" prefix, the previous one used "gx_" prefix.
At that point the code is not yet usable. The first draft ideas are dated
back to 23.10.2001.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 06 Aug 2002 16:39:45 +0000 |
parents | |
children | 669801705ab1 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4eff17414a43 |
---|---|
1 /* | |
2 * Copyright (C) 2002 Igor Sysoev, http://sysoev.ru | |
3 */ | |
4 | |
5 /* | |
6 NEED ? : unify change_list and event_list: | |
7 event_list = change_list; | |
8 */ | |
9 | |
10 #include <ngx_config.h> | |
11 #include <ngx_types.h> | |
12 #include <ngx_log.h> | |
13 #include <ngx_connection.h> | |
14 #include <ngx_event.h> | |
15 #include <ngx_kqueue_module.h> | |
16 | |
17 #if (USE_KQUEUE) && !(HAVE_KQUEUE) | |
18 #error "kqueue is not supported on this platform" | |
19 #endif | |
20 | |
21 static void ngx_add_timer(ngx_event_t *ev, u_int timer); | |
22 static void ngx_inline ngx_del_timer(ngx_event_t *ev); | |
23 | |
24 | |
25 static int kq; | |
26 static struct kevent *change_list, *event_list; | |
27 static int nchanges, nevents; | |
28 | |
29 static ngx_event_t timer_queue; | |
30 | |
31 void ngx_kqueue_init(int max_connections, ngx_log_t *log) | |
32 { | |
33 int size = sizeof(struct kevent) * 512; | |
34 | |
35 nchanges = 0; | |
36 nevents = 512; | |
37 | |
38 if ((kq = kqueue()) == -1) | |
39 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, | |
40 "ngx_kqueue_init: kqueue failed"); | |
41 | |
42 change_list = ngx_alloc(size, log); | |
43 event_list = ngx_alloc(size, log); | |
44 | |
45 timer_queue.timer_prev = &timer_queue; | |
46 timer_queue.timer_next = &timer_queue; | |
47 | |
48 #if !(USE_KQUEUE) | |
49 ngx_event_actions.add = ngx_kqueue_add_event; | |
50 ngx_event_actions.del = ngx_kqueue_del_event; | |
51 ngx_event_actions.process = ngx_kqueue_process_events; | |
52 #endif | |
53 | |
54 } | |
55 | |
56 int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags) | |
57 { | |
58 if (event == NGX_TIMER_EVENT) { | |
59 ngx_add_timer(ev, flags); | |
60 return 0; | |
61 } | |
62 | |
63 return ngx_kqueue_set_event(ev, event, EV_ADD | flags); | |
64 } | |
65 | |
66 int ngx_kqueue_del_event(ngx_event_t *ev, int event) | |
67 { | |
68 if (event == NGX_TIMER_EVENT) { | |
69 ngx_del_timer(ev); | |
70 return 0; | |
71 } | |
72 | |
73 return ngx_kqueue_set_event(ev, event, EV_DELETE); | |
74 } | |
75 | |
76 int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags) | |
77 { | |
78 struct timespec ts = { 0, 0 }; | |
79 ngx_connection_t *cn = (ngx_connection_t *) ev->data; | |
80 | |
81 ngx_log_debug(ev->log, "ngx_kqueue_set_event: %d: ft:%d f:%08x" _ | |
82 cn->fd _ filter _ flags); | |
83 | |
84 if (nchanges >= nevents) { | |
85 ngx_log_error(NGX_LOG_WARN, ev->log, 0, | |
86 "ngx_kqueue_set_event: change list is filled up"); | |
87 | |
88 if (kevent(kq, change_list, nchanges, NULL, 0, &ts) == -1) { | |
89 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, | |
90 "ngx_kqueue_set_event: kevent failed"); | |
91 return -1; | |
92 } | |
93 nchanges = 0; | |
94 } | |
95 | |
96 change_list[nchanges].ident = cn->fd; | |
97 change_list[nchanges].filter = filter; | |
98 change_list[nchanges].flags = flags; | |
99 change_list[nchanges].fflags = 0; | |
100 change_list[nchanges].data = 0; | |
101 change_list[nchanges].udata = ev; | |
102 nchanges++; | |
103 | |
104 return 0; | |
105 } | |
106 | |
107 int ngx_kqueue_process_events(ngx_log_t *log) | |
108 { | |
109 int events, i; | |
110 u_int timer = 0, delta = 0; | |
111 ngx_event_t *ev, *nx; | |
112 struct timeval tv; | |
113 struct timespec ts, *tp = NULL; | |
114 | |
115 if (timer_queue.timer_next != &timer_queue) { | |
116 timer = timer_queue.timer_next->timer_delta; | |
117 ts.tv_sec = timer / 1000; | |
118 ts.tv_nsec = (timer % 1000) * 1000000; | |
119 tp = &ts; | |
120 gettimeofday(&tv, NULL); | |
121 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000; | |
122 } | |
123 | |
124 ngx_log_debug(log, "ngx_kqueue_process_events: timer: %d" _ timer); | |
125 | |
126 if ((events = kevent(kq, change_list, nchanges, event_list, nevents, tp)) | |
127 == -1) { | |
128 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, | |
129 "ngx_kqueue_process_events: kevent failed"); | |
130 return -1; | |
131 } | |
132 | |
133 nchanges = 0; | |
134 | |
135 if (timer) { | |
136 gettimeofday(&tv, NULL); | |
137 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; | |
138 | |
139 } else { | |
140 ngx_assert((events != 0), return -1, log, | |
141 "ngx_kqueue_process_events: " | |
142 "kevent returns no events without timeout"); | |
143 } | |
144 | |
145 ngx_log_debug(log, "ngx_kqueue_process_events: " | |
146 "timer: %d, delta: %d" _ timer _ delta); | |
147 | |
148 if (timer) { | |
149 if (delta >= timer) { | |
150 for (ev = timer_queue.timer_next; | |
151 ev != &timer_queue && delta >= ev->timer_delta; | |
152 /* void */) | |
153 { | |
154 delta -= ev->timer_delta; | |
155 nx = ev->timer_next; | |
156 ngx_del_timer(ev); | |
157 if (ev->timer_handler(ev) == -1) | |
158 ev->close_handler(ev); | |
159 ev = nx; | |
160 } | |
161 | |
162 } else { | |
163 timer_queue.timer_next->timer_delta -= delta; | |
164 } | |
165 } | |
166 | |
167 for (i = 0; i < events; i++) { | |
168 | |
169 ngx_log_debug(log, "ngx_kqueue_process_events: kevent: " | |
170 "%d: ft:%d f:%08x ff:%08x d:%d ud:%08x" _ | |
171 event_list[i].ident _ event_list[i].filter _ | |
172 event_list[i].flags _ event_list[i].fflags _ | |
173 event_list[i].data _ event_list[i].udata); | |
174 | |
175 if (event_list[i].flags & EV_ERROR) { | |
176 ngx_log_error(NGX_LOG_ALERT, log, event_list[i].data, | |
177 "ngx_kqueue_process_events: kevent error"); | |
178 continue; | |
179 } | |
180 | |
181 ev = (ngx_event_t *) event_list[i].udata; | |
182 | |
183 switch (event_list[i].filter) { | |
184 | |
185 case EVFILT_READ: | |
186 case EVFILT_WRITE: | |
187 ev->ready = 1; | |
188 ev->available = event_list[i].data; | |
189 | |
190 if (event_list[i].flags & EV_EOF) { | |
191 ev->eof = 1; | |
192 ev->error = event_list[i].fflags; | |
193 } | |
194 | |
195 if (ev->event_handler(ev) == -1) | |
196 ev->close_handler(ev); | |
197 | |
198 break; | |
199 | |
200 default: | |
201 ngx_assert(0, /* void */, log, | |
202 "ngx_kqueue_process_events: unknown filter %d" _ | |
203 event_list[i].filter); | |
204 } | |
205 } | |
206 | |
207 return 0; | |
208 } | |
209 | |
210 static void ngx_add_timer(ngx_event_t *ev, u_int timer) | |
211 { | |
212 ngx_event_t *e; | |
213 | |
214 for (e = timer_queue.timer_next; | |
215 e != &timer_queue && timer > e->timer_delta; | |
216 e = e->timer_next) | |
217 timer -= e->timer_delta; | |
218 | |
219 ev->timer_delta = timer; | |
220 | |
221 ev->timer_next = e; | |
222 ev->timer_prev = e->timer_prev; | |
223 | |
224 e->timer_prev->timer_next = ev; | |
225 e->timer_prev = ev; | |
226 } | |
227 | |
228 static void ngx_inline ngx_del_timer(ngx_event_t *ev) | |
229 { | |
230 if (ev->timer_prev) | |
231 ev->timer_prev->timer_next = ev->timer_next; | |
232 | |
233 if (ev->timer_next) { | |
234 ev->timer_next->timer_prev = ev->timer_prev; | |
235 ev->timer_prev = NULL; | |
236 } | |
237 | |
238 if (ev->timer_prev) | |
239 ev->timer_next = NULL; | |
240 } |