pull up r25473 from trunk
[krb5.git] / src / util / k5ev / verto-k5ev.c
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 /* An edited version of verto's verto-libev.c, using an embedded libev with
26  * renamed symbols. */
27
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31
32 #include "verto-k5ev.h"
33 #include <verto-module.h>
34 #include "rename.h"
35 #include "autoconf.h"
36 #define EV_STANDALONE 1
37 /* Avoids using clock_gettime; we probably shouldn't have to do this. */
38 #define EV_USE_REALTIME 0
39 #define EV_FEATURES 0x5f        /* Everything but back ends */
40 #ifdef HAVE_POLL_H
41 #define EV_USE_POLL 1
42 #endif
43 /* ev.c explicitly disables poll() on Mac or FreeBSD; fall back to select(). */
44 #define EV_USE_SELECT 1
45 #include "ev.c"
46
47 static void
48 k5ev_ctx_free(void *ctx)
49 {
50     if (ctx != EV_DEFAULT)
51         ev_loop_destroy(ctx);
52 }
53
54 static void
55 k5ev_ctx_run(void *ctx)
56 {
57     ev_run(ctx, 0);
58 }
59
60 static void
61 k5ev_ctx_run_once(void *ctx)
62 {
63     ev_run(ctx, EVRUN_ONCE);
64 }
65
66 static void
67 k5ev_ctx_break(void *ctx)
68 {
69     ev_break(ctx, EVBREAK_ONE);
70 }
71
72 static void
73 k5ev_ctx_reinitialize(void *ctx)
74 {
75     ev_loop_fork(ctx);
76 }
77
78 static void
79 libev_callback(EV_P_ ev_watcher *w, int revents)
80 {
81     if (verto_get_type(w->data) == VERTO_EV_TYPE_CHILD)
82         verto_set_proc_status(w->data, ((ev_child*) w)->rstatus);
83
84     verto_fire(w->data);
85 }
86
87 #define setuptype(type, priv, ...) \
88     type ## w = malloc(sizeof(ev_ ## type)); \
89     if (!type ## w) \
90         return NULL; \
91     ev_ ## type ## _init(type ## w, (EV_CB(type, (*))) __VA_ARGS__); \
92     type ## w->data = (void *) priv; \
93     ev_ ## type ## _start(ctx, type ## w); \
94     return type ## w
95
96 static void *
97 k5ev_ctx_add(void *ctx, const verto_ev *ev, verto_ev_flag *flags)
98 {
99     ev_io *iow = NULL;
100     ev_timer *timerw = NULL;
101     ev_idle *idlew = NULL;
102     ev_signal *signalw = NULL;
103     ev_child *childw = NULL;
104     ev_tstamp interval;
105     int events = EV_NONE;
106
107     *flags |= VERTO_EV_FLAG_PERSIST;
108     switch (verto_get_type(ev)) {
109         case VERTO_EV_TYPE_IO:
110             if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_READ)
111                 events |= EV_READ;
112             if (verto_get_flags(ev) & VERTO_EV_FLAG_IO_WRITE)
113                 events |= EV_WRITE;
114             setuptype(io, ev, libev_callback, verto_get_fd(ev), events);
115         case VERTO_EV_TYPE_TIMEOUT:
116             interval = ((ev_tstamp) verto_get_interval(ev)) / 1000.0;
117             setuptype(timer, ev, libev_callback, interval, interval);
118         case VERTO_EV_TYPE_IDLE:
119             setuptype(idle, ev, libev_callback);
120         case VERTO_EV_TYPE_SIGNAL:
121             setuptype(signal, ev, libev_callback, verto_get_signal(ev));
122         case VERTO_EV_TYPE_CHILD:
123             *flags &= ~VERTO_EV_FLAG_PERSIST; /* Child events don't persist */
124             setuptype(child, ev, libev_callback, verto_get_proc(ev), 0);
125         default:
126             return NULL; /* Not supported */
127     }
128 }
129
130 static void
131 k5ev_ctx_del(void *ctx, const verto_ev *ev, void *evpriv)
132 {
133     switch (verto_get_type(ev)) {
134         case VERTO_EV_TYPE_IO:
135             ev_io_stop(ctx, evpriv);
136             break;
137         case VERTO_EV_TYPE_TIMEOUT:
138             ev_timer_stop(ctx, evpriv);
139             break;
140         case VERTO_EV_TYPE_IDLE:
141             ev_idle_stop(ctx, evpriv);
142             break;
143         case VERTO_EV_TYPE_SIGNAL:
144             ev_signal_stop(ctx, evpriv);
145             break;
146         case VERTO_EV_TYPE_CHILD:
147             ev_child_stop(ctx, evpriv);
148             break;
149         default:
150             break;
151     }
152
153     free(evpriv);
154 }
155
156 static verto_ctx *verto_convert_k5ev(struct ev_loop* loop);
157
158 VERTO_MODULE(k5ev, NULL,
159              VERTO_EV_TYPE_IO |
160              VERTO_EV_TYPE_TIMEOUT |
161              VERTO_EV_TYPE_IDLE |
162              VERTO_EV_TYPE_SIGNAL |
163              VERTO_EV_TYPE_CHILD);
164
165 verto_ctx *
166 verto_new_k5ev(void)
167 {
168     return verto_convert_k5ev(ev_loop_new(EVFLAG_AUTO));
169 }
170
171 verto_ctx *
172 verto_default_k5ev(void)
173 {
174     return verto_convert_k5ev(ev_default_loop(EVFLAG_AUTO));
175 }
176
177 /* Don't export this since our underlying libev is hidden. */
178 static verto_ctx *
179 verto_convert_k5ev(struct ev_loop* loop)
180 {
181     return verto_convert(k5ev, loop);
182 }