1 /* 2 * Copyright 2011 Red Hat, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation files 6 * (the "Software"), to deal in the Software without restriction, 7 * including without limitation the rights to use, copy, modify, merge, 8 * publish, distribute, sublicense, and/or sell copies of the Software, 9 * and to permit persons to whom the Software is furnished to do so, 10 * subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 /* 26 * An edited version of verto-libev.c, using an embedded libev with renamed 27 * symbols. The corresponding version of verto-libev.c is stored in this 28 * directory for reference, although it is not built here. 29 */ 30 31 #include "autoconf.h" 32 #include <stdlib.h> 33 #include <string.h> 34 #include <errno.h> 35 36 #include <verto.h> 37 #include <verto-module.h> 38 #include "rename.h" 39 40 /* Ignore some warnings generated by the libev code, which the libev maintainer 41 * isn't interested in avoiding. */ 42 #ifdef __GNUC__ 43 #pragma GCC diagnostic ignored "-Wunused-value" 44 #pragma GCC diagnostic ignored "-Wcomment" 45 #pragma GCC diagnostic ignored "-Wunused-result" 46 #ifdef __clang__ 47 #pragma GCC diagnostic ignored "-Wbitwise-op-parentheses" 48 #endif 49 #endif 50 51 #define EV_API_STATIC 1 52 #define EV_STANDALONE 1 53 /* Avoid using clock_gettime, which would create a dependency on librt. */ 54 #define EV_USE_MONOTONIC 0 55 #define EV_USE_REALTIME 0 56 #define EV_FEATURES 0x4f /* No back ends or optional watchers */ 57 /* Enable the optional watcher types we use. */ 58 #define EV_IDLE_ENABLE 1 59 #define EV_SIGNAL_ENABLE 1 60 #define EV_CHILD_ENABLE 1 61 /* Enable the back ends we want. */ 62 #ifdef HAVE_POLL_H 63 #define EV_USE_POLL 1 64 #endif 65 /* ev.c explicitly disables poll() on Mac or FreeBSD; fall back to select(). */ 66 #define EV_USE_SELECT 1 67 #include "ev.c" 68 69 static verto_mod_ctx * 70 k5ev_ctx_new(void) 71 { 72 return ev_loop_new(EVFLAG_AUTO); 73 } 74 75 static verto_mod_ctx * 76 k5ev_ctx_default(void) 77 { 78 return ev_default_loop(EVFLAG_AUTO); 79 } 80 81 static void 82 k5ev_ctx_free(verto_mod_ctx *ctx) 83 { 84 if (ctx != EV_DEFAULT) 85 ev_loop_destroy(ctx); 86 } 87 88 static void 89 k5ev_ctx_run(verto_mod_ctx *ctx) 90 { 91 ev_run(ctx, 0); 92 } 93 94 static void 95 k5ev_ctx_run_once(verto_mod_ctx *ctx) 96 { 97 ev_run(ctx, EVRUN_ONCE); 98 } 99 100 static void 101 k5ev_ctx_break(verto_mod_ctx *ctx) 102 { 103 ev_break(ctx, EVBREAK_ONE); 104 } 105 106 static void 107 k5ev_ctx_reinitialize(verto_mod_ctx *ctx) 108 { 109 ev_loop_fork(ctx); 110 } 111 112 static void 113 libev_callback(EV_P_ ev_watcher *w, int revents) 114 { 115 verto_ev_flag state = VERTO_EV_FLAG_NONE; 116 117 #if EV_MULTIPLICITY 118 /* Match the check in ev.h, which doesn't mark this unused */ 119 (void) EV_A; 120 #endif 121 122 if (verto_get_type(w->data)== VERTO_EV_TYPE_CHILD) 123 verto_set_proc_status(w->data, ((ev_child*) w)->rstatus); 124 125 if (revents & EV_READ) 126 state |= VERTO_EV_FLAG_IO_READ; 127 if (revents & EV_WRITE) 128 state |= VERTO_EV_FLAG_IO_WRITE; 129 if (revents & EV_ERROR) 130 state |= VERTO_EV_FLAG_IO_ERROR; 131 132 verto_set_fd_state(w->data, state); 133 verto_fire(w->data); 134 } 135 136 static void 137 k5ev_ctx_set_flags(verto_mod_ctx *ctx, const verto_ev *ev, 138 verto_mod_ev *evpriv) 139 { 140 if (verto_get_type(ev) == VERTO_EV_TYPE_IO) { 141 int events = EV_NONE; 142 143 if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_READ) 144 events |= EV_READ; 145 if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_WRITE) 146 events |= EV_WRITE; 147 148 ev_io_stop(ctx, (ev_io*) evpriv); 149 ev_io_set(((ev_io*) evpriv), verto_get_fd(ev), events); 150 ev_io_start(ctx, (ev_io*) evpriv); 151 } 152 } 153 154 #define setuptype(type, ...) \ 155 w.type = malloc(sizeof(ev_ ## type)); \ 156 if (w.type) { \ 157 ev_ ## type ## _init(w.type, (EV_CB(type, (*))) __VA_ARGS__); \ 158 ev_ ## type ## _start(ctx, w.type); \ 159 } \ 160 break 161 162 static verto_mod_ev * 163 k5ev_ctx_add(verto_mod_ctx *ctx, const verto_ev *ev, verto_ev_flag *flags) 164 { 165 union { 166 ev_watcher *watcher; 167 ev_io *io; 168 ev_timer *timer; 169 ev_idle *idle; 170 ev_signal *signal; 171 ev_child *child; 172 } w; 173 ev_tstamp interval; 174 175 w.watcher = NULL; 176 *flags |= VERTO_EV_FLAG_PERSIST; 177 switch (verto_get_type(ev)) { 178 case VERTO_EV_TYPE_IO: 179 setuptype(io, libev_callback, verto_get_fd(ev), EV_NONE); 180 case VERTO_EV_TYPE_TIMEOUT: 181 interval = ((ev_tstamp) verto_get_interval(ev)) / 1000.0; 182 setuptype(timer, libev_callback, interval, interval); 183 case VERTO_EV_TYPE_IDLE: 184 setuptype(idle, libev_callback); 185 case VERTO_EV_TYPE_SIGNAL: 186 setuptype(signal, libev_callback, verto_get_signal(ev)); 187 case VERTO_EV_TYPE_CHILD: 188 *flags &= ~VERTO_EV_FLAG_PERSIST; /* Child events don't persist */ 189 setuptype(child, libev_callback, verto_get_proc(ev), 0); 190 default: 191 break; /* Not supported */ 192 } 193 194 if (w.watcher) { 195 w.watcher->data = (void*) ev; 196 k5ev_ctx_set_flags(ctx, ev, w.watcher); 197 } 198 return w.watcher; 199 } 200 201 static void 202 k5ev_ctx_del(verto_mod_ctx *ctx, const verto_ev *ev, verto_mod_ev *evpriv) 203 { 204 switch (verto_get_type(ev)) { 205 case VERTO_EV_TYPE_IO: 206 ev_io_stop(ctx, (ev_io*) evpriv); 207 break; 208 case VERTO_EV_TYPE_TIMEOUT: 209 ev_timer_stop(ctx, (ev_timer*) evpriv); 210 break; 211 case VERTO_EV_TYPE_IDLE: 212 ev_idle_stop(ctx, (ev_idle*) evpriv); 213 break; 214 case VERTO_EV_TYPE_SIGNAL: 215 ev_signal_stop(ctx, (ev_signal*) evpriv); 216 break; 217 case VERTO_EV_TYPE_CHILD: 218 ev_child_stop(ctx, (ev_child*) evpriv); 219 break; 220 default: 221 break; 222 } 223 224 free(evpriv); 225 } 226 227 verto_ctx *verto_new_k5ev(void); 228 verto_ctx *verto_default_k5ev(void); 229 230 VERTO_MODULE(k5ev, NULL, 231 VERTO_EV_TYPE_IO | 232 VERTO_EV_TYPE_TIMEOUT | 233 VERTO_EV_TYPE_IDLE | 234 VERTO_EV_TYPE_SIGNAL | 235 VERTO_EV_TYPE_CHILD); 236