root/sapi/fpm/fpm/events/kqueue.c

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

DEFINITIONS

This source file includes following definitions.
  1. fpm_event_kqueue_module
  2. fpm_event_kqueue_init
  3. fpm_event_kqueue_clean
  4. fpm_event_kqueue_wait
  5. fpm_event_kqueue_add
  6. fpm_event_kqueue_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_KQUEUE
  27 
  28 #include <sys/types.h>
  29 #include <sys/event.h>
  30 #include <sys/time.h>
  31 
  32 #include <errno.h>
  33 
  34 static int fpm_event_kqueue_init(int max);
  35 static int fpm_event_kqueue_clean();
  36 static int fpm_event_kqueue_wait(struct fpm_event_queue_s *queue, unsigned long int timeout);
  37 static int fpm_event_kqueue_add(struct fpm_event_s *ev);
  38 static int fpm_event_kqueue_remove(struct fpm_event_s *ev);
  39 
  40 static struct fpm_event_module_s kqueue_module = {
  41         .name = "kqueue",
  42         .support_edge_trigger = 1,
  43         .init = fpm_event_kqueue_init,
  44         .clean = fpm_event_kqueue_clean,
  45         .wait = fpm_event_kqueue_wait,
  46         .add = fpm_event_kqueue_add,
  47         .remove = fpm_event_kqueue_remove,
  48 };
  49 
  50 static struct kevent *kevents = NULL;
  51 static int nkevents = 0;
  52 static int kfd = 0;
  53 
  54 #endif /* HAVE_KQUEUE */
  55 
  56 /*
  57  * Return the module configuration
  58  */
  59 struct fpm_event_module_s *fpm_event_kqueue_module() /* {{{ */
  60 {
  61 #if HAVE_KQUEUE
  62         return &kqueue_module;
  63 #else
  64         return NULL;
  65 #endif /* HAVE_KQUEUE */
  66 }
  67 /* }}} */
  68 
  69 #if HAVE_KQUEUE
  70 
  71 /*
  72  * init kqueue and stuff
  73  */
  74 static int fpm_event_kqueue_init(int max) /* {{{ */
  75 {
  76         if (max < 1) {
  77                 return 0;
  78         }
  79 
  80         kfd = kqueue();
  81         if (kfd < 0) {
  82                 zlog(ZLOG_ERROR, "kqueue: unable to initialize");
  83                 return -1;
  84         }
  85 
  86         kevents = malloc(sizeof(struct kevent) * max);
  87         if (!kevents) {
  88                 zlog(ZLOG_ERROR, "epoll: unable to allocate %d events", max);
  89                 return -1;
  90         }
  91 
  92         memset(kevents, 0, sizeof(struct kevent) * max);
  93 
  94         nkevents = max;
  95 
  96         return 0;
  97 }
  98 /* }}} */
  99 
 100 /*
 101  * release kqueue stuff
 102  */
 103 static int fpm_event_kqueue_clean() /* {{{ */
 104 {
 105         if (kevents) {
 106                 free(kevents);
 107                 kevents = NULL;
 108         }
 109 
 110         nkevents = 0;
 111 
 112         return 0;
 113 }
 114 /* }}} */
 115 
 116 /*
 117  * wait for events or timeout
 118  */
 119 static int fpm_event_kqueue_wait(struct fpm_event_queue_s *queue, unsigned long int timeout) /* {{{ */
 120 {
 121         struct timespec t;
 122         int ret, i;
 123 
 124         /* ensure we have a clean kevents before calling kevent() */
 125         memset(kevents, 0, sizeof(struct kevent) * nkevents);
 126 
 127         /* convert ms to timespec struct */
 128         t.tv_sec = timeout / 1000;
 129         t.tv_nsec = (timeout % 1000) * 1000 * 1000;
 130 
 131         /* wait for incoming event or timeout */
 132         ret = kevent(kfd, NULL, 0, kevents, nkevents, &t);
 133         if (ret == -1) {
 134 
 135                 /* trigger error unless signal interrupt */
 136                 if (errno != EINTR) {
 137                         zlog(ZLOG_WARNING, "epoll_wait() returns %d", errno);
 138                         return -1;
 139                 }
 140         }
 141 
 142         /* fire triggered events */
 143         for (i = 0; i < ret; i++) {
 144                 if (kevents[i].udata) {
 145                         struct fpm_event_s *ev = (struct fpm_event_s *)kevents[i].udata;
 146                         fpm_event_fire(ev);
 147                         /* sanity check */
 148                         if (fpm_globals.parent_pid != getpid()) {
 149                                 return -2;
 150                         }
 151                 }
 152         }
 153 
 154         return ret;
 155 }
 156 /* }}} */
 157 
 158 /*
 159  * Add a FD to to kevent queue
 160  */
 161 static int fpm_event_kqueue_add(struct fpm_event_s *ev) /* {{{ */
 162 {
 163         struct kevent k;
 164         int flags = EV_ADD;
 165 
 166         if (ev->flags & FPM_EV_EDGE) {
 167                         flags = flags | EV_CLEAR;
 168         }
 169 
 170         EV_SET(&k, ev->fd, EVFILT_READ, flags, 0, 0, (void *)ev);
 171 
 172         if (kevent(kfd, &k, 1, NULL, 0, NULL) < 0) {
 173                 zlog(ZLOG_ERROR, "kevent: unable to add event");
 174                 return -1;
 175         }
 176 
 177         /* mark the event as registered */
 178         ev->index = ev->fd;
 179         return 0;
 180 }
 181 /* }}} */
 182 
 183 /*
 184  * Remove a FD from the kevent queue
 185  */
 186 static int fpm_event_kqueue_remove(struct fpm_event_s *ev) /* {{{ */
 187 {
 188         struct kevent k;
 189         int flags = EV_DELETE;
 190 
 191         if (ev->flags & FPM_EV_EDGE) {
 192                         flags = flags | EV_CLEAR;
 193         }
 194 
 195         EV_SET(&k, ev->fd, EVFILT_READ, flags, 0, 0, (void *)ev);
 196 
 197         if (kevent(kfd, &k, 1, NULL, 0, NULL) < 0) {
 198                 zlog(ZLOG_ERROR, "kevent: unable to add event");
 199                 return -1;
 200         }
 201 
 202         /* mark the vent as not registered */
 203         ev->index = -1;
 204         return 0;
 205 }
 206 /* }}} */
 207 
 208 #endif /* HAVE_KQUEUE */

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