Back to index

php5  5.3.10
epoll.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_EPOLL
00027 
00028 #include <sys/epoll.h>
00029 #include <errno.h>
00030 
00031 static int fpm_event_epoll_init(int max);
00032 static int fpm_event_epoll_clean();
00033 static int fpm_event_epoll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout);
00034 static int fpm_event_epoll_add(struct fpm_event_s *ev);
00035 static int fpm_event_epoll_remove(struct fpm_event_s *ev);
00036 
00037 static struct fpm_event_module_s epoll_module = {
00038        .name = "epoll",
00039        .support_edge_trigger = 1,
00040        .init = fpm_event_epoll_init,
00041        .clean = fpm_event_epoll_clean,
00042        .wait = fpm_event_epoll_wait,
00043        .add = fpm_event_epoll_add,
00044        .remove = fpm_event_epoll_remove, 
00045 };
00046 
00047 static struct epoll_event *epollfds = NULL;
00048 static int nepollfds = 0;
00049 static int epollfd = 0;
00050 
00051 #endif /* HAVE_EPOLL */
00052 
00053 struct fpm_event_module_s *fpm_event_epoll_module() /* {{{ */
00054 {
00055 #if HAVE_EPOLL
00056        return &epoll_module;
00057 #else
00058        return NULL;
00059 #endif /* HAVE_EPOLL */
00060 }
00061 /* }}} */
00062 
00063 #if HAVE_EPOLL
00064 
00065 /*
00066  * Init the module
00067  */
00068 static int fpm_event_epoll_init(int max) /* {{{ */
00069 {
00070        if (max < 1) {
00071               return 0;
00072        }
00073 
00074        /* init epoll */
00075        epollfd = epoll_create(max + 1);
00076        if (epollfd < 0) {
00077               zlog(ZLOG_ERROR, "epoll: unable to initialize");
00078               return -1;
00079        }
00080 
00081        /* allocate fds */
00082        epollfds = malloc(sizeof(struct epoll_event) * max);
00083        if (!epollfds) {
00084               zlog(ZLOG_ERROR, "epoll: unable to allocate %d events", max);
00085               return -1;
00086        }
00087        memset(epollfds, 0, sizeof(struct epoll_event) * max);
00088 
00089        /* save max */
00090        nepollfds = max;
00091 
00092        return 0;
00093 }
00094 /* }}} */
00095 
00096 /*
00097  * Clean the module
00098  */
00099 static int fpm_event_epoll_clean() /* {{{ */
00100 {
00101        /* free epollfds */
00102        if (epollfds) {
00103               free(epollfds);
00104               epollfds = NULL;
00105        }
00106 
00107        nepollfds = 0;
00108 
00109        return 0;
00110 }
00111 /* }}} */
00112 
00113 /*
00114  * wait for events or timeout
00115  */
00116 static int fpm_event_epoll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout) /* {{{ */
00117 {
00118        int ret, i;
00119 
00120        /* ensure we have a clean epoolfds before calling epoll_wait() */
00121        memset(epollfds, 0, sizeof(struct epoll_event) * nepollfds);
00122 
00123        /* wait for inconming event or timeout */
00124        ret = epoll_wait(epollfd, epollfds, nepollfds, timeout);
00125        if (ret == -1) {
00126 
00127               /* trigger error unless signal interrupt */
00128               if (errno != EINTR) {
00129                      zlog(ZLOG_WARNING, "epoll_wait() returns %d", errno);
00130                      return -1;
00131               }
00132        }
00133 
00134        /* events have been triggered, let's fire them */
00135        for (i = 0; i < ret; i++) {
00136 
00137               /* do we have a valid ev ptr ? */
00138               if (!epollfds[i].data.ptr) {
00139                      continue;
00140               }
00141 
00142               /* fire the event */
00143               fpm_event_fire((struct fpm_event_s *)epollfds[i].data.ptr);
00144 
00145               /* sanity check */
00146               if (fpm_globals.parent_pid != getpid()) {
00147                      return -2;
00148               }
00149        }
00150 
00151        return ret;
00152 }
00153 /* }}} */
00154 
00155 /*
00156  * Add a FD to the fd set
00157  */
00158 static int fpm_event_epoll_add(struct fpm_event_s *ev) /* {{{ */
00159 {
00160        struct epoll_event e;
00161 
00162        /* fill epoll struct */
00163        e.events = EPOLLIN;
00164        e.data.fd = ev->fd;
00165        e.data.ptr = (void *)ev;
00166 
00167        if (ev->flags & FPM_EV_EDGE) {
00168               e.events = e.events | EPOLLET;
00169        }
00170 
00171        /* add the event to epoll internal queue */
00172        if (epoll_ctl(epollfd, EPOLL_CTL_ADD, ev->fd, &e) == -1) {
00173               zlog(ZLOG_ERROR, "epoll: unable to add fd %d", ev->fd);
00174               return -1;
00175        }
00176 
00177        /* mark the event as registered */
00178        ev->index = ev->fd;
00179        return 0;
00180 }
00181 /* }}} */
00182 
00183 /*
00184  * Remove a FD from the fd set
00185  */
00186 static int fpm_event_epoll_remove(struct fpm_event_s *ev) /* {{{ */
00187 {
00188        struct epoll_event e;
00189 
00190        /* fill epoll struct the same way we did in fpm_event_epoll_add() */
00191        e.events = EPOLLIN;
00192        e.data.fd = ev->fd;
00193        e.data.ptr = (void *)ev;
00194 
00195        if (ev->flags & FPM_EV_EDGE) {
00196               e.events = e.events | EPOLLET;
00197        }
00198 
00199        /* remove the event from epoll internal queue */
00200        if (epoll_ctl(epollfd, EPOLL_CTL_DEL, ev->fd, &e) == -1) {
00201               zlog(ZLOG_ERROR, "epoll: unable to remove fd %d", ev->fd);
00202               return -1;
00203        }
00204 
00205        /* mark the event as not registered */
00206        ev->index = -1;
00207        return 0;
00208 }
00209 /* }}} */
00210 
00211 #endif /* HAVE_EPOLL */