Back to index

php5  5.3.10
poll.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Authors: Jerome Loyet <jerome@loyet.net>                             |
00016    +----------------------------------------------------------------------+
00017 */
00018 
00019 /* $Id$ */
00020 
00021 #include "../fpm_config.h"
00022 #include "../fpm_events.h"
00023 #include "../fpm.h"
00024 #include "../zlog.h"
00025 
00026 #if HAVE_POLL
00027 
00028 #include <poll.h>
00029 #include <errno.h>
00030 #include <string.h>
00031 
00032 static int fpm_event_poll_init(int max);
00033 static int fpm_event_poll_clean();
00034 static int fpm_event_poll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout);
00035 static int fpm_event_poll_add(struct fpm_event_s *ev);
00036 static int fpm_event_poll_remove(struct fpm_event_s *ev);
00037 
00038 static struct fpm_event_module_s poll_module = {
00039        .name = "poll",
00040        .support_edge_trigger = 0,
00041        .init = fpm_event_poll_init,
00042        .clean = fpm_event_poll_clean,
00043        .wait = fpm_event_poll_wait,
00044        .add = fpm_event_poll_add,
00045        .remove = fpm_event_poll_remove, 
00046 };
00047 
00048 static struct pollfd *pollfds = NULL;
00049 static struct pollfd *active_pollfds = NULL;
00050 static int npollfds = 0;
00051 static int next_free_slot = 0;
00052 #endif /* HAVE_POLL */
00053 
00054 /*
00055  * return the module configuration
00056  */
00057 struct fpm_event_module_s *fpm_event_poll_module() /* {{{ */
00058 {
00059 #if HAVE_POLL
00060        return &poll_module;
00061 #else
00062        return NULL;
00063 #endif /* HAVE_POLL */
00064 }
00065 /* }}} */
00066 
00067 #if HAVE_POLL
00068 
00069 /*
00070  * Init the module
00071  */
00072 static int fpm_event_poll_init(int max) /* {{{ */
00073 {
00074        int i;
00075 
00076        if (max < 1) {
00077               return 0;
00078        }
00079 
00080        /* alloc and clear pollfds */
00081        pollfds = malloc(sizeof(struct pollfd) * max);
00082        if (!pollfds) {
00083               zlog(ZLOG_ERROR, "poll: unable to allocate %d events", max);
00084               return -1;
00085        }
00086        memset(pollfds, 0, sizeof(struct pollfd) * max);
00087 
00088        /* set all fd to -1 in order to ensure it's not set */
00089        for (i = 0; i < max; i++) {
00090                      pollfds[i].fd = -1;
00091        }
00092 
00093        /* alloc and clear active_pollfds */
00094        active_pollfds = malloc(sizeof(struct pollfd) * max);
00095        if (!active_pollfds) {
00096               free(pollfds);
00097               zlog(ZLOG_ERROR, "poll: unable to allocate %d events", max);
00098               return -1;
00099        }
00100        memset(active_pollfds, 0, sizeof(struct pollfd) * max);
00101 
00102        /* save max */
00103        npollfds = max;
00104        return 0;
00105 }
00106 /* }}} */
00107 
00108 /*
00109  * Clean the module
00110  */
00111 static int fpm_event_poll_clean() /* {{{ */
00112 {
00113        /* free pollfds */
00114        if (pollfds) {
00115               free(pollfds);
00116               pollfds = NULL;
00117        }
00118 
00119        /* free active_pollfds */
00120        if (active_pollfds) {
00121               free(active_pollfds);
00122               active_pollfds = NULL;
00123        }
00124 
00125        npollfds = 0;
00126        return 0;
00127 }
00128 /* }}} */
00129 
00130 /*
00131  * wait for events or timeout
00132  */
00133 static int fpm_event_poll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout) /* {{{ */
00134 {
00135        int ret;
00136        struct fpm_event_queue_s *q;
00137 
00138        if (npollfds > 0) {
00139               /* copy pollfds because poll() alters it */
00140               memcpy(active_pollfds, pollfds, sizeof(struct pollfd) * npollfds);
00141        }
00142 
00143        /* wait for inconming event or timeout */
00144        ret = poll(active_pollfds, npollfds, timeout);
00145        if (ret == -1) {
00146 
00147               /* trigger error unless signal interrupt */
00148               if (errno != EINTR) {
00149                      zlog(ZLOG_WARNING, "poll() returns %d", errno);
00150                      return -1;
00151               }
00152        }
00153        
00154        /* events have been triggered */
00155        if (ret > 0) {
00156 
00157               /* trigger POLLIN events */
00158               q = queue;
00159               while (q) {
00160                      /* ensure ev->index is valid */
00161                      if (q->ev && q->ev->index >= 0 && q->ev->index < npollfds && q->ev->fd == active_pollfds[q->ev->index].fd) {
00162 
00163                             /* has the event has been triggered ? */
00164                             if (active_pollfds[q->ev->index].revents & POLLIN) {
00165 
00166                                    /* fire the event */
00167                                    fpm_event_fire(q->ev);
00168 
00169                                    /* sanity check */
00170                                    if (fpm_globals.parent_pid != getpid()) {
00171                                           return -2;
00172                                    }
00173                             }
00174                      }
00175                      q = q->next; /* iterate */
00176               }
00177        }
00178 
00179        return ret;
00180 }
00181 /* }}} */
00182 
00183 /*
00184  * Add a FD to the fd set
00185  */
00186 static int fpm_event_poll_add(struct fpm_event_s *ev) /* {{{ */
00187 {
00188        int i;
00189 
00190        /* do we have a direct free slot */
00191        if (pollfds[next_free_slot].fd == -1) {
00192               /* register the event */
00193               pollfds[next_free_slot].fd = ev->fd;
00194               pollfds[next_free_slot].events = POLLIN;
00195 
00196               /* remember the event place in the fd list and suppose next slot is free */
00197               ev->index = next_free_slot++;
00198               if (next_free_slot >= npollfds) {
00199                      next_free_slot = 0;
00200               }
00201               return 0;
00202        }
00203 
00204        /* let's search */
00205        for (i = 0; i < npollfds; i++) {
00206               if (pollfds[i].fd != -1) {
00207                      /* not free */
00208                      continue;
00209               }
00210 
00211               /* register the event */
00212               pollfds[i].fd = ev->fd;
00213               pollfds[i].events = POLLIN;
00214 
00215               /* remember the event place in the fd list and suppose next slot is free */
00216               ev->index = next_free_slot++;
00217               if (next_free_slot >= npollfds) {
00218                      next_free_slot = 0;
00219               }
00220               return 0;
00221        }
00222 
00223        zlog(ZLOG_ERROR, "poll: not enought space to add event (fd=%d)", ev->fd);
00224        return -1;
00225 }
00226 /* }}} */
00227 
00228 /*
00229  * Remove a FD from the fd set
00230  */
00231 static int fpm_event_poll_remove(struct fpm_event_s *ev) /* {{{ */
00232 {
00233        int i;
00234 
00235        /* do we have a direct access */
00236        if (ev->index >= 0 && ev->index < npollfds && pollfds[ev->index].fd == ev->fd) {
00237               /* remember this slot as free */
00238               next_free_slot = ev->index;
00239 
00240               /* clear event in pollfds */
00241               pollfds[ev->index].fd = -1;
00242               pollfds[ev->index].events = 0;
00243 
00244               /* mark the event as not registered */
00245               ev->index = -1;
00246 
00247               return 0;
00248        }
00249 
00250        /* let's search */
00251        for (i = 0; i < npollfds; i++) {
00252 
00253               if (pollfds[i].fd != ev->fd) {
00254                      /* not found */
00255                      continue;
00256               }
00257 
00258               /* remember this slot as free */
00259               next_free_slot = i;
00260 
00261               /* clear event in pollfds */
00262               pollfds[i].fd = -1;
00263               pollfds[i].events = 0;
00264 
00265               /* mark the event as not registered */
00266               ev->index = -1;
00267 
00268               return 0;
00269        }
00270 
00271        zlog(ZLOG_ERROR, "poll: unable to remove event: not found (fd=%d, index=%d)", ev->fd, ev->index);
00272        return -1;
00273 }
00274 /* }}} */
00275 
00276 #endif /* HAVE_POLL */