Mercurial > hg > nginx
comparison src/event/modules/ngx_select_module.c @ 0:4eff17414a43
nginx-0.0.1-2002-08-06-20:39:45 import
The first code that uses "ngx_" prefix, the previous one used "gx_" prefix.
At that point the code is not yet usable. The first draft ideas are dated
back to 23.10.2001.
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Tue, 06 Aug 2002 16:39:45 +0000 |
parents | |
children | 669801705ab1 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4eff17414a43 |
---|---|
1 | |
2 #include <ngx_config.h> | |
3 #include <ngx_types.h> | |
4 #include <ngx_log.h> | |
5 #include <ngx_time.h> | |
6 #include <ngx_connection.h> | |
7 #include <ngx_event.h> | |
8 #include <ngx_select_module.h> | |
9 | |
10 static fd_set master_read_fds; | |
11 static fd_set master_write_fds; | |
12 static fd_set work_read_fds; | |
13 static fd_set work_write_fds; | |
14 | |
15 #if (WIN32) | |
16 static int max_read; | |
17 static int max_write; | |
18 #else | |
19 static int max_fd; | |
20 #endif | |
21 | |
22 static ngx_event_t event_queue; | |
23 static ngx_event_t timer_queue; | |
24 | |
25 | |
26 static void ngx_add_timer(ngx_event_t *ev, u_int timer); | |
27 static void ngx_inline ngx_del_timer(ngx_event_t *ev); | |
28 | |
29 static fd_set *ngx_select_get_fd_set(ngx_socket_t fd, int event, | |
30 ngx_log_t *log); | |
31 | |
32 void ngx_select_init(int max_connections, ngx_log_t *log) | |
33 { | |
34 #if (WIN32) | |
35 if (max_connections > FD_SETSIZE) | |
36 ngx_log_error(NGX_LOG_EMERG, log, 0, | |
37 "ngx_select_init: maximum number of descriptors " | |
38 "supported by select() is %d", | |
39 FD_SETSIZE); | |
40 #else | |
41 if (max_connections >= FD_SETSIZE) | |
42 ngx_log_error(NGX_LOG_EMERG, log, 0, | |
43 "ngx_select_init: maximum descriptor number" | |
44 "supported by select() is %d", | |
45 FD_SETSIZE - 1); | |
46 #endif | |
47 | |
48 FD_ZERO(&master_read_fds); | |
49 FD_ZERO(&master_write_fds); | |
50 | |
51 event_queue.prev = &event_queue; | |
52 event_queue.next = &event_queue; | |
53 | |
54 timer_queue.timer_prev = &timer_queue; | |
55 timer_queue.timer_next = &timer_queue; | |
56 | |
57 ngx_event_actions.add = ngx_select_add_event; | |
58 ngx_event_actions.del = ngx_select_del_event; | |
59 ngx_event_actions.process = ngx_select_process_events; | |
60 | |
61 #if (WIN32) | |
62 max_read = max_write = 0; | |
63 #else | |
64 max_fd = -1; | |
65 #endif | |
66 } | |
67 | |
68 int ngx_select_add_event(ngx_event_t *ev, int event, u_int flags) | |
69 { | |
70 fd_set *fds; | |
71 ngx_connection_t *cn = (ngx_connection_t *) ev->data; | |
72 | |
73 if (event == NGX_TIMER_EVENT) { | |
74 ngx_add_timer(ev, flags); | |
75 return 0; | |
76 } | |
77 | |
78 ngx_assert((flags != NGX_ONESHOT_EVENT), return -1, ev->log, | |
79 "ngx_select_add_event: NGX_ONESHOT_EVENT is not supported"); | |
80 | |
81 fds = ngx_select_get_fd_set(cn->fd, event, ev->log); | |
82 if (fds == NULL) | |
83 return -1; | |
84 | |
85 ev->prev = &event_queue; | |
86 ev->next = event_queue.next; | |
87 event_queue.next->prev = ev; | |
88 event_queue.next = ev; | |
89 | |
90 FD_SET(cn->fd, fds); | |
91 | |
92 #if (WIN32) | |
93 switch (event) { | |
94 case NGX_READ_EVENT: | |
95 max_read++; | |
96 break; | |
97 case NGX_WRITE_EVENT: | |
98 max_write++; | |
99 break; | |
100 } | |
101 #else | |
102 if (max_fd != -1 && max_fd < cn->fd) | |
103 max_fd = cn->fd; | |
104 #endif | |
105 | |
106 return 0; | |
107 } | |
108 | |
109 int ngx_select_del_event(ngx_event_t *ev, int event) | |
110 { | |
111 fd_set *fds; | |
112 ngx_connection_t *cn = (ngx_connection_t *) ev->data; | |
113 | |
114 if (event == NGX_TIMER_EVENT) { | |
115 ngx_del_timer(ev); | |
116 return 0; | |
117 } | |
118 | |
119 fds = ngx_select_get_fd_set(cn->fd, event, ev->log); | |
120 if (fds == NULL) | |
121 return -1; | |
122 | |
123 if (ev->prev) | |
124 ev->prev->next = ev->next; | |
125 | |
126 if (ev->next) { | |
127 ev->next->prev = ev->prev; | |
128 ev->prev = NULL; | |
129 } | |
130 | |
131 if (ev->prev) | |
132 ev->next = NULL; | |
133 | |
134 FD_CLR(cn->fd, fds); | |
135 | |
136 #if (WIN32) | |
137 switch (event) { | |
138 case NGX_READ_EVENT: | |
139 max_read--; | |
140 break; | |
141 case NGX_WRITE_EVENT: | |
142 max_write--; | |
143 break; | |
144 } | |
145 #else | |
146 if (max_fd == cn->fd) | |
147 max_fd = -1; | |
148 #endif | |
149 | |
150 return 0; | |
151 } | |
152 | |
153 static fd_set *ngx_select_get_fd_set(ngx_socket_t fd, int event, ngx_log_t *log) | |
154 { | |
155 ngx_log_debug(log, "ngx_select_get_fd_set: %d %d" _ fd _ event); | |
156 | |
157 #if !(WIN32) | |
158 if (fd >= FD_SETSIZE) { | |
159 ngx_log_error(NGX_LOG_ERR, log, 0, | |
160 "ngx_select_get_event: maximum descriptor number" | |
161 "supported by select() is %d", | |
162 FD_SETSIZE - 1); | |
163 return NULL; | |
164 } | |
165 #endif | |
166 | |
167 switch (event) { | |
168 case NGX_READ_EVENT: | |
169 #if (WIN32) | |
170 if (max_read >= FD_SETSIZE) { | |
171 ngx_log_error(NGX_LOG_ERR, log, 0, | |
172 "ngx_select_get_event: maximum number of descriptors " | |
173 "supported by select() is %d", | |
174 FD_SETSIZE); | |
175 return NULL; | |
176 } | |
177 #endif | |
178 return &master_read_fds; | |
179 | |
180 case NGX_WRITE_EVENT: | |
181 #if (WIN32) | |
182 if (max_write >= FD_SETSIZE) { | |
183 ngx_log_error(NGX_LOG_ERR, log, 0, | |
184 "ngx_select_get_event: maximum number of descriptors " | |
185 "supported by select() is %d", | |
186 FD_SETSIZE); | |
187 return NULL; | |
188 } | |
189 #endif | |
190 return &master_write_fds; | |
191 | |
192 default: | |
193 ngx_assert(0, return NULL, log, | |
194 "ngx_select_get_fd_set: invalid event %d" _ event); | |
195 } | |
196 | |
197 return NULL; | |
198 } | |
199 | |
200 int ngx_select_process_events(ngx_log_t *log) | |
201 { | |
202 int ready, found; | |
203 u_int timer, delta; | |
204 ngx_event_t *ev, *nx; | |
205 ngx_connection_t *cn; | |
206 struct timeval tv, *tp; | |
207 | |
208 work_read_fds = master_read_fds; | |
209 work_write_fds = master_write_fds; | |
210 | |
211 if (timer_queue.timer_next != &timer_queue) { | |
212 timer = timer_queue.timer_next->timer_delta; | |
213 tv.tv_sec = timer / 1000; | |
214 tv.tv_usec = (timer % 1000) * 1000; | |
215 tp = &tv; | |
216 | |
217 delta = ngx_msec(); | |
218 | |
219 } else { | |
220 timer = 0; | |
221 tp = NULL; | |
222 delta = 0; | |
223 } | |
224 | |
225 #if !(WIN32) | |
226 if (max_fd == -1) { | |
227 for (ev = event_queue.next; ev != &event_queue; ev = ev->next) { | |
228 cn = (ngx_connection_t *) ev->data; | |
229 if (max_fd < cn->fd) | |
230 max_fd = cn->fd; | |
231 } | |
232 | |
233 ngx_log_debug(log, "ngx_select_process_events: change max_fd: %d" _ | |
234 max_fd); | |
235 } | |
236 #endif | |
237 | |
238 ngx_log_debug(log, "ngx_select_process_events: timer: %d" _ timer); | |
239 | |
240 #if (WIN32) | |
241 if ((ready = select(0, &work_read_fds, &work_write_fds, NULL, tp)) | |
242 #else | |
243 if ((ready = select(max_fd + 1, &work_read_fds, &work_write_fds, NULL, tp)) | |
244 #endif | |
245 == -1) { | |
246 ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno, | |
247 "ngx_select_process_events: select failed"); | |
248 return -1; | |
249 } | |
250 | |
251 ngx_log_debug(log, "ngx_select_process_events: ready %d" _ ready); | |
252 | |
253 if (timer) { | |
254 delta = ngx_msec() - delta; | |
255 | |
256 } else { | |
257 ngx_assert((ready != 0), return -1, log, | |
258 "ngx_select_process_events: " | |
259 "select returns no events without timeout"); | |
260 } | |
261 | |
262 ngx_log_debug(log, "ngx_select_process_events: " | |
263 "timer: %d, delta: %d" _ timer _ delta); | |
264 | |
265 if (timer) { | |
266 if (delta >= timer) { | |
267 for (ev = timer_queue.timer_next; | |
268 ev != &timer_queue && delta >= ev->timer_delta; | |
269 /* void */) | |
270 { | |
271 delta -= ev->timer_delta; | |
272 nx = ev->timer_next; | |
273 ngx_del_timer(ev); | |
274 if (ev->timer_handler(ev) == -1) | |
275 ev->close_handler(ev); | |
276 ev = nx; | |
277 } | |
278 | |
279 } else { | |
280 timer_queue.timer_next->timer_delta -= delta; | |
281 } | |
282 } | |
283 | |
284 for (ev = event_queue.next; ev != &event_queue; ev = ev->next) { | |
285 cn = (ngx_connection_t *) ev->data; | |
286 found = 0; | |
287 | |
288 if (ev->write) { | |
289 if (FD_ISSET(cn->fd, &work_write_fds)) { | |
290 ngx_log_debug(log, "ngx_select_process_events: write %d" _ | |
291 cn->fd); | |
292 found = 1; | |
293 } | |
294 | |
295 } else { | |
296 if (FD_ISSET(cn->fd, &work_read_fds)) { | |
297 ngx_log_debug(log, "ngx_select_process_events: read %d" _ | |
298 cn->fd); | |
299 found = 1; | |
300 } | |
301 } | |
302 | |
303 if (found) { | |
304 ev->ready = 1; | |
305 if (ev->event_handler(ev) == -1) | |
306 ev->close_handler(ev); | |
307 | |
308 ready--; | |
309 } | |
310 | |
311 } | |
312 | |
313 ngx_assert((ready == 0), return 0, log, | |
314 "ngx_select_process_events: ready != events"); | |
315 | |
316 return 0; | |
317 } | |
318 | |
319 static void ngx_add_timer(ngx_event_t *ev, u_int timer) | |
320 { | |
321 ngx_event_t *e; | |
322 | |
323 for (e = timer_queue.timer_next; | |
324 e != &timer_queue && timer > e->timer_delta; | |
325 e = e->timer_next) | |
326 timer -= e->timer_delta; | |
327 | |
328 ev->timer_delta = timer; | |
329 | |
330 ev->timer_next = e; | |
331 ev->timer_prev = e->timer_prev; | |
332 | |
333 e->timer_prev->timer_next = ev; | |
334 e->timer_prev = ev; | |
335 } | |
336 | |
337 static void ngx_inline ngx_del_timer(ngx_event_t *ev) | |
338 { | |
339 if (ev->timer_prev) | |
340 ev->timer_prev->timer_next = ev->timer_next; | |
341 | |
342 if (ev->timer_next) { | |
343 ev->timer_next->timer_prev = ev->timer_prev; | |
344 ev->timer_prev = NULL; | |
345 } | |
346 | |
347 if (ev->timer_prev) | |
348 ev->timer_next = NULL; | |
349 } |