~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/event/modules/ngx_poll_module.c

Version: ~ [ nginx-0.8.20 ] ~ [ nginx-0.7.62 ] ~ [ nginx-0.6.39 ] ~

  1 
  2 /*
  3  * Copyright (C) Igor Sysoev
  4  */
  5 
  6 
  7 #include <ngx_config.h>
  8 #include <ngx_core.h>
  9 #include <ngx_event.h>
 10 
 11 
 12 static ngx_int_t ngx_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer);
 13 static void ngx_poll_done(ngx_cycle_t *cycle);
 14 static ngx_int_t ngx_poll_add_event(ngx_event_t *ev, ngx_int_t event,
 15     ngx_uint_t flags);
 16 static ngx_int_t ngx_poll_del_event(ngx_event_t *ev, ngx_int_t event,
 17     ngx_uint_t flags);
 18 static ngx_int_t ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
 19     ngx_uint_t flags);
 20 static char *ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf);
 21 
 22 
 23 static struct pollfd  *event_list;
 24 static ngx_int_t       nevents;
 25 
 26 
 27 static ngx_str_t    poll_name = ngx_string("poll");
 28 
 29 ngx_event_module_t  ngx_poll_module_ctx = {
 30     &poll_name,
 31     NULL,                                  /* create configuration */
 32     ngx_poll_init_conf,                    /* init configuration */
 33 
 34     {
 35         ngx_poll_add_event,                /* add an event */
 36         ngx_poll_del_event,                /* delete an event */
 37         ngx_poll_add_event,                /* enable an event */
 38         ngx_poll_del_event,                /* disable an event */
 39         NULL,                              /* add an connection */
 40         NULL,                              /* delete an connection */
 41         NULL,                              /* process the changes */
 42         ngx_poll_process_events,           /* process the events */
 43         ngx_poll_init,                     /* init the events */
 44         ngx_poll_done                      /* done the events */
 45     }
 46 
 47 };
 48 
 49 ngx_module_t  ngx_poll_module = {
 50     NGX_MODULE_V1,
 51     &ngx_poll_module_ctx,                  /* module context */
 52     NULL,                                  /* module directives */
 53     NGX_EVENT_MODULE,                      /* module type */
 54     NULL,                                  /* init master */
 55     NULL,                                  /* init module */
 56     NULL,                                  /* init process */
 57     NULL,                                  /* init thread */
 58     NULL,                                  /* exit thread */
 59     NULL,                                  /* exit process */
 60     NULL,                                  /* exit master */
 61     NGX_MODULE_V1_PADDING
 62 };
 63 
 64 
 65 
 66 static ngx_int_t
 67 ngx_poll_init(ngx_cycle_t *cycle, ngx_msec_t timer)
 68 {
 69     struct pollfd   *list;
 70 
 71     if (event_list == NULL) {
 72         nevents = 0;
 73     }
 74 
 75     if (ngx_process == NGX_PROCESS_WORKER
 76         || cycle->old_cycle == NULL
 77         || cycle->old_cycle->connection_n < cycle->connection_n)
 78     {
 79         list = ngx_alloc(sizeof(struct pollfd) * cycle->connection_n,
 80                          cycle->log);
 81         if (list == NULL) {
 82             return NGX_ERROR;
 83         }
 84 
 85         if (event_list) {
 86             ngx_memcpy(list, event_list, sizeof(ngx_event_t *) * nevents);
 87             ngx_free(event_list);
 88         }
 89 
 90         event_list = list;
 91     }
 92 
 93     ngx_io = ngx_os_io;
 94 
 95     ngx_event_actions = ngx_poll_module_ctx.actions;
 96 
 97     ngx_event_flags = NGX_USE_LEVEL_EVENT|NGX_USE_FD_EVENT;
 98 
 99     return NGX_OK;
100 }
101 
102 
103 static void
104 ngx_poll_done(ngx_cycle_t *cycle)
105 {
106     ngx_free(event_list);
107 
108     event_list = NULL;
109 }
110 
111 
112 static ngx_int_t
113 ngx_poll_add_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
114 {
115     ngx_event_t       *e;
116     ngx_connection_t  *c;
117 
118     c = ev->data;
119 
120     ev->active = 1;
121 
122     if (ev->index != NGX_INVALID_INDEX) {
123         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
124                       "poll event fd:%d ev:%i is already set", c->fd, event);
125         return NGX_OK;
126     }
127 
128     if (event == NGX_READ_EVENT) {
129         e = c->write;
130 #if (NGX_READ_EVENT != POLLIN)
131         event = POLLIN;
132 #endif
133 
134     } else {
135         e = c->read;
136 #if (NGX_WRITE_EVENT != POLLOUT)
137         event = POLLOUT;
138 #endif
139     }
140 
141     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
142                    "poll add event: fd:%d ev:%i", c->fd, event);
143 
144     if (e == NULL || e->index == NGX_INVALID_INDEX) {
145         event_list[nevents].fd = c->fd;
146         event_list[nevents].events = (short) event;
147         event_list[nevents].revents = 0;
148 
149         ev->index = nevents;
150         nevents++;
151 
152     } else {
153         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
154                        "poll add index: %i", e->index);
155 
156         event_list[e->index].events |= (short) event;
157         ev->index = e->index;
158     }
159 
160     return NGX_OK;
161 }
162 
163 
164 static ngx_int_t
165 ngx_poll_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags)
166 {
167     ngx_event_t       *e;
168     ngx_connection_t  *c;
169 
170     c = ev->data;
171 
172     ev->active = 0;
173 
174     if (ev->index == NGX_INVALID_INDEX) {
175         ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
176                       "poll event fd:%d ev:%i is already deleted",
177                       c->fd, event);
178         return NGX_OK;
179     }
180 
181     if (event == NGX_READ_EVENT) {
182         e = c->write;
183 #if (NGX_READ_EVENT != POLLIN)
184         event = POLLIN;
185 #endif
186 
187     } else {
188         e = c->read;
189 #if (NGX_WRITE_EVENT != POLLOUT)
190         event = POLLOUT;
191 #endif
192     }
193 
194     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
195                    "poll del event: fd:%d ev:%i", c->fd, event);
196 
197     if (e == NULL || e->index == NGX_INVALID_INDEX) {
198         nevents--;
199 
200         if (ev->index < (ngx_uint_t) nevents) {
201 
202             ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0,
203                            "index: copy event %ui to %i", nevents, ev->index);
204 
205             event_list[ev->index] = event_list[nevents];
206 
207             c = ngx_cycle->files[event_list[nevents].fd];
208 
209             if (c->fd == -1) {
210                 ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
211                               "unexpected last event");
212 
213             } else {
214                 if (c->read->index == (ngx_uint_t) nevents) {
215                     c->read->index = ev->index;
216                 }
217 
218                 if (c->write->index == (ngx_uint_t) nevents) {
219                     c->write->index = ev->index;
220                 }
221             }
222         }
223 
224     } else {
225         ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0,
226                        "poll del index: %i", e->index);
227 
228         event_list[e->index].events &= (short) ~event;
229     }
230 
231     ev->index = NGX_INVALID_INDEX;
232 
233     return NGX_OK;
234 }
235 
236 
237 static ngx_int_t
238 ngx_poll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags)
239 {
240     int                 ready, revents;
241     ngx_err_t           err;
242     ngx_int_t           i, nready;
243     ngx_uint_t          found, level;
244     ngx_event_t        *ev, **queue;
245     ngx_connection_t   *c;
246 
247     /* NGX_TIMER_INFINITE == INFTIM */
248 
249 #if (NGX_DEBUG0)
250     if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) {
251         for (i = 0; i < nevents; i++) {
252             ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
253                            "poll: %d: fd:%d ev:%04Xd",
254                            i, event_list[i].fd, event_list[i].events);
255         }
256     }
257 #endif
258 
259     ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "poll timer: %M", timer);
260 
261     ready = poll(event_list, (u_int) nevents, (int) timer);
262 
263     err = (ready == -1) ? ngx_errno : 0;
264 
265     if (flags & NGX_UPDATE_TIME) {
266         ngx_time_update(0, 0);
267     }
268 
269     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
270                    "poll ready %d of %d", ready, nevents);
271 
272     if (err) {
273         if (err == NGX_EINTR) {
274 
275             if (ngx_event_timer_alarm) {
276                 ngx_event_timer_alarm = 0;
277                 return NGX_OK;
278             }
279 
280             level = NGX_LOG_INFO;
281 
282         } else {
283             level = NGX_LOG_ALERT;
284         }
285 
286         ngx_log_error(level, cycle->log, err, "poll() failed");
287         return NGX_ERROR;
288     }
289 
290     if (ready == 0) {
291         if (timer != NGX_TIMER_INFINITE) {
292             return NGX_OK;
293         }
294 
295         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
296                       "poll() returned no events without timeout");
297         return NGX_ERROR;
298     }
299 
300     ngx_mutex_lock(ngx_posted_events_mutex);
301 
302     nready = 0;
303 
304     for (i = 0; i < nevents && ready; i++) {
305 
306         revents = event_list[i].revents;
307 
308 #if 1
309         ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
310                        "poll: %d: fd:%d ev:%04Xd rev:%04Xd",
311                        i, event_list[i].fd, event_list[i].events, revents);
312 #else
313         if (revents) {
314             ngx_log_debug4(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
315                            "poll: %d: fd:%d ev:%04Xd rev:%04Xd",
316                            i, event_list[i].fd, event_list[i].events, revents);
317         }
318 #endif
319 
320         if (revents & POLLNVAL) {
321             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
322                           "poll() error fd:%d ev:%04Xd rev:%04Xd",
323                           event_list[i].fd, event_list[i].events, revents);
324         }
325 
326         if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) {
327             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
328                           "strange poll() events fd:%d ev:%04Xd rev:%04Xd",
329                           event_list[i].fd, event_list[i].events, revents);
330         }
331 
332         if (event_list[i].fd == -1) {
333             /*
334              * the disabled event, a workaround for our possible bug,
335              * see the comment below
336              */
337             continue;
338         }
339 
340         c = ngx_cycle->files[event_list[i].fd];
341 
342         if (c->fd == -1) {
343             ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected event");
344 
345             /*
346              * it is certainly our fault and it should be investigated,
347              * in the meantime we disable this event to avoid a CPU spinning
348              */
349 
350             if (i == nevents - 1) {
351                 nevents--;
352             } else {
353                 event_list[i].fd = -1;
354             }
355 
356             continue;
357         }
358 
359         if ((revents & (POLLERR|POLLHUP|POLLNVAL))
360              && (revents & (POLLIN|POLLOUT)) == 0)
361         {
362             /*
363              * if the error events were returned without POLLIN or POLLOUT,
364              * then add these flags to handle the events at least in one
365              * active handler
366              */
367 
368             revents |= POLLIN|POLLOUT;
369         }
370 
371         found = 0;
372 
373         if (revents & POLLIN) {
374             found = 1;
375 
376             ev = c->read;
377 
378             if ((flags & NGX_POST_THREAD_EVENTS) && !ev->accept) {
379                 ev->posted_ready = 1;
380 
381             } else {
382                 ev->ready = 1;
383             }
384 
385             queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events:
386                                                    &ngx_posted_events);
387             ngx_locked_post_event(ev, queue);
388         }
389 
390         if (revents & POLLOUT) {
391             found = 1;
392             ev = c->write;
393 
394             if (flags & NGX_POST_THREAD_EVENTS) {
395                 ev->posted_ready = 1;
396 
397             } else {
398                 ev->ready = 1;
399             }
400 
401             ngx_locked_post_event(ev, &ngx_posted_events);
402         }
403 
404         if (found) {
405             ready--;
406             continue;
407         }
408     }
409 
410     ngx_mutex_unlock(ngx_posted_events_mutex);
411 
412     if (ready != 0) {
413         ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "poll ready != events");
414     }
415 
416     return nready;
417 }
418 
419 
420 static char *
421 ngx_poll_init_conf(ngx_cycle_t *cycle, void *conf)
422 {
423     ngx_event_conf_t  *ecf;
424 
425     ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module);
426 
427     if (ecf->use != ngx_poll_module.ctx_index) {
428         return NGX_CONF_OK;
429     }
430 
431 #if (NGX_THREADS)
432 
433     ngx_log_error(NGX_LOG_EMERG, cycle->log, 0,
434                   "poll() is not supported in the threaded mode");
435     return NGX_CONF_ERROR;
436 
437 #else
438 
439     return NGX_CONF_OK;
440 
441 #endif
442 }
443 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.