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 }