Back to index

php5  5.3.10
devpoll.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_DEVPOLL
00027 
00028 #include <sys/types.h>
00029 #include <sys/stat.h>
00030 #include <fcntl.h>
00031 #include <poll.h>
00032 #include <sys/devpoll.h>
00033 #include <errno.h>
00034 
00035 static int fpm_event_devpoll_init(int max);
00036 static int fpm_event_devpoll_clean();
00037 static int fpm_event_devpoll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout);
00038 static int fpm_event_devpoll_add(struct fpm_event_s *ev);
00039 static int fpm_event_devpoll_remove(struct fpm_event_s *ev);
00040 
00041 static struct fpm_event_module_s devpoll_module = {
00042        .name = "/dev/poll",
00043        .support_edge_trigger = 0,
00044        .init = fpm_event_devpoll_init,
00045        .clean = fpm_event_devpoll_clean,
00046        .wait = fpm_event_devpoll_wait,
00047        .add = fpm_event_devpoll_add,
00048        .remove = fpm_event_devpoll_remove, 
00049 };
00050 
00051 int dpfd = -1;
00052 static struct pollfd *pollfds = NULL;
00053 static struct pollfd *active_pollfds = NULL;
00054 static int npollfds = 0;
00055 
00056 #endif /* HAVE_DEVPOLL */
00057 
00058 struct fpm_event_module_s *fpm_event_devpoll_module() /* {{{ */
00059 {
00060 #if HAVE_DEVPOLL
00061        return &devpoll_module;
00062 #else
00063        return NULL;
00064 #endif /* HAVE_DEVPOLL */
00065 }
00066 /* }}} */
00067 
00068 #if HAVE_DEVPOLL
00069 
00070 /*
00071  * Init module
00072  */
00073 static int fpm_event_devpoll_init(int max) /* {{{ */
00074 {
00075        int i;
00076 
00077        /* open /dev/poll for future usages */
00078        dpfd = open("/dev/poll", O_RDWR);
00079        if (dpfd < 0) {  
00080               zlog(ZLOG_ERROR, "Unable to open /dev/poll");
00081               return -1;
00082        }
00083 
00084        if (max < 1) {
00085               return 0;
00086        }
00087 
00088        /* alloc and clear pollfds */
00089        pollfds = malloc(sizeof(struct pollfd) * max);
00090        if (!pollfds) {
00091               zlog(ZLOG_ERROR, "poll: unable to allocate %d events", max);
00092               return -1;
00093        }
00094        memset(pollfds, 0, sizeof(struct pollfd) * max);
00095 
00096        /* set all fd to -1 in order to ensure it's not set */
00097        for (i = 0; i < max; i++) {
00098               pollfds[i].fd = -1;
00099        }
00100 
00101        /* alloc and clear active_pollfds */
00102        active_pollfds = malloc(sizeof(struct pollfd) * max);
00103        if (!active_pollfds) {
00104               free(pollfds);
00105               zlog(ZLOG_ERROR, "poll: unable to allocate %d events", max);
00106               return -1;
00107        }
00108        memset(active_pollfds, 0, sizeof(struct pollfd) * max);
00109 
00110        /* save max */
00111        npollfds = max;
00112 
00113        return 0;
00114 }
00115 /* }}} */
00116 
00117 /*
00118  * Clean the module
00119  */
00120 static int fpm_event_devpoll_clean() /* {{{ */
00121 {
00122        /* close /dev/poll if open */
00123        if (dpfd > -1) {  
00124               close(dpfd);
00125               dpfd = -1;
00126        }
00127 
00128        /* free pollfds */
00129        if (pollfds) {
00130               free(pollfds);
00131               pollfds = NULL;
00132        }
00133 
00134        /* free active_pollfds */
00135        if (active_pollfds) {
00136               free(active_pollfds);
00137               active_pollfds = NULL;
00138        }
00139 
00140        npollfds = 0;
00141        return 0;
00142 }
00143 /* }}} */
00144 
00145 /*
00146  * wait for events or timeout
00147  */
00148 static int fpm_event_devpoll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout) /* {{{ */
00149 {
00150        int ret, i;
00151        struct fpm_event_queue_s *q;
00152        struct dvpoll dopoll;
00153 
00154        /* setup /dev/poll */
00155        dopoll.dp_fds = active_pollfds;
00156        dopoll.dp_nfds = npollfds;
00157        dopoll.dp_timeout = (int)timeout;
00158 
00159        /* wait for inconming event or timeout */
00160        ret = ioctl(dpfd, DP_POLL, &dopoll);
00161 
00162        if (ret < 0) {
00163 
00164               /* trigger error unless signal interrupt */
00165               if (errno != EINTR) {
00166                      zlog(ZLOG_WARNING, "/dev/poll: ioctl() returns %d", errno);
00167                      return -1;
00168               }
00169        }
00170 
00171        /* iterate throught triggered events */
00172        for (i = 0; i < ret; i++) {
00173 
00174               /* find the corresponding event */
00175               q = queue;
00176               while (q) {
00177 
00178                      /* found */
00179                      if (q->ev && q->ev->fd == active_pollfds[i].fd) {  
00180 
00181                                    /* fire the event */
00182                                    fpm_event_fire(q->ev);
00183 
00184                                    /* sanity check */
00185                                    if (fpm_globals.parent_pid != getpid()) {
00186                                           return -2;
00187                                    }
00188                             break; /* next triggered event */
00189                      }
00190                      q = q->next; /* iterate */
00191               }
00192        }
00193 
00194        return ret;
00195 }
00196 /* }}} */
00197 
00198 /*
00199  * Add a FD from the fd set
00200  */
00201 static int fpm_event_devpoll_add(struct fpm_event_s *ev) /* {{{ */
00202 {
00203        struct pollfd pollfd;
00204 
00205        /* fill pollfd with event informations */
00206        pollfd.fd = ev->fd;
00207        pollfd.events = POLLIN;
00208        pollfd.revents = 0;
00209 
00210        /* add the event to the internal queue */
00211        if (write(dpfd, &pollfd, sizeof(struct pollfd)) != sizeof(struct pollfd)) {
00212               zlog(ZLOG_ERROR, "/dev/poll: Unable to add the event in the internal queue");
00213               return -1;
00214        }
00215 
00216        /* mark the event as registered */
00217        ev->index = ev->fd;
00218 
00219        return 0;
00220 }
00221 /* }}} */
00222 
00223 /*
00224  * Remove a FD from the fd set
00225  */
00226 static int fpm_event_devpoll_remove(struct fpm_event_s *ev) /* {{{ */
00227 {
00228        struct pollfd pollfd;
00229 
00230        /* fill pollfd with the same informations as fpm_event_devpoll_add */
00231        pollfd.fd = ev->fd;
00232        pollfd.events = POLLIN | POLLREMOVE;
00233        pollfd.revents = 0;
00234 
00235        /* add the event to the internal queue */
00236        if (write(dpfd, &pollfd, sizeof(struct pollfd)) != sizeof(struct pollfd)) {
00237               zlog(ZLOG_ERROR, "/dev/poll: Unable to remove the event in the internal queue");
00238               return -1;
00239        }
00240 
00241        /* mark the event as registered */
00242        ev->index = -1;
00243 
00244        return 0;
00245 }
00246 /* }}} */
00247 
00248 #endif /* HAVE_DEVPOLL */