Mercurial > hg > nginx-quic
comparison src/event/modules/ngx_devpoll_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 | c14d7232b11f |
children | d5d4f3bba6f0 |
comparison
equal
deleted
inserted
replaced
38:2ffaa35fba42 | 39:83fa61cd3d2f |
---|---|
14 #if (USE_DEVPOLL) && !(HAVE_DEVPOLL) | 14 #if (USE_DEVPOLL) && !(HAVE_DEVPOLL) |
15 #error "/dev/poll is not supported on this platform" | 15 #error "/dev/poll is not supported on this platform" |
16 #endif | 16 #endif |
17 | 17 |
18 | 18 |
19 /* STUB */ | |
20 #define DEVPOLL_NCHANGES 512 | |
21 #define DEVPOLL_NEVENTS 512 | |
22 | |
19 /* should be per-thread */ | 23 /* should be per-thread */ |
20 static int dp; | 24 static int dp; |
21 static struct pollfd *change_list, *event_list; | 25 static struct pollfd *change_list, *event_list; |
22 static int nchanges, nevents; | 26 static unsigned int nchanges; |
27 static int nevents; | |
28 | |
29 static ngx_event_t **change_index; | |
23 | 30 |
24 static ngx_event_t timer_queue; | 31 static ngx_event_t timer_queue; |
25 /* */ | 32 /* */ |
26 | 33 |
27 | 34 |
28 int ngx_devpoll_init(int max_connections, ngx_log_t *log) | 35 int ngx_devpoll_init(int max_connections, ngx_log_t *log) |
29 { | 36 { |
30 int size; | 37 int change_size, event_size; |
31 | 38 |
32 size = sizeof(struct pollfd) * 512; | 39 nevents = DEVPOLL_NEVENTS; |
33 nchanges = 0; | 40 nchanges = 0; |
34 nevents = 512; | 41 change_size = sizeof(struct pollfd) * DEVPOLL_NCHANGES; |
42 event_size = sizeof(struct pollfd) * DEVPOLL_NEVENTS; | |
35 | 43 |
36 dp = open("/dev/poll", O_RDWR); | 44 dp = open("/dev/poll", O_RDWR); |
37 | 45 |
38 if (dp == -1) { | 46 if (dp == -1) { |
39 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "open(/dev/poll) failed"); | 47 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "open(/dev/poll) failed"); |
40 return NGX_ERROR; | 48 return NGX_ERROR; |
41 } | 49 } |
42 | 50 |
43 ngx_test_null(change_list, ngx_alloc(size, log), NGX_ERROR); | 51 ngx_test_null(change_list, ngx_alloc(change_size, log), NGX_ERROR); |
44 ngx_test_null(event_list, ngx_alloc(size, log), NGX_ERROR); | 52 ngx_test_null(event_list, ngx_alloc(event_size, log), NGX_ERROR); |
45 ngx_test_null(event_index, ngx_alloc(sizeof(ngx_event_t *) * nevents, log), | 53 ngx_test_null(change_index, |
54 ngx_alloc(sizeof(ngx_event_t *) * DEVPOLL_NCHANGES, log), | |
46 NGX_ERROR); | 55 NGX_ERROR); |
47 | 56 |
48 timer_queue.timer_prev = &timer_queue; | 57 timer_queue.timer_prev = &timer_queue; |
49 timer_queue.timer_next = &timer_queue; | 58 timer_queue.timer_next = &timer_queue; |
50 | 59 |
57 | 66 |
58 return NGX_OK; | 67 return NGX_OK; |
59 } | 68 } |
60 | 69 |
61 | 70 |
62 /* NOT READY */ | |
63 | |
64 int ngx_devpoll_add_event(ngx_event_t *ev, int event, u_int flags) | 71 int ngx_devpoll_add_event(ngx_event_t *ev, int event, u_int flags) |
65 { | 72 { |
66 ngx_event_t *e; | 73 #if (NGX_DEBUG_EVENT) |
67 ngx_connection_t *c; | 74 ngx_connection_t *c = (ngx_connection_t *) ev->data; |
68 | 75 #endif |
76 | |
77 #if (NGX_READ_EVENT != POLLIN) | |
78 if (event == NGX_READ_EVENT) { | |
79 event = POLLOUT; | |
80 #if (NGX_WRITE_EVENT != POLLOUT) | |
81 } else { | |
82 event = POLLIN; | |
83 #endif | |
84 } | |
85 #endif | |
86 | |
87 #if (NGX_DEBUG_EVENT) | |
69 c = (ngx_connection_t *) ev->data; | 88 c = (ngx_connection_t *) ev->data; |
70 | 89 ngx_log_debug(ev->log, "add event: %d:%d" _ c->fd _ event); |
90 #endif | |
91 | |
92 ev->active = 1; | |
71 ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0; | 93 ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0; |
94 | |
95 return ngx_devpoll_set_event(ev, event, 0); | |
96 } | |
97 | |
98 | |
99 int ngx_devpoll_del_event(ngx_event_t *ev, int event, u_int flags) | |
100 { | |
101 ngx_event_t *e; | |
102 | |
103 #if (NGX_DEBUG_EVENT) | |
104 ngx_connection_t *c = (ngx_connection_t *) ev->data; | |
105 ngx_log_debug(c->log, "del event: %d, %d" _ c->fd _ event); | |
106 #endif | |
107 | |
108 if (ngx_devpoll_set_event(ev, POLLREMOVE, flags) == NGX_ERROR) { | |
109 return NGX_ERROR; | |
110 } | |
111 | |
112 ev->active = 0; | |
113 | |
114 if (flags & NGX_CLOSE_EVENT) { | |
115 return NGX_OK; | |
116 } | |
72 | 117 |
73 if (event == NGX_READ_EVENT) { | 118 if (event == NGX_READ_EVENT) { |
74 e = c->write; | 119 e = c->write; |
75 #if (NGX_READ_EVENT != POLLIN) | 120 event = POLLOUT; |
76 event = POLLIN; | |
77 #endif | |
78 | 121 |
79 } else { | 122 } else { |
80 e = c->read; | 123 e = c->read; |
81 #if (NGX_WRITE_EVENT != POLLOUT) | 124 event = POLLIN; |
82 event = POLLOUT; | 125 } |
83 #endif | 126 |
84 } | 127 if (e) { |
85 | 128 return ngx_devpoll_set_event(e, event, 0); |
86 ngx_log_debug(ev->log, "poll fd:%d event:%d" _ c->fd _ event); | 129 } |
87 | 130 |
88 if (e == NULL || e->index == NGX_INVALID_INDEX) { | 131 return NGX_OK; |
89 event_list[nevents].fd = c->fd; | 132 } |
90 event_list[nevents].events = event; | 133 |
91 event_list[nevents].revents = 0; | 134 |
92 | 135 int ngx_devpoll_set_event(ngx_event_t *ev, int event, u_int flags) |
93 event_index[nevents] = ev; | |
94 ev->index = nevents; | |
95 nevents++; | |
96 | |
97 } else { | |
98 event_list[e->index].events |= event; | |
99 ev->index = e->index; | |
100 } | |
101 | |
102 return ngx_devpoll_set_event(ev, event, EV_ADD | flags); | |
103 } | |
104 | |
105 /* NOT READY */ | |
106 | |
107 int ngx_devpoll_del_event(ngx_event_t *ev, int event, u_int flags) | |
108 { | |
109 ngx_event_t *e; | |
110 | |
111 if (nchanges > 0 && ev->index < nchanges | |
112 && change_list[ev->index].udata == ev) | |
113 { | |
114 ngx_connection_t *cn = (ngx_connection_t *) ev->data; | |
115 ngx_log_debug(ev->log, "kqueue del event: %d: ft:%d" _ | |
116 cn->fd _ event); | |
117 | |
118 if (ev->index < --nchanges) { | |
119 e = (ngx_event_t *) change_list[nchanges].udata; | |
120 change_list[ev->index] = change_list[nchanges]; | |
121 e->index = ev->index; | |
122 } | |
123 | |
124 return NGX_OK; | |
125 } | |
126 | |
127 if (flags & NGX_CLOSE_EVENT) | |
128 return NGX_OK; | |
129 | |
130 return ngx_devpoll_set_event(ev, POLLREMOVE); | |
131 } | |
132 | |
133 /* NOT READY */ | |
134 | |
135 int ngx_devpoll_set_event(ngx_event_t *ev, int event) | |
136 { | 136 { |
137 int n; | 137 int n; |
138 ngx_connection_t *c; | 138 ngx_connection_t *c; |
139 | 139 |
140 c = (ngx_connection_t *) ev->data; | 140 c = (ngx_connection_t *) ev->data; |
141 | 141 |
142 ngx_log_debug(ev->log, "devpoll fd:%d event:%d" _ c->fd _ event); | 142 #if (NGX_DEBUG_EVENT) |
143 | 143 ngx_log_debug(ev->log, "devpoll fd:%d event:%d flush:%d" _ |
144 if (nchanges >= nevents) { | 144 c->fd _ event _ flags); |
145 #endif | |
146 | |
147 if (nchanges >= DEVPOLL_NCHANGES) { | |
145 ngx_log_error(NGX_LOG_WARN, ev->log, 0, | 148 ngx_log_error(NGX_LOG_WARN, ev->log, 0, |
146 "/dev/pool change list is filled up"); | 149 "/dev/pool change list is filled up"); |
147 | 150 |
148 n = nchanges * sizeof(struct pollfd); | 151 n = nchanges * sizeof(struct pollfd); |
149 if (write(dp, change_list, n) != n) { | 152 if (write(dp, change_list, n) != n) { |
150 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, | 153 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, |
151 "write(/dev/poll) failed"); | 154 "write(/dev/poll) failed"); |
152 return NGX_ERROR; | 155 return NGX_ERROR; |
153 } | 156 } |
154 | 157 |
155 nchanges = 0; | 158 nchanges = 0; |
156 } | 159 } |
157 | 160 |
158 event_list[nchanges].fd = c->fd; | 161 change_list[nchanges].fd = c->fd; |
159 event_list[nchanges].events = event; | 162 change_list[nchanges].events = event; |
160 event_list[nchanges].revents = 0; | 163 change_list[nchanges].revents = 0; |
161 | 164 |
162 event_index[nchanges] = ev; | 165 change_index[nchanges] = ev; |
163 ev->index = nchanges; | 166 ev->index = nchanges; |
164 | 167 |
165 /* | |
166 if (flags == EV_ADD) | |
167 ev->index = nchanges; | |
168 */ | |
169 | |
170 nchanges++; | 168 nchanges++; |
171 | 169 |
170 if (flags & NGX_CLOSE_EVENT) { | |
171 n = nchanges * sizeof(struct pollfd); | |
172 if (write(dp, change_list, n) != n) { | |
173 ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, | |
174 "write(/dev/poll) failed"); | |
175 return NGX_ERROR; | |
176 } | |
177 | |
178 nchanges = 0; | |
179 } | |
180 | |
172 return NGX_OK; | 181 return NGX_OK; |
173 } | 182 } |
174 | 183 |
175 | 184 |
176 int ngx_devpoll_process_events(ngx_log_t *log) | 185 int ngx_devpoll_process_events(ngx_log_t *log) |
177 { | 186 { |
178 int events, i; | 187 int events, n, i; |
179 u_int timer, delta; | 188 u_int timer, delta; |
180 ngx_event_t *ev; | 189 ngx_err_t err; |
181 struct dvpoll dvpoll; | 190 ngx_event_t *ev; |
182 struct timeval tv; | 191 ngx_connection_t *c; |
192 struct dvpoll dvpoll; | |
193 struct timeval tv; | |
183 | 194 |
184 if (timer_queue.timer_next != &timer_queue) { | 195 if (timer_queue.timer_next != &timer_queue) { |
185 timer = timer_queue.timer_next->timer_delta; | 196 timer = timer_queue.timer_next->timer_delta; |
186 #if 1 | |
187 gettimeofday(&tv, NULL); | 197 gettimeofday(&tv, NULL); |
188 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000; | 198 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000; |
189 #else | |
190 delta = ngx_msec(); | |
191 #endif | |
192 | 199 |
193 } else { | 200 } else { |
194 timer = INFTIM; | 201 timer = INFTIM; |
195 delta = 0; | 202 delta = 0; |
196 } | 203 } |
197 | 204 |
205 #if (NGX_DEBUG_EVENT) | |
198 ngx_log_debug(log, "devpoll timer: %d" _ timer); | 206 ngx_log_debug(log, "devpoll timer: %d" _ timer); |
207 #endif | |
199 | 208 |
200 n = nchanges * sizeof(struct pollfd); | 209 n = nchanges * sizeof(struct pollfd); |
201 if (write(dp, change_list, n) != n) { | 210 if (write(dp, change_list, n) != n) { |
202 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "write(/dev/poll) failed"); | 211 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "write(/dev/poll) failed"); |
203 return NGX_ERROR; | 212 return NGX_ERROR; |
214 } | 223 } |
215 | 224 |
216 nchanges = 0; | 225 nchanges = 0; |
217 | 226 |
218 if (timer != INFTIM) { | 227 if (timer != INFTIM) { |
219 #if 1 | |
220 gettimeofday(&tv, NULL); | 228 gettimeofday(&tv, NULL); |
221 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; | 229 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; |
222 #else | |
223 delta = ngx_msec() - delta; | |
224 #endif | |
225 | 230 |
226 } else { | 231 } else { |
227 ngx_assert((events != 0), return NGX_ERROR, log, | 232 if (events == 0) { |
228 "ioctl(DP_POLL) returns no events without timeout"); | 233 ngx_log_error(NGX_LOG_ALERT, log, 0, |
229 } | 234 "ioctl(DP_POLL) returns no events without timeout"); |
230 | 235 return NGX_ERROR; |
236 } | |
237 } | |
238 | |
239 #if (NGX_DEBUG_EVENT) | |
231 ngx_log_debug(log, "devpoll timer: %d, delta: %d" _ timer _ delta); | 240 ngx_log_debug(log, "devpoll timer: %d, delta: %d" _ timer _ delta); |
232 | 241 #endif |
233 if (timer != INFTIM) { | |
234 if (delta >= timer) { | |
235 for ( ;; ) { | |
236 ev = timer_queue.timer_next; | |
237 | |
238 if (ev == &timer_queue || delta < ev->timer_delta) | |
239 break; | |
240 | |
241 delta -= ev->timer_delta; | |
242 ngx_del_timer(ev); | |
243 ev->timedout = 1; | |
244 if (ev->event_handler(ev) == NGX_ERROR) | |
245 ev->close_handler(ev); | |
246 } | |
247 | |
248 } else { | |
249 timer_queue.timer_next->timer_delta -= delta; | |
250 } | |
251 } | |
252 | 242 |
253 for (i = 0; i < events; i++) { | 243 for (i = 0; i < events; i++) { |
254 | 244 |
245 #if (NGX_DEBUG_EVENT) | |
255 ngx_log_debug(log, "devpoll: %d: ev:%d rev:%d" _ | 246 ngx_log_debug(log, "devpoll: %d: ev:%d rev:%d" _ |
256 event_list[i].fd _ | 247 event_list[i].fd _ |
257 event_list[i].events _ event_list[i].revents); | 248 event_list[i].events _ event_list[i].revents); |
258 | 249 #endif |
250 | |
251 c = &ngx_connections[event_list[i].fd]; | |
259 | 252 |
260 if (event_list[i].revents & POLLIN) { | 253 if (event_list[i].revents & POLLIN) { |
254 if (!c->read->active) { | |
255 continue; | |
256 } | |
257 | |
261 c->read->ready = 1; | 258 c->read->ready = 1; |
262 | 259 |
263 if (c->read->oneshot) { | 260 if (c->read->oneshot) { |
264 ngx_del_timer(c->read); | 261 ngx_del_timer(c->read); |
265 ngx_select_del_event(c->read, NGX_READ_EVENT, 0); | 262 ngx_devpoll_del_event(c->read, NGX_READ_EVENT, 0); |
266 } | 263 } |
267 | 264 |
268 if (c->read->event_handler(c->read) == NGX_ERROR) { | 265 if (c->read->event_handler(c->read) == NGX_ERROR) { |
269 c->read->close_handler(c->read); | 266 c->read->close_handler(c->read); |
270 } | 267 } |
271 } | 268 } |
272 | 269 |
273 if (event_list[i].revents & POLLOUT) { | 270 if (event_list[i].revents & POLLOUT) { |
271 if (!c->write->active) { | |
272 continue; | |
273 } | |
274 | |
274 c->write->ready = 1; | 275 c->write->ready = 1; |
275 | 276 |
276 if (c->write->oneshot) { | 277 if (c->write->oneshot) { |
277 ngx_del_timer(c->write); | 278 ngx_del_timer(c->write); |
278 ngx_select_del_event(c->write, NGX_WRITE_EVENT, 0); | 279 ngx_devpoll_del_event(c->write, NGX_WRITE_EVENT, 0); |
279 } | 280 } |
280 | 281 |
281 if (c->write->event_handler(c->write) == NGX_ERROR) { | 282 if (c->write->event_handler(c->write) == NGX_ERROR) { |
282 c->write->close_handler(c->write); | 283 c->write->close_handler(c->write); |
283 } | 284 } |
284 } | 285 } |
285 | 286 |
286 if (event_list[i].revents & (POLLERR|POLLHUP|POLLNVAL)) { | 287 if (event_list[i].revents & (POLLERR|POLLHUP|POLLNVAL)) { |
287 ngx_log_error(NGX_LOG_ERR, log, ngx_errno, | 288 err = 0; |
289 if (event_list[i].revents & POLLNVAL) { | |
290 err = EBADF; | |
291 } | |
292 | |
293 ngx_log_error(NGX_LOG_ERR, log, err, | |
288 "ioctl(DP_POLL) error on %d:%d", | 294 "ioctl(DP_POLL) error on %d:%d", |
289 event_list[i].fd, event_list[i].revents); | 295 event_list[i].fd, event_list[i].revents); |
290 } | 296 } |
291 } | 297 } |
292 | 298 |
299 if (timer != INFTIM && timer_queue.timer_next != &timer_queue) { | |
300 if (delta >= timer_queue.timer_next->timer_delta) { | |
301 for ( ;; ) { | |
302 ev = timer_queue.timer_next; | |
303 | |
304 if (ev == &timer_queue || delta < ev->timer_delta) { | |
305 break; | |
306 } | |
307 | |
308 delta -= ev->timer_delta; | |
309 | |
310 ngx_del_timer(ev); | |
311 ev->timedout = 1; | |
312 if (ev->event_handler(ev) == NGX_ERROR) { | |
313 ev->close_handler(ev); | |
314 } | |
315 } | |
316 | |
317 } else { | |
318 timer_queue.timer_next->timer_delta -= delta; | |
319 } | |
320 } | |
321 | |
293 return NGX_OK; | 322 return NGX_OK; |
294 } | 323 } |
295 | 324 |
296 | 325 |
297 void ngx_devpoll_add_timer(ngx_event_t *ev, ngx_msec_t timer) | 326 void ngx_devpoll_add_timer(ngx_event_t *ev, ngx_msec_t timer) |
298 { | 327 { |
299 ngx_event_t *e; | 328 ngx_event_t *e; |
300 | 329 |
301 ngx_log_debug(ev->log, "set timer: %d" _ timer); | 330 #if (NGX_DEBUG_EVENT) |
302 | 331 ngx_connection_t *c = (ngx_connection_t *) ev->data; |
303 ngx_assert((!ev->timer_next && !ev->timer_prev), return, ev->log, | 332 ngx_log_debug(ev->log, "set timer: %d:%d" _ c->fd _ timer); |
304 "timer already set"); | 333 #endif |
334 | |
335 if (ev->timer_next || ev->timer_prev) { | |
336 ngx_log_error(NGX_LOG_ALERT, ev->log, 0, "timer already set"); | |
337 return; | |
338 } | |
305 | 339 |
306 for (e = timer_queue.timer_next; | 340 for (e = timer_queue.timer_next; |
307 e != &timer_queue && timer > e->timer_delta; | 341 e != &timer_queue && timer > e->timer_delta; |
308 e = e->timer_next) | 342 e = e->timer_next) |
343 { | |
309 timer -= e->timer_delta; | 344 timer -= e->timer_delta; |
345 } | |
310 | 346 |
311 ev->timer_delta = timer; | 347 ev->timer_delta = timer; |
312 | 348 |
313 ev->timer_next = e; | 349 ev->timer_next = e; |
314 ev->timer_prev = e->timer_prev; | 350 ev->timer_prev = e->timer_prev; |