root/sapi/fpm/fpm/events/devpoll.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fpm_event_devpoll_module
  2. fpm_event_devpoll_init
  3. fpm_event_devpoll_clean
  4. fpm_event_devpoll_wait
  5. fpm_event_devpoll_add
  6. fpm_event_devpoll_remove

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 The PHP Group                                |
   6    +----------------------------------------------------------------------+
   7    | This source file is subject to version 3.01 of the PHP license,      |
   8    | that is bundled with this package in the file LICENSE, and is        |
   9    | available through the world-wide-web at the following url:           |
  10    | http://www.php.net/license/3_01.txt                                  |
  11    | If you did not receive a copy of the PHP license and are unable to   |
  12    | obtain it through the world-wide-web, please send a note to          |
  13    | license@php.net so we can mail you a copy immediately.               |
  14    +----------------------------------------------------------------------+
  15    | Authors: Jerome Loyet <jerome@loyet.net>                             |
  16    +----------------------------------------------------------------------+
  17 */
  18 
  19 /* $Id$ */
  20 
  21 #include "../fpm_config.h"
  22 #include "../fpm_events.h"
  23 #include "../fpm.h"
  24 #include "../zlog.h"
  25 
  26 #if HAVE_DEVPOLL
  27 
  28 #include <sys/types.h>
  29 #include <sys/stat.h>
  30 #include <fcntl.h>
  31 #include <poll.h>
  32 #include <sys/devpoll.h>
  33 #include <errno.h>
  34 
  35 static int fpm_event_devpoll_init(int max);
  36 static int fpm_event_devpoll_clean();
  37 static int fpm_event_devpoll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout);
  38 static int fpm_event_devpoll_add(struct fpm_event_s *ev);
  39 static int fpm_event_devpoll_remove(struct fpm_event_s *ev);
  40 
  41 static struct fpm_event_module_s devpoll_module = {
  42         .name = "/dev/poll",
  43         .support_edge_trigger = 0,
  44         .init = fpm_event_devpoll_init,
  45         .clean = fpm_event_devpoll_clean,
  46         .wait = fpm_event_devpoll_wait,
  47         .add = fpm_event_devpoll_add,
  48         .remove = fpm_event_devpoll_remove,
  49 };
  50 
  51 int dpfd = -1;
  52 static struct pollfd *pollfds = NULL;
  53 static struct pollfd *active_pollfds = NULL;
  54 static int npollfds = 0;
  55 
  56 #endif /* HAVE_DEVPOLL */
  57 
  58 struct fpm_event_module_s *fpm_event_devpoll_module() /* {{{ */
  59 {
  60 #if HAVE_DEVPOLL
  61         return &devpoll_module;
  62 #else
  63         return NULL;
  64 #endif /* HAVE_DEVPOLL */
  65 }
  66 /* }}} */
  67 
  68 #if HAVE_DEVPOLL
  69 
  70 /*
  71  * Init module
  72  */
  73 static int fpm_event_devpoll_init(int max) /* {{{ */
  74 {
  75         int i;
  76 
  77         /* open /dev/poll for future usages */
  78         dpfd = open("/dev/poll", O_RDWR);
  79         if (dpfd < 0) {
  80                 zlog(ZLOG_ERROR, "Unable to open /dev/poll");
  81                 return -1;
  82         }
  83 
  84         if (max < 1) {
  85                 return 0;
  86         }
  87 
  88         /* alloc and clear pollfds */
  89         pollfds = malloc(sizeof(struct pollfd) * max);
  90         if (!pollfds) {
  91                 zlog(ZLOG_ERROR, "poll: unable to allocate %d events", max);
  92                 return -1;
  93         }
  94         memset(pollfds, 0, sizeof(struct pollfd) * max);
  95 
  96         /* set all fd to -1 in order to ensure it's not set */
  97         for (i = 0; i < max; i++) {
  98                 pollfds[i].fd = -1;
  99         }
 100 
 101         /* alloc and clear active_pollfds */
 102         active_pollfds = malloc(sizeof(struct pollfd) * max);
 103         if (!active_pollfds) {
 104                 free(pollfds);
 105                 zlog(ZLOG_ERROR, "poll: unable to allocate %d events", max);
 106                 return -1;
 107         }
 108         memset(active_pollfds, 0, sizeof(struct pollfd) * max);
 109 
 110         /* save max */
 111         npollfds = max;
 112 
 113         return 0;
 114 }
 115 /* }}} */
 116 
 117 /*
 118  * Clean the module
 119  */
 120 static int fpm_event_devpoll_clean() /* {{{ */
 121 {
 122         /* close /dev/poll if open */
 123         if (dpfd > -1) {
 124                 close(dpfd);
 125                 dpfd = -1;
 126         }
 127 
 128         /* free pollfds */
 129         if (pollfds) {
 130                 free(pollfds);
 131                 pollfds = NULL;
 132         }
 133 
 134         /* free active_pollfds */
 135         if (active_pollfds) {
 136                 free(active_pollfds);
 137                 active_pollfds = NULL;
 138         }
 139 
 140         npollfds = 0;
 141         return 0;
 142 }
 143 /* }}} */
 144 
 145 /*
 146  * wait for events or timeout
 147  */
 148 static int fpm_event_devpoll_wait(struct fpm_event_queue_s *queue, unsigned long int timeout) /* {{{ */
 149 {
 150         int ret, i;
 151         struct fpm_event_queue_s *q;
 152         struct dvpoll dopoll;
 153 
 154         /* setup /dev/poll */
 155         dopoll.dp_fds = active_pollfds;
 156         dopoll.dp_nfds = npollfds;
 157         dopoll.dp_timeout = (int)timeout;
 158 
 159         /* wait for inconming event or timeout */
 160         ret = ioctl(dpfd, DP_POLL, &dopoll);
 161 
 162         if (ret < 0) {
 163 
 164                 /* trigger error unless signal interrupt */
 165                 if (errno != EINTR) {
 166                         zlog(ZLOG_WARNING, "/dev/poll: ioctl() returns %d", errno);
 167                         return -1;
 168                 }
 169         }
 170 
 171         /* iterate throught triggered events */
 172         for (i = 0; i < ret; i++) {
 173 
 174                 /* find the corresponding event */
 175                 q = queue;
 176                 while (q) {
 177 
 178                         /* found */
 179                         if (q->ev && q->ev->fd == active_pollfds[i].fd) {
 180 
 181                                         /* fire the event */
 182                                         fpm_event_fire(q->ev);
 183 
 184                                         /* sanity check */
 185                                         if (fpm_globals.parent_pid != getpid()) {
 186                                                 return -2;
 187                                         }
 188                                 break; /* next triggered event */
 189                         }
 190                         q = q->next; /* iterate */
 191                 }
 192         }
 193 
 194         return ret;
 195 }
 196 /* }}} */
 197 
 198 /*
 199  * Add a FD from the fd set
 200  */
 201 static int fpm_event_devpoll_add(struct fpm_event_s *ev) /* {{{ */
 202 {
 203         struct pollfd pollfd;
 204 
 205         /* fill pollfd with event informations */
 206         pollfd.fd = ev->fd;
 207         pollfd.events = POLLIN;
 208         pollfd.revents = 0;
 209 
 210         /* add the event to the internal queue */
 211         if (write(dpfd, &pollfd, sizeof(struct pollfd)) != sizeof(struct pollfd)) {
 212                 zlog(ZLOG_ERROR, "/dev/poll: Unable to add the event in the internal queue");
 213                 return -1;
 214         }
 215 
 216         /* mark the event as registered */
 217         ev->index = ev->fd;
 218 
 219         return 0;
 220 }
 221 /* }}} */
 222 
 223 /*
 224  * Remove a FD from the fd set
 225  */
 226 static int fpm_event_devpoll_remove(struct fpm_event_s *ev) /* {{{ */
 227 {
 228         struct pollfd pollfd;
 229 
 230         /* fill pollfd with the same informations as fpm_event_devpoll_add */
 231         pollfd.fd = ev->fd;
 232         pollfd.events = POLLIN | POLLREMOVE;
 233         pollfd.revents = 0;
 234 
 235         /* add the event to the internal queue */
 236         if (write(dpfd, &pollfd, sizeof(struct pollfd)) != sizeof(struct pollfd)) {
 237                 zlog(ZLOG_ERROR, "/dev/poll: Unable to remove the event in the internal queue");
 238                 return -1;
 239         }
 240 
 241         /* mark the event as registered */
 242         ev->index = -1;
 243 
 244         return 0;
 245 }
 246 /* }}} */
 247 
 248 #endif /* HAVE_DEVPOLL */

/* [<][>][^][v][top][bottom][index][help] */