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