Mercurial > hg > nginx
comparison src/event/modules/ngx_poll_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 | 2ffaa35fba42 |
children | b288069a8696 |
comparison
equal
deleted
inserted
replaced
38:2ffaa35fba42 | 39:83fa61cd3d2f |
---|---|
10 #include <ngx_poll_module.h> | 10 #include <ngx_poll_module.h> |
11 | 11 |
12 | 12 |
13 /* should be per-thread */ | 13 /* should be per-thread */ |
14 static struct pollfd *event_list; | 14 static struct pollfd *event_list; |
15 static int nevents; | 15 static unsigned int nevents; |
16 | 16 |
17 static ngx_event_t **event_index; | 17 static ngx_event_t **event_index; |
18 static ngx_event_t **ready_index; | |
18 static ngx_event_t timer_queue; | 19 static ngx_event_t timer_queue; |
19 /* */ | 20 /* */ |
20 | 21 |
21 int ngx_poll_init(int max_connections, ngx_log_t *log) | 22 int ngx_poll_init(int max_connections, ngx_log_t *log) |
22 { | 23 { |
24 ngx_alloc(sizeof(struct pollfd) * max_connections, log), | 25 ngx_alloc(sizeof(struct pollfd) * max_connections, log), |
25 NGX_ERROR); | 26 NGX_ERROR); |
26 | 27 |
27 ngx_test_null(event_index, | 28 ngx_test_null(event_index, |
28 ngx_alloc(sizeof(ngx_event_t *) * max_connections, log), | 29 ngx_alloc(sizeof(ngx_event_t *) * max_connections, log), |
30 NGX_ERROR); | |
31 | |
32 ngx_test_null(ready_index, | |
33 ngx_alloc(sizeof(ngx_event_t *) * 2 * max_connections, log), | |
29 NGX_ERROR); | 34 NGX_ERROR); |
30 | 35 |
31 nevents = 0; | 36 nevents = 0; |
32 | 37 |
33 timer_queue.timer_prev = &timer_queue; | 38 timer_queue.timer_prev = &timer_queue; |
41 return NGX_OK; | 46 return NGX_OK; |
42 } | 47 } |
43 | 48 |
44 int ngx_poll_add_event(ngx_event_t *ev, int event, u_int flags) | 49 int ngx_poll_add_event(ngx_event_t *ev, int event, u_int flags) |
45 { | 50 { |
46 ngx_event_t *e; | 51 ngx_event_t *e; |
47 ngx_connection_t *c; | 52 ngx_connection_t *c; |
48 | 53 |
49 c = (ngx_connection_t *) ev->data; | 54 c = (ngx_connection_t *) ev->data; |
50 | 55 |
56 ev->active = 1; | |
51 ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0; | 57 ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0; |
52 | 58 |
53 if (event == NGX_READ_EVENT) { | 59 if (event == NGX_READ_EVENT) { |
54 e = c->write; | 60 e = c->write; |
55 #if (NGX_READ_EVENT != POLLIN) | 61 #if (NGX_READ_EVENT != POLLIN) |
61 #if (NGX_WRITE_EVENT != POLLOUT) | 67 #if (NGX_WRITE_EVENT != POLLOUT) |
62 event = POLLOUT; | 68 event = POLLOUT; |
63 #endif | 69 #endif |
64 } | 70 } |
65 | 71 |
66 ngx_log_debug(ev->log, "poll fd:%d event:%d" _ c->fd _ event); | 72 #if (NGX_DEBUG_EVENT) |
73 ngx_log_debug(ev->log, "add event: %d:%d" _ c->fd _ event); | |
74 #endif | |
67 | 75 |
68 if (e == NULL || e->index == NGX_INVALID_INDEX) { | 76 if (e == NULL || e->index == NGX_INVALID_INDEX) { |
69 event_list[nevents].fd = c->fd; | 77 event_list[nevents].fd = c->fd; |
70 event_list[nevents].events = event; | 78 event_list[nevents].events = event; |
71 event_list[nevents].revents = 0; | 79 event_list[nevents].revents = 0; |
82 return NGX_OK; | 90 return NGX_OK; |
83 } | 91 } |
84 | 92 |
85 int ngx_poll_del_event(ngx_event_t *ev, int event, u_int flags) | 93 int ngx_poll_del_event(ngx_event_t *ev, int event, u_int flags) |
86 { | 94 { |
87 ngx_event_t *e; | 95 ngx_event_t *e; |
88 ngx_connection_t *c; | 96 ngx_connection_t *c; |
89 | 97 |
90 c = (ngx_connection_t *) ev->data; | 98 c = (ngx_connection_t *) ev->data; |
91 | 99 |
92 if (ev->index == NGX_INVALID_INDEX) | 100 if (ev->index == NGX_INVALID_INDEX) { |
93 return NGX_OK; | 101 return NGX_OK; |
102 } | |
94 | 103 |
95 if (event == NGX_READ_EVENT) { | 104 if (event == NGX_READ_EVENT) { |
96 e = c->write; | 105 e = c->write; |
97 #if (NGX_READ_EVENT != POLLIN) | 106 #if (NGX_READ_EVENT != POLLIN) |
98 event = POLLIN; | 107 event = POLLIN; |
103 #if (NGX_WRITE_EVENT != POLLOUT) | 112 #if (NGX_WRITE_EVENT != POLLOUT) |
104 event = POLLOUT; | 113 event = POLLOUT; |
105 #endif | 114 #endif |
106 } | 115 } |
107 | 116 |
117 #if (NGX_DEBUG_EVENT) | |
108 ngx_log_debug(c->log, "del event: %d, %d" _ c->fd _ event); | 118 ngx_log_debug(c->log, "del event: %d, %d" _ c->fd _ event); |
119 #endif | |
109 | 120 |
110 if (e == NULL || e->index == NGX_INVALID_INDEX) { | 121 if (e == NULL || e->index == NGX_INVALID_INDEX) { |
111 if (ev->index < --nevents) { | 122 if (ev->index < --nevents) { |
112 event_list[ev->index] = event_list[nevents]; | 123 event_list[ev->index] = event_list[nevents]; |
113 event_index[ev->index] = event_index[nevents]; | 124 event_index[ev->index] = event_index[nevents]; |
116 | 127 |
117 } else { | 128 } else { |
118 event_list[e->index].events &= ~event; | 129 event_list[e->index].events &= ~event; |
119 } | 130 } |
120 | 131 |
132 ev->active = 0; | |
121 ev->index = NGX_INVALID_INDEX; | 133 ev->index = NGX_INVALID_INDEX; |
122 | 134 |
123 return NGX_OK; | 135 return NGX_OK; |
124 } | 136 } |
125 | 137 |
126 int ngx_poll_process_events(ngx_log_t *log) | 138 int ngx_poll_process_events(ngx_log_t *log) |
127 { | 139 { |
128 int i, ready, found; | 140 int i, ready, nready, found; |
129 u_int timer, delta; | 141 u_int timer, delta; |
130 ngx_err_t err; | 142 ngx_err_t err; |
131 ngx_event_t *ev; | 143 ngx_event_t *ev; |
132 ngx_connection_t *c; | 144 ngx_connection_t *c; |
133 | 145 |
138 } else { | 150 } else { |
139 timer = INFTIM; | 151 timer = INFTIM; |
140 delta = 0; | 152 delta = 0; |
141 } | 153 } |
142 | 154 |
143 #if 1 | 155 #if (NGX_DEBUG_EVENT) |
144 /* DEBUG */ | |
145 for (i = 0; i < nevents; i++) { | 156 for (i = 0; i < nevents; i++) { |
146 ngx_log_debug(log, "poll: %d, %d" _ | 157 ngx_log_debug(log, "poll: %d, %d" _ |
147 event_list[i].fd _ event_list[i].events); | 158 event_list[i].fd _ event_list[i].events); |
148 } | 159 } |
149 #endif | |
150 | 160 |
151 ngx_log_debug(log, "poll timer: %d" _ timer); | 161 ngx_log_debug(log, "poll timer: %d" _ timer); |
162 #endif | |
152 | 163 |
153 if ((ready = poll(event_list, nevents, timer)) == -1) { | 164 if ((ready = poll(event_list, nevents, timer)) == -1) { |
154 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "poll() failed"); | 165 ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, "poll() failed"); |
155 return NGX_ERROR; | 166 return NGX_ERROR; |
156 } | 167 } |
159 | 170 |
160 if (timer != INFTIM) { | 171 if (timer != INFTIM) { |
161 delta = ngx_msec() - delta; | 172 delta = ngx_msec() - delta; |
162 | 173 |
163 } else { | 174 } else { |
164 ngx_assert((ready != 0), return NGX_ERROR, log, | 175 if (ready == 0) { |
165 "poll() returns no events without timeout"); | 176 ngx_log_error(NGX_LOG_ALERT, log, 0, |
166 } | 177 "poll() returns no events without timeout"); |
167 | 178 return NGX_ERROR; |
179 } | |
180 } | |
181 | |
182 #if (NGX_DEBUG_EVENT) | |
168 ngx_log_debug(log, "poll timer: %d, delta: %d" _ timer _ delta); | 183 ngx_log_debug(log, "poll timer: %d, delta: %d" _ timer _ delta); |
169 | 184 #endif |
170 if (timer != INFTIM) { | 185 |
171 if (delta >= timer) { | 186 nready = 0; |
187 | |
188 for (i = 0; i < nevents && ready; i++) { | |
189 c = &ngx_connections[event_list[i].fd]; | |
190 | |
191 #if (NGX_DEBUG_EVENT) | |
192 ngx_log_debug(log, "poll: fd:%d, ev:%d, rev:%d" _ | |
193 event_list[i].fd _ | |
194 event_list[i].events _ event_list[i].revents); | |
195 #endif | |
196 | |
197 found = 0; | |
198 | |
199 if (event_list[i].revents & POLLIN) { | |
200 found = 1; | |
201 ready_index[nready++] = c->read; | |
202 } | |
203 | |
204 if (event_list[i].revents & POLLOUT) { | |
205 found = 1; | |
206 ready_index[nready++] = c->write; | |
207 } | |
208 | |
209 if (event_list[i].revents & (POLLERR|POLLHUP|POLLNVAL)) { | |
210 found = 1; | |
211 | |
212 err = 0; | |
213 if (event_list[i].revents & POLLNVAL) { | |
214 err = EBADF; | |
215 } | |
216 | |
217 ngx_log_error(NGX_LOG_ERR, log, err, | |
218 "poll() error on %d:%d", | |
219 event_list[i].fd, event_list[i].revents); | |
220 } | |
221 | |
222 if (found) { | |
223 ready--; | |
224 } | |
225 } | |
226 | |
227 for (i = 0; i < nready; i++) { | |
228 ev = ready_index[i]; | |
229 | |
230 if (!ev->active) { | |
231 continue; | |
232 } | |
233 | |
234 ev->ready = 1; | |
235 | |
236 if (ev->oneshot) { | |
237 ngx_del_timer(ev); | |
238 | |
239 if (ev->write) { | |
240 ngx_poll_del_event(ev, NGX_WRITE_EVENT, 0); | |
241 } else { | |
242 ngx_poll_del_event(ev, NGX_READ_EVENT, 0); | |
243 } | |
244 } | |
245 | |
246 if (ev->event_handler(ev) == NGX_ERROR) { | |
247 ev->close_handler(ev); | |
248 } | |
249 } | |
250 | |
251 if (ready != 0) { | |
252 ngx_log_error(NGX_LOG_ALERT, log, 0, "poll ready != events"); | |
253 } | |
254 | |
255 if (timer != INFTIM && timer_queue.timer_next != &timer_queue) { | |
256 if (delta >= timer_queue.timer_next->timer_delta) { | |
172 for ( ;; ) { | 257 for ( ;; ) { |
173 ev = timer_queue.timer_next; | 258 ev = timer_queue.timer_next; |
174 | 259 |
175 if (ev == &timer_queue || delta < ev->timer_delta) { | 260 if (ev == &timer_queue || delta < ev->timer_delta) { |
176 break; | 261 break; |
177 } | 262 } |
178 | 263 |
179 delta -= ev->timer_delta; | 264 delta -= ev->timer_delta; |
265 | |
180 ngx_del_timer(ev); | 266 ngx_del_timer(ev); |
181 ev->timedout = 1; | 267 ev->timedout = 1; |
182 | |
183 if (ev->event_handler(ev) == NGX_ERROR) { | 268 if (ev->event_handler(ev) == NGX_ERROR) { |
184 ev->close_handler(ev); | 269 ev->close_handler(ev); |
185 } | 270 } |
186 } | 271 } |
187 | 272 |
188 } else { | 273 } else { |
189 timer_queue.timer_next->timer_delta -= delta; | 274 timer_queue.timer_next->timer_delta -= delta; |
190 } | 275 } |
191 } | 276 } |
192 | 277 |
193 for (i = 0; i < nevents && ready; i++) { | |
194 c = &ngx_connections[event_list[i].fd]; | |
195 | |
196 ngx_log_debug(log, "poll: fd:%d, ev:%d, rev:%d" _ | |
197 event_list[i].fd _ | |
198 event_list[i].events _ event_list[i].revents); | |
199 | |
200 found = 0; | |
201 | |
202 if (event_list[i].revents & POLLIN) { | |
203 found = 1; | |
204 c->read->ready = 1; | |
205 | |
206 if (c->read->oneshot) { | |
207 ngx_del_timer(c->read); | |
208 ngx_poll_del_event(c->read, NGX_READ_EVENT, 0); | |
209 } | |
210 | |
211 if (c->read->event_handler(c->read) == NGX_ERROR) { | |
212 c->read->close_handler(c->read); | |
213 } | |
214 } | |
215 | |
216 if (event_list[i].revents & POLLOUT) { | |
217 found = 1; | |
218 c->write->ready = 1; | |
219 | |
220 if (c->write->oneshot) { | |
221 ngx_del_timer(c->write); | |
222 ngx_poll_del_event(c->write, NGX_WRITE_EVENT, 0); | |
223 } | |
224 | |
225 if (c->write->event_handler(c->write) == NGX_ERROR) { | |
226 c->write->close_handler(c->write); | |
227 } | |
228 } | |
229 | |
230 if (event_list[i].revents & (POLLERR|POLLHUP|POLLNVAL)) { | |
231 found = 1; | |
232 | |
233 err = 0; | |
234 if (event_list[i].revents & POLLNVAL) { | |
235 err = EBADF; | |
236 } | |
237 | |
238 ngx_log_error(NGX_LOG_ERR, log, err, | |
239 "poll() error on %d:%d", | |
240 event_list[i].fd, event_list[i].revents); | |
241 } | |
242 | |
243 if (found) { | |
244 ready--; | |
245 } | |
246 } | |
247 | |
248 ngx_assert((ready == 0), /* void */ ; , log, "poll ready != nevents"); | |
249 | |
250 return NGX_OK; | 278 return NGX_OK; |
251 } | 279 } |
252 | 280 |
253 void ngx_poll_add_timer(ngx_event_t *ev, ngx_msec_t timer) | 281 void ngx_poll_add_timer(ngx_event_t *ev, ngx_msec_t timer) |
254 { | 282 { |
255 ngx_event_t *e; | 283 ngx_event_t *e; |
284 | |
285 #if (NGX_DEBUG_EVENT) | |
286 ngx_connection_t *c = (ngx_connection_t *) ev->data; | |
287 ngx_log_debug(ev->log, "set timer: %d:%d" _ c->fd _ timer); | |
288 #endif | |
289 | |
290 if (ev->timer_next || ev->timer_prev) { | |
291 ngx_log_error(NGX_LOG_ALERT, ev->log, 0, "timer already set"); | |
292 return; | |
293 } | |
256 | 294 |
257 for (e = timer_queue.timer_next; | 295 for (e = timer_queue.timer_next; |
258 e != &timer_queue && timer > e->timer_delta; | 296 e != &timer_queue && timer > e->timer_delta; |
259 e = e->timer_next) | 297 e = e->timer_next) |
298 { | |
260 timer -= e->timer_delta; | 299 timer -= e->timer_delta; |
300 } | |
261 | 301 |
262 ev->timer_delta = timer; | 302 ev->timer_delta = timer; |
263 | 303 |
264 ev->timer_next = e; | 304 ev->timer_next = e; |
265 ev->timer_prev = e->timer_prev; | 305 ev->timer_prev = e->timer_prev; |