Mercurial > hg > nginx
comparison src/event/modules/ngx_devpoll_module.c @ 36:c14d7232b11f
nginx-0.0.1-2002-12-23-09:29:22 import
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Mon, 23 Dec 2002 06:29:22 +0000 |
parents | |
children | 83fa61cd3d2f |
comparison
equal
deleted
inserted
replaced
35:79c1fce18e71 | 36:c14d7232b11f |
---|---|
1 /* | |
2 * Copyright (C) 2002 Igor Sysoev, http://sysoev.ru | |
3 */ | |
4 | |
5 | |
6 #include <ngx_config.h> | |
7 #include <ngx_core.h> | |
8 #include <ngx_types.h> | |
9 #include <ngx_log.h> | |
10 #include <ngx_connection.h> | |
11 #include <ngx_event.h> | |
12 #include <ngx_devpoll_module.h> | |
13 | |
14 #if (USE_DEVPOLL) && !(HAVE_DEVPOLL) | |
15 #error "/dev/poll is not supported on this platform" | |
16 #endif | |
17 | |
18 | |
19 /* should be per-thread */ | |
20 static int dp; | |
21 static struct pollfd *change_list, *event_list; | |
22 static int nchanges, nevents; | |
23 | |
24 static ngx_event_t timer_queue; | |
25 /* */ | |
26 | |
27 | |
28 int ngx_devpoll_init(int max_connections, ngx_log_t *log) | |
29 { | |
30 int size; | |
31 | |
32 size = sizeof(struct pollfd) * 512; | |
33 nchanges = 0; | |
34 nevents = 512; | |
35 | |
36 dp = open("/dev/poll", O_RDWR); | |
37 | |
38 if (dp == -1) { | |
39 ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "open(/dev/poll) failed"); | |
40 return NGX_ERROR; | |
41 } | |
42 | |
43 ngx_test_null(change_list, ngx_alloc(size, log), NGX_ERROR); | |
44 ngx_test_null(event_list, ngx_alloc(size, log), NGX_ERROR); | |
45 ngx_test_null(event_index, ngx_alloc(sizeof(ngx_event_t *) * nevents, log), | |
46 NGX_ERROR); | |
47 | |
48 timer_queue.timer_prev = &timer_queue; | |
49 timer_queue.timer_next = &timer_queue; | |
50 | |
51 #if !(USE_DEVPOLL) | |
52 ngx_event_actions.add = ngx_devpoll_add_event; | |
53 ngx_event_actions.del = ngx_devpoll_del_event; | |
54 ngx_event_actions.timer = ngx_devpoll_add_timer; | |
55 ngx_event_actions.process = ngx_devpoll_process_events; | |
56 #endif | |
57 | |
58 return NGX_OK; | |
59 } | |
60 | |
61 | |
62 /* NOT READY */ | |
63 | |
64 int ngx_devpoll_add_event(ngx_event_t *ev, int event, u_int flags) | |
65 { | |
66 ngx_event_t *e; | |
67 ngx_connection_t *c; | |
68 | |
69 c = (ngx_connection_t *) ev->data; | |
70 | |
71 ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0; | |
72 | |
73 if (event == NGX_READ_EVENT) { | |
74 e = c->write; | |
75 #if (NGX_READ_EVENT != POLLIN) | |
76 event = POLLIN; | |
77 #endif | |
78 | |
79 } else { | |
80 e = c->read; | |
81 #if (NGX_WRITE_EVENT != POLLOUT) | |
82 event = POLLOUT; | |
83 #endif | |
84 } | |
85 | |
86 ngx_log_debug(ev->log, "poll fd:%d event:%d" _ c->fd _ event); | |
87 | |
88 if (e == NULL || e->index == NGX_INVALID_INDEX) { | |
89 event_list[nevents].fd = c->fd; | |
90 event_list[nevents].events = event; | |
91 event_list[nevents].revents = 0; | |
92 | |
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 { | |
137 int n; | |
138 ngx_connection_t *c; | |
139 | |
140 c = (ngx_connection_t *) ev->data; | |
141 | |
142 ngx_log_debug(ev->log, "devpoll fd:%d event:%d" _ c->fd _ event); | |
143 | |
144 if (nchanges >= nevents) { | |
145 ngx_log_error(NGX_LOG_WARN, ev->log, 0, | |
146 "/dev/pool change list is filled up"); | |
147 | |
148 n = nchanges * sizeof(struct pollfd); | |
149 if (write(dp, change_list, n) != n) { | |
150 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, | |
151 "write(/dev/poll) failed"); | |
152 return NGX_ERROR; | |
153 } | |
154 | |
155 nchanges = 0; | |
156 } | |
157 | |
158 event_list[nchanges].fd = c->fd; | |
159 event_list[nchanges].events = event; | |
160 event_list[nchanges].revents = 0; | |
161 | |
162 event_index[nchanges] = ev; | |
163 ev->index = nchanges; | |
164 | |
165 /* | |
166 if (flags == EV_ADD) | |
167 ev->index = nchanges; | |
168 */ | |
169 | |
170 nchanges++; | |
171 | |
172 return NGX_OK; | |
173 } | |
174 | |
175 | |
176 int ngx_devpoll_process_events(ngx_log_t *log) | |
177 { | |
178 int events, i; | |
179 u_int timer, delta; | |
180 ngx_event_t *ev; | |
181 struct dvpoll dvpoll; | |
182 struct timeval tv; | |
183 | |
184 if (timer_queue.timer_next != &timer_queue) { | |
185 timer = timer_queue.timer_next->timer_delta; | |
186 #if 1 | |
187 gettimeofday(&tv, NULL); | |
188 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000; | |
189 #else | |
190 delta = ngx_msec(); | |
191 #endif | |
192 | |
193 } else { | |
194 timer = INFTIM; | |
195 delta = 0; | |
196 } | |
197 | |
198 ngx_log_debug(log, "devpoll timer: %d" _ timer); | |
199 | |
200 n = nchanges * sizeof(struct pollfd); | |
201 if (write(dp, change_list, n) != n) { | |
202 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "write(/dev/poll) failed"); | |
203 return NGX_ERROR; | |
204 } | |
205 | |
206 dvpoll.dp_fds = event_list; | |
207 dvpoll.dp_nfds = nevents; | |
208 dvpoll.dp_timeout = timer; | |
209 events = ioctl(dp, DP_POLL, &dvpoll); | |
210 | |
211 if (events == -1) { | |
212 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "ioctl(DP_POLL) failed"); | |
213 return NGX_ERROR; | |
214 } | |
215 | |
216 nchanges = 0; | |
217 | |
218 if (timer != INFTIM) { | |
219 #if 1 | |
220 gettimeofday(&tv, NULL); | |
221 delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; | |
222 #else | |
223 delta = ngx_msec() - delta; | |
224 #endif | |
225 | |
226 } else { | |
227 ngx_assert((events != 0), return NGX_ERROR, log, | |
228 "ioctl(DP_POLL) returns no events without timeout"); | |
229 } | |
230 | |
231 ngx_log_debug(log, "devpoll timer: %d, delta: %d" _ timer _ delta); | |
232 | |
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 | |
253 for (i = 0; i < events; i++) { | |
254 | |
255 ngx_log_debug(log, "devpoll: %d: ev:%d rev:%d" _ | |
256 event_list[i].fd _ | |
257 event_list[i].events _ event_list[i].revents); | |
258 | |
259 | |
260 if (event_list[i].revents & POLLIN) { | |
261 c->read->ready = 1; | |
262 | |
263 if (c->read->oneshot) { | |
264 ngx_del_timer(c->read); | |
265 ngx_select_del_event(c->read, NGX_READ_EVENT, 0); | |
266 } | |
267 | |
268 if (c->read->event_handler(c->read) == NGX_ERROR) { | |
269 c->read->close_handler(c->read); | |
270 } | |
271 } | |
272 | |
273 if (event_list[i].revents & POLLOUT) { | |
274 c->write->ready = 1; | |
275 | |
276 if (c->write->oneshot) { | |
277 ngx_del_timer(c->write); | |
278 ngx_select_del_event(c->write, NGX_WRITE_EVENT, 0); | |
279 } | |
280 | |
281 if (c->write->event_handler(c->write) == NGX_ERROR) { | |
282 c->write->close_handler(c->write); | |
283 } | |
284 } | |
285 | |
286 if (event_list[i].revents & (POLLERR|POLLHUP|POLLNVAL)) { | |
287 ngx_log_error(NGX_LOG_ERR, log, ngx_errno, | |
288 "ioctl(DP_POLL) error on %d:%d", | |
289 event_list[i].fd, event_list[i].revents); | |
290 } | |
291 } | |
292 | |
293 return NGX_OK; | |
294 } | |
295 | |
296 | |
297 void ngx_devpoll_add_timer(ngx_event_t *ev, ngx_msec_t timer) | |
298 { | |
299 ngx_event_t *e; | |
300 | |
301 ngx_log_debug(ev->log, "set timer: %d" _ timer); | |
302 | |
303 ngx_assert((!ev->timer_next && !ev->timer_prev), return, ev->log, | |
304 "timer already set"); | |
305 | |
306 for (e = timer_queue.timer_next; | |
307 e != &timer_queue && timer > e->timer_delta; | |
308 e = e->timer_next) | |
309 timer -= e->timer_delta; | |
310 | |
311 ev->timer_delta = timer; | |
312 | |
313 ev->timer_next = e; | |
314 ev->timer_prev = e->timer_prev; | |
315 | |
316 e->timer_prev->timer_next = ev; | |
317 e->timer_prev = ev; | |
318 } |