1*663afb9bSAndroid Build Coastguard Worker /*
2*663afb9bSAndroid Build Coastguard Worker * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
3*663afb9bSAndroid Build Coastguard Worker *
4*663afb9bSAndroid Build Coastguard Worker * Redistribution and use in source and binary forms, with or without
5*663afb9bSAndroid Build Coastguard Worker * modification, are permitted provided that the following conditions
6*663afb9bSAndroid Build Coastguard Worker * are met:
7*663afb9bSAndroid Build Coastguard Worker * 1. Redistributions of source code must retain the above copyright
8*663afb9bSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer.
9*663afb9bSAndroid Build Coastguard Worker * 2. Redistributions in binary form must reproduce the above copyright
10*663afb9bSAndroid Build Coastguard Worker * notice, this list of conditions and the following disclaimer in the
11*663afb9bSAndroid Build Coastguard Worker * documentation and/or other materials provided with the distribution.
12*663afb9bSAndroid Build Coastguard Worker * 3. The name of the author may not be used to endorse or promote products
13*663afb9bSAndroid Build Coastguard Worker * derived from this software without specific prior written permission.
14*663afb9bSAndroid Build Coastguard Worker *
15*663afb9bSAndroid Build Coastguard Worker * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16*663afb9bSAndroid Build Coastguard Worker * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17*663afb9bSAndroid Build Coastguard Worker * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18*663afb9bSAndroid Build Coastguard Worker * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19*663afb9bSAndroid Build Coastguard Worker * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20*663afb9bSAndroid Build Coastguard Worker * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21*663afb9bSAndroid Build Coastguard Worker * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22*663afb9bSAndroid Build Coastguard Worker * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23*663afb9bSAndroid Build Coastguard Worker * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24*663afb9bSAndroid Build Coastguard Worker * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*663afb9bSAndroid Build Coastguard Worker */
26*663afb9bSAndroid Build Coastguard Worker #include "event2/event-config.h"
27*663afb9bSAndroid Build Coastguard Worker #include "evconfig-private.h"
28*663afb9bSAndroid Build Coastguard Worker
29*663afb9bSAndroid Build Coastguard Worker #ifdef _WIN32
30*663afb9bSAndroid Build Coastguard Worker #include <winsock2.h>
31*663afb9bSAndroid Build Coastguard Worker #define WIN32_LEAN_AND_MEAN
32*663afb9bSAndroid Build Coastguard Worker #include <windows.h>
33*663afb9bSAndroid Build Coastguard Worker #undef WIN32_LEAN_AND_MEAN
34*663afb9bSAndroid Build Coastguard Worker #endif
35*663afb9bSAndroid Build Coastguard Worker #include <sys/types.h>
36*663afb9bSAndroid Build Coastguard Worker #if !defined(_WIN32) && defined(EVENT__HAVE_SYS_TIME_H)
37*663afb9bSAndroid Build Coastguard Worker #include <sys/time.h>
38*663afb9bSAndroid Build Coastguard Worker #endif
39*663afb9bSAndroid Build Coastguard Worker #include <sys/queue.h>
40*663afb9bSAndroid Build Coastguard Worker #include <stdio.h>
41*663afb9bSAndroid Build Coastguard Worker #include <stdlib.h>
42*663afb9bSAndroid Build Coastguard Worker #ifndef _WIN32
43*663afb9bSAndroid Build Coastguard Worker #include <unistd.h>
44*663afb9bSAndroid Build Coastguard Worker #endif
45*663afb9bSAndroid Build Coastguard Worker #include <errno.h>
46*663afb9bSAndroid Build Coastguard Worker #include <limits.h>
47*663afb9bSAndroid Build Coastguard Worker #include <signal.h>
48*663afb9bSAndroid Build Coastguard Worker #include <string.h>
49*663afb9bSAndroid Build Coastguard Worker #include <time.h>
50*663afb9bSAndroid Build Coastguard Worker
51*663afb9bSAndroid Build Coastguard Worker #include "event-internal.h"
52*663afb9bSAndroid Build Coastguard Worker #include "evmap-internal.h"
53*663afb9bSAndroid Build Coastguard Worker #include "mm-internal.h"
54*663afb9bSAndroid Build Coastguard Worker #include "changelist-internal.h"
55*663afb9bSAndroid Build Coastguard Worker
56*663afb9bSAndroid Build Coastguard Worker /** An entry for an evmap_io list: notes all the events that want to read or
57*663afb9bSAndroid Build Coastguard Worker write on a given fd, and the number of each.
58*663afb9bSAndroid Build Coastguard Worker */
59*663afb9bSAndroid Build Coastguard Worker struct evmap_io {
60*663afb9bSAndroid Build Coastguard Worker struct event_dlist events;
61*663afb9bSAndroid Build Coastguard Worker ev_uint16_t nread;
62*663afb9bSAndroid Build Coastguard Worker ev_uint16_t nwrite;
63*663afb9bSAndroid Build Coastguard Worker ev_uint16_t nclose;
64*663afb9bSAndroid Build Coastguard Worker };
65*663afb9bSAndroid Build Coastguard Worker
66*663afb9bSAndroid Build Coastguard Worker /* An entry for an evmap_signal list: notes all the events that want to know
67*663afb9bSAndroid Build Coastguard Worker when a signal triggers. */
68*663afb9bSAndroid Build Coastguard Worker struct evmap_signal {
69*663afb9bSAndroid Build Coastguard Worker struct event_dlist events;
70*663afb9bSAndroid Build Coastguard Worker };
71*663afb9bSAndroid Build Coastguard Worker
72*663afb9bSAndroid Build Coastguard Worker /* On some platforms, fds start at 0 and increment by 1 as they are
73*663afb9bSAndroid Build Coastguard Worker allocated, and old numbers get used. For these platforms, we
74*663afb9bSAndroid Build Coastguard Worker implement io maps just like signal maps: as an array of pointers to
75*663afb9bSAndroid Build Coastguard Worker struct evmap_io. But on other platforms (windows), sockets are not
76*663afb9bSAndroid Build Coastguard Worker 0-indexed, not necessarily consecutive, and not necessarily reused.
77*663afb9bSAndroid Build Coastguard Worker There, we use a hashtable to implement evmap_io.
78*663afb9bSAndroid Build Coastguard Worker */
79*663afb9bSAndroid Build Coastguard Worker #ifdef EVMAP_USE_HT
80*663afb9bSAndroid Build Coastguard Worker struct event_map_entry {
81*663afb9bSAndroid Build Coastguard Worker HT_ENTRY(event_map_entry) map_node;
82*663afb9bSAndroid Build Coastguard Worker evutil_socket_t fd;
83*663afb9bSAndroid Build Coastguard Worker union { /* This is a union in case we need to make more things that can
84*663afb9bSAndroid Build Coastguard Worker be in the hashtable. */
85*663afb9bSAndroid Build Coastguard Worker struct evmap_io evmap_io;
86*663afb9bSAndroid Build Coastguard Worker } ent;
87*663afb9bSAndroid Build Coastguard Worker };
88*663afb9bSAndroid Build Coastguard Worker
89*663afb9bSAndroid Build Coastguard Worker /* Helper used by the event_io_map hashtable code; tries to return a good hash
90*663afb9bSAndroid Build Coastguard Worker * of the fd in e->fd. */
91*663afb9bSAndroid Build Coastguard Worker static inline unsigned
hashsocket(struct event_map_entry * e)92*663afb9bSAndroid Build Coastguard Worker hashsocket(struct event_map_entry *e)
93*663afb9bSAndroid Build Coastguard Worker {
94*663afb9bSAndroid Build Coastguard Worker /* On win32, in practice, the low 2-3 bits of a SOCKET seem not to
95*663afb9bSAndroid Build Coastguard Worker * matter. Our hashtable implementation really likes low-order bits,
96*663afb9bSAndroid Build Coastguard Worker * though, so let's do the rotate-and-add trick. */
97*663afb9bSAndroid Build Coastguard Worker unsigned h = (unsigned) e->fd;
98*663afb9bSAndroid Build Coastguard Worker h += (h >> 2) | (h << 30);
99*663afb9bSAndroid Build Coastguard Worker return h;
100*663afb9bSAndroid Build Coastguard Worker }
101*663afb9bSAndroid Build Coastguard Worker
102*663afb9bSAndroid Build Coastguard Worker /* Helper used by the event_io_map hashtable code; returns true iff e1 and e2
103*663afb9bSAndroid Build Coastguard Worker * have the same e->fd. */
104*663afb9bSAndroid Build Coastguard Worker static inline int
eqsocket(struct event_map_entry * e1,struct event_map_entry * e2)105*663afb9bSAndroid Build Coastguard Worker eqsocket(struct event_map_entry *e1, struct event_map_entry *e2)
106*663afb9bSAndroid Build Coastguard Worker {
107*663afb9bSAndroid Build Coastguard Worker return e1->fd == e2->fd;
108*663afb9bSAndroid Build Coastguard Worker }
109*663afb9bSAndroid Build Coastguard Worker
HT_PROTOTYPE(event_io_map,event_map_entry,map_node,hashsocket,eqsocket)110*663afb9bSAndroid Build Coastguard Worker HT_PROTOTYPE(event_io_map, event_map_entry, map_node, hashsocket, eqsocket)
111*663afb9bSAndroid Build Coastguard Worker HT_GENERATE(event_io_map, event_map_entry, map_node, hashsocket, eqsocket,
112*663afb9bSAndroid Build Coastguard Worker 0.5, mm_malloc, mm_realloc, mm_free)
113*663afb9bSAndroid Build Coastguard Worker
114*663afb9bSAndroid Build Coastguard Worker #define GET_IO_SLOT(x, map, slot, type) \
115*663afb9bSAndroid Build Coastguard Worker do { \
116*663afb9bSAndroid Build Coastguard Worker struct event_map_entry key_, *ent_; \
117*663afb9bSAndroid Build Coastguard Worker key_.fd = slot; \
118*663afb9bSAndroid Build Coastguard Worker ent_ = HT_FIND(event_io_map, map, &key_); \
119*663afb9bSAndroid Build Coastguard Worker (x) = ent_ ? &ent_->ent.type : NULL; \
120*663afb9bSAndroid Build Coastguard Worker } while (0);
121*663afb9bSAndroid Build Coastguard Worker
122*663afb9bSAndroid Build Coastguard Worker #define GET_IO_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len) \
123*663afb9bSAndroid Build Coastguard Worker do { \
124*663afb9bSAndroid Build Coastguard Worker struct event_map_entry key_, *ent_; \
125*663afb9bSAndroid Build Coastguard Worker key_.fd = slot; \
126*663afb9bSAndroid Build Coastguard Worker HT_FIND_OR_INSERT_(event_io_map, map_node, hashsocket, map, \
127*663afb9bSAndroid Build Coastguard Worker event_map_entry, &key_, ptr, \
128*663afb9bSAndroid Build Coastguard Worker { \
129*663afb9bSAndroid Build Coastguard Worker ent_ = *ptr; \
130*663afb9bSAndroid Build Coastguard Worker }, \
131*663afb9bSAndroid Build Coastguard Worker { \
132*663afb9bSAndroid Build Coastguard Worker ent_ = mm_calloc(1,sizeof(struct event_map_entry)+fdinfo_len); \
133*663afb9bSAndroid Build Coastguard Worker if (EVUTIL_UNLIKELY(ent_ == NULL)) \
134*663afb9bSAndroid Build Coastguard Worker return (-1); \
135*663afb9bSAndroid Build Coastguard Worker ent_->fd = slot; \
136*663afb9bSAndroid Build Coastguard Worker (ctor)(&ent_->ent.type); \
137*663afb9bSAndroid Build Coastguard Worker HT_FOI_INSERT_(map_node, map, &key_, ent_, ptr) \
138*663afb9bSAndroid Build Coastguard Worker }); \
139*663afb9bSAndroid Build Coastguard Worker (x) = &ent_->ent.type; \
140*663afb9bSAndroid Build Coastguard Worker } while (0)
141*663afb9bSAndroid Build Coastguard Worker
142*663afb9bSAndroid Build Coastguard Worker void evmap_io_initmap_(struct event_io_map *ctx)
143*663afb9bSAndroid Build Coastguard Worker {
144*663afb9bSAndroid Build Coastguard Worker HT_INIT(event_io_map, ctx);
145*663afb9bSAndroid Build Coastguard Worker }
146*663afb9bSAndroid Build Coastguard Worker
evmap_io_clear_(struct event_io_map * ctx)147*663afb9bSAndroid Build Coastguard Worker void evmap_io_clear_(struct event_io_map *ctx)
148*663afb9bSAndroid Build Coastguard Worker {
149*663afb9bSAndroid Build Coastguard Worker struct event_map_entry **ent, **next, *this;
150*663afb9bSAndroid Build Coastguard Worker for (ent = HT_START(event_io_map, ctx); ent; ent = next) {
151*663afb9bSAndroid Build Coastguard Worker this = *ent;
152*663afb9bSAndroid Build Coastguard Worker next = HT_NEXT_RMV(event_io_map, ctx, ent);
153*663afb9bSAndroid Build Coastguard Worker mm_free(this);
154*663afb9bSAndroid Build Coastguard Worker }
155*663afb9bSAndroid Build Coastguard Worker HT_CLEAR(event_io_map, ctx); /* remove all storage held by the ctx. */
156*663afb9bSAndroid Build Coastguard Worker }
157*663afb9bSAndroid Build Coastguard Worker #endif
158*663afb9bSAndroid Build Coastguard Worker
159*663afb9bSAndroid Build Coastguard Worker /* Set the variable 'x' to the field in event_map 'map' with fields of type
160*663afb9bSAndroid Build Coastguard Worker 'struct type *' corresponding to the fd or signal 'slot'. Set 'x' to NULL
161*663afb9bSAndroid Build Coastguard Worker if there are no entries for 'slot'. Does no bounds-checking. */
162*663afb9bSAndroid Build Coastguard Worker #define GET_SIGNAL_SLOT(x, map, slot, type) \
163*663afb9bSAndroid Build Coastguard Worker (x) = (struct type *)((map)->entries[slot])
164*663afb9bSAndroid Build Coastguard Worker /* As GET_SLOT, but construct the entry for 'slot' if it is not present,
165*663afb9bSAndroid Build Coastguard Worker by allocating enough memory for a 'struct type', and initializing the new
166*663afb9bSAndroid Build Coastguard Worker value by calling the function 'ctor' on it. Makes the function
167*663afb9bSAndroid Build Coastguard Worker return -1 on allocation failure.
168*663afb9bSAndroid Build Coastguard Worker */
169*663afb9bSAndroid Build Coastguard Worker #define GET_SIGNAL_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len) \
170*663afb9bSAndroid Build Coastguard Worker do { \
171*663afb9bSAndroid Build Coastguard Worker if ((map)->entries[slot] == NULL) { \
172*663afb9bSAndroid Build Coastguard Worker (map)->entries[slot] = \
173*663afb9bSAndroid Build Coastguard Worker mm_calloc(1,sizeof(struct type)+fdinfo_len); \
174*663afb9bSAndroid Build Coastguard Worker if (EVUTIL_UNLIKELY((map)->entries[slot] == NULL)) \
175*663afb9bSAndroid Build Coastguard Worker return (-1); \
176*663afb9bSAndroid Build Coastguard Worker (ctor)((struct type *)(map)->entries[slot]); \
177*663afb9bSAndroid Build Coastguard Worker } \
178*663afb9bSAndroid Build Coastguard Worker (x) = (struct type *)((map)->entries[slot]); \
179*663afb9bSAndroid Build Coastguard Worker } while (0)
180*663afb9bSAndroid Build Coastguard Worker
181*663afb9bSAndroid Build Coastguard Worker /* If we aren't using hashtables, then define the IO_SLOT macros and functions
182*663afb9bSAndroid Build Coastguard Worker as thin aliases over the SIGNAL_SLOT versions. */
183*663afb9bSAndroid Build Coastguard Worker #ifndef EVMAP_USE_HT
184*663afb9bSAndroid Build Coastguard Worker #define GET_IO_SLOT(x,map,slot,type) GET_SIGNAL_SLOT(x,map,slot,type)
185*663afb9bSAndroid Build Coastguard Worker #define GET_IO_SLOT_AND_CTOR(x,map,slot,type,ctor,fdinfo_len) \
186*663afb9bSAndroid Build Coastguard Worker GET_SIGNAL_SLOT_AND_CTOR(x,map,slot,type,ctor,fdinfo_len)
187*663afb9bSAndroid Build Coastguard Worker #define FDINFO_OFFSET sizeof(struct evmap_io)
188*663afb9bSAndroid Build Coastguard Worker void
evmap_io_initmap_(struct event_io_map * ctx)189*663afb9bSAndroid Build Coastguard Worker evmap_io_initmap_(struct event_io_map* ctx)
190*663afb9bSAndroid Build Coastguard Worker {
191*663afb9bSAndroid Build Coastguard Worker evmap_signal_initmap_(ctx);
192*663afb9bSAndroid Build Coastguard Worker }
193*663afb9bSAndroid Build Coastguard Worker void
evmap_io_clear_(struct event_io_map * ctx)194*663afb9bSAndroid Build Coastguard Worker evmap_io_clear_(struct event_io_map* ctx)
195*663afb9bSAndroid Build Coastguard Worker {
196*663afb9bSAndroid Build Coastguard Worker evmap_signal_clear_(ctx);
197*663afb9bSAndroid Build Coastguard Worker }
198*663afb9bSAndroid Build Coastguard Worker #endif
199*663afb9bSAndroid Build Coastguard Worker
200*663afb9bSAndroid Build Coastguard Worker
201*663afb9bSAndroid Build Coastguard Worker /** Expand 'map' with new entries of width 'msize' until it is big enough
202*663afb9bSAndroid Build Coastguard Worker to store a value in 'slot'.
203*663afb9bSAndroid Build Coastguard Worker */
204*663afb9bSAndroid Build Coastguard Worker static int
evmap_make_space(struct event_signal_map * map,int slot,int msize)205*663afb9bSAndroid Build Coastguard Worker evmap_make_space(struct event_signal_map *map, int slot, int msize)
206*663afb9bSAndroid Build Coastguard Worker {
207*663afb9bSAndroid Build Coastguard Worker if (map->nentries <= slot) {
208*663afb9bSAndroid Build Coastguard Worker int nentries = map->nentries ? map->nentries : 32;
209*663afb9bSAndroid Build Coastguard Worker void **tmp;
210*663afb9bSAndroid Build Coastguard Worker
211*663afb9bSAndroid Build Coastguard Worker if (slot > INT_MAX / 2)
212*663afb9bSAndroid Build Coastguard Worker return (-1);
213*663afb9bSAndroid Build Coastguard Worker
214*663afb9bSAndroid Build Coastguard Worker while (nentries <= slot)
215*663afb9bSAndroid Build Coastguard Worker nentries <<= 1;
216*663afb9bSAndroid Build Coastguard Worker
217*663afb9bSAndroid Build Coastguard Worker if (nentries > INT_MAX / msize)
218*663afb9bSAndroid Build Coastguard Worker return (-1);
219*663afb9bSAndroid Build Coastguard Worker
220*663afb9bSAndroid Build Coastguard Worker tmp = (void **)mm_realloc(map->entries, nentries * msize);
221*663afb9bSAndroid Build Coastguard Worker if (tmp == NULL)
222*663afb9bSAndroid Build Coastguard Worker return (-1);
223*663afb9bSAndroid Build Coastguard Worker
224*663afb9bSAndroid Build Coastguard Worker memset(&tmp[map->nentries], 0,
225*663afb9bSAndroid Build Coastguard Worker (nentries - map->nentries) * msize);
226*663afb9bSAndroid Build Coastguard Worker
227*663afb9bSAndroid Build Coastguard Worker map->nentries = nentries;
228*663afb9bSAndroid Build Coastguard Worker map->entries = tmp;
229*663afb9bSAndroid Build Coastguard Worker }
230*663afb9bSAndroid Build Coastguard Worker
231*663afb9bSAndroid Build Coastguard Worker return (0);
232*663afb9bSAndroid Build Coastguard Worker }
233*663afb9bSAndroid Build Coastguard Worker
234*663afb9bSAndroid Build Coastguard Worker void
evmap_signal_initmap_(struct event_signal_map * ctx)235*663afb9bSAndroid Build Coastguard Worker evmap_signal_initmap_(struct event_signal_map *ctx)
236*663afb9bSAndroid Build Coastguard Worker {
237*663afb9bSAndroid Build Coastguard Worker ctx->nentries = 0;
238*663afb9bSAndroid Build Coastguard Worker ctx->entries = NULL;
239*663afb9bSAndroid Build Coastguard Worker }
240*663afb9bSAndroid Build Coastguard Worker
241*663afb9bSAndroid Build Coastguard Worker void
evmap_signal_clear_(struct event_signal_map * ctx)242*663afb9bSAndroid Build Coastguard Worker evmap_signal_clear_(struct event_signal_map *ctx)
243*663afb9bSAndroid Build Coastguard Worker {
244*663afb9bSAndroid Build Coastguard Worker if (ctx->entries != NULL) {
245*663afb9bSAndroid Build Coastguard Worker int i;
246*663afb9bSAndroid Build Coastguard Worker for (i = 0; i < ctx->nentries; ++i) {
247*663afb9bSAndroid Build Coastguard Worker if (ctx->entries[i] != NULL)
248*663afb9bSAndroid Build Coastguard Worker mm_free(ctx->entries[i]);
249*663afb9bSAndroid Build Coastguard Worker }
250*663afb9bSAndroid Build Coastguard Worker mm_free(ctx->entries);
251*663afb9bSAndroid Build Coastguard Worker ctx->entries = NULL;
252*663afb9bSAndroid Build Coastguard Worker }
253*663afb9bSAndroid Build Coastguard Worker ctx->nentries = 0;
254*663afb9bSAndroid Build Coastguard Worker }
255*663afb9bSAndroid Build Coastguard Worker
256*663afb9bSAndroid Build Coastguard Worker
257*663afb9bSAndroid Build Coastguard Worker /* code specific to file descriptors */
258*663afb9bSAndroid Build Coastguard Worker
259*663afb9bSAndroid Build Coastguard Worker /** Constructor for struct evmap_io */
260*663afb9bSAndroid Build Coastguard Worker static void
evmap_io_init(struct evmap_io * entry)261*663afb9bSAndroid Build Coastguard Worker evmap_io_init(struct evmap_io *entry)
262*663afb9bSAndroid Build Coastguard Worker {
263*663afb9bSAndroid Build Coastguard Worker LIST_INIT(&entry->events);
264*663afb9bSAndroid Build Coastguard Worker entry->nread = 0;
265*663afb9bSAndroid Build Coastguard Worker entry->nwrite = 0;
266*663afb9bSAndroid Build Coastguard Worker entry->nclose = 0;
267*663afb9bSAndroid Build Coastguard Worker }
268*663afb9bSAndroid Build Coastguard Worker
269*663afb9bSAndroid Build Coastguard Worker
270*663afb9bSAndroid Build Coastguard Worker /* return -1 on error, 0 on success if nothing changed in the event backend,
271*663afb9bSAndroid Build Coastguard Worker * and 1 on success if something did. */
272*663afb9bSAndroid Build Coastguard Worker int
evmap_io_add_(struct event_base * base,evutil_socket_t fd,struct event * ev)273*663afb9bSAndroid Build Coastguard Worker evmap_io_add_(struct event_base *base, evutil_socket_t fd, struct event *ev)
274*663afb9bSAndroid Build Coastguard Worker {
275*663afb9bSAndroid Build Coastguard Worker const struct eventop *evsel = base->evsel;
276*663afb9bSAndroid Build Coastguard Worker struct event_io_map *io = &base->io;
277*663afb9bSAndroid Build Coastguard Worker struct evmap_io *ctx = NULL;
278*663afb9bSAndroid Build Coastguard Worker int nread, nwrite, nclose, retval = 0;
279*663afb9bSAndroid Build Coastguard Worker short res = 0, old = 0;
280*663afb9bSAndroid Build Coastguard Worker struct event *old_ev;
281*663afb9bSAndroid Build Coastguard Worker
282*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(fd == ev->ev_fd);
283*663afb9bSAndroid Build Coastguard Worker
284*663afb9bSAndroid Build Coastguard Worker if (fd < 0)
285*663afb9bSAndroid Build Coastguard Worker return 0;
286*663afb9bSAndroid Build Coastguard Worker
287*663afb9bSAndroid Build Coastguard Worker #ifndef EVMAP_USE_HT
288*663afb9bSAndroid Build Coastguard Worker if (fd >= io->nentries) {
289*663afb9bSAndroid Build Coastguard Worker if (evmap_make_space(io, fd, sizeof(struct evmap_io *)) == -1)
290*663afb9bSAndroid Build Coastguard Worker return (-1);
291*663afb9bSAndroid Build Coastguard Worker }
292*663afb9bSAndroid Build Coastguard Worker #endif
293*663afb9bSAndroid Build Coastguard Worker GET_IO_SLOT_AND_CTOR(ctx, io, fd, evmap_io, evmap_io_init,
294*663afb9bSAndroid Build Coastguard Worker evsel->fdinfo_len);
295*663afb9bSAndroid Build Coastguard Worker
296*663afb9bSAndroid Build Coastguard Worker nread = ctx->nread;
297*663afb9bSAndroid Build Coastguard Worker nwrite = ctx->nwrite;
298*663afb9bSAndroid Build Coastguard Worker nclose = ctx->nclose;
299*663afb9bSAndroid Build Coastguard Worker
300*663afb9bSAndroid Build Coastguard Worker if (nread)
301*663afb9bSAndroid Build Coastguard Worker old |= EV_READ;
302*663afb9bSAndroid Build Coastguard Worker if (nwrite)
303*663afb9bSAndroid Build Coastguard Worker old |= EV_WRITE;
304*663afb9bSAndroid Build Coastguard Worker if (nclose)
305*663afb9bSAndroid Build Coastguard Worker old |= EV_CLOSED;
306*663afb9bSAndroid Build Coastguard Worker
307*663afb9bSAndroid Build Coastguard Worker if (ev->ev_events & EV_READ) {
308*663afb9bSAndroid Build Coastguard Worker if (++nread == 1)
309*663afb9bSAndroid Build Coastguard Worker res |= EV_READ;
310*663afb9bSAndroid Build Coastguard Worker }
311*663afb9bSAndroid Build Coastguard Worker if (ev->ev_events & EV_WRITE) {
312*663afb9bSAndroid Build Coastguard Worker if (++nwrite == 1)
313*663afb9bSAndroid Build Coastguard Worker res |= EV_WRITE;
314*663afb9bSAndroid Build Coastguard Worker }
315*663afb9bSAndroid Build Coastguard Worker if (ev->ev_events & EV_CLOSED) {
316*663afb9bSAndroid Build Coastguard Worker if (++nclose == 1)
317*663afb9bSAndroid Build Coastguard Worker res |= EV_CLOSED;
318*663afb9bSAndroid Build Coastguard Worker }
319*663afb9bSAndroid Build Coastguard Worker if (EVUTIL_UNLIKELY(nread > 0xffff || nwrite > 0xffff || nclose > 0xffff)) {
320*663afb9bSAndroid Build Coastguard Worker event_warnx("Too many events reading or writing on fd %d",
321*663afb9bSAndroid Build Coastguard Worker (int)fd);
322*663afb9bSAndroid Build Coastguard Worker return -1;
323*663afb9bSAndroid Build Coastguard Worker }
324*663afb9bSAndroid Build Coastguard Worker if (EVENT_DEBUG_MODE_IS_ON() &&
325*663afb9bSAndroid Build Coastguard Worker (old_ev = LIST_FIRST(&ctx->events)) &&
326*663afb9bSAndroid Build Coastguard Worker (old_ev->ev_events&EV_ET) != (ev->ev_events&EV_ET)) {
327*663afb9bSAndroid Build Coastguard Worker event_warnx("Tried to mix edge-triggered and non-edge-triggered"
328*663afb9bSAndroid Build Coastguard Worker " events on fd %d", (int)fd);
329*663afb9bSAndroid Build Coastguard Worker return -1;
330*663afb9bSAndroid Build Coastguard Worker }
331*663afb9bSAndroid Build Coastguard Worker
332*663afb9bSAndroid Build Coastguard Worker if (res) {
333*663afb9bSAndroid Build Coastguard Worker void *extra = ((char*)ctx) + sizeof(struct evmap_io);
334*663afb9bSAndroid Build Coastguard Worker /* XXX(niels): we cannot mix edge-triggered and
335*663afb9bSAndroid Build Coastguard Worker * level-triggered, we should probably assert on
336*663afb9bSAndroid Build Coastguard Worker * this. */
337*663afb9bSAndroid Build Coastguard Worker if (evsel->add(base, ev->ev_fd,
338*663afb9bSAndroid Build Coastguard Worker old, (ev->ev_events & EV_ET) | res, extra) == -1)
339*663afb9bSAndroid Build Coastguard Worker return (-1);
340*663afb9bSAndroid Build Coastguard Worker retval = 1;
341*663afb9bSAndroid Build Coastguard Worker }
342*663afb9bSAndroid Build Coastguard Worker
343*663afb9bSAndroid Build Coastguard Worker ctx->nread = (ev_uint16_t) nread;
344*663afb9bSAndroid Build Coastguard Worker ctx->nwrite = (ev_uint16_t) nwrite;
345*663afb9bSAndroid Build Coastguard Worker ctx->nclose = (ev_uint16_t) nclose;
346*663afb9bSAndroid Build Coastguard Worker LIST_INSERT_HEAD(&ctx->events, ev, ev_io_next);
347*663afb9bSAndroid Build Coastguard Worker
348*663afb9bSAndroid Build Coastguard Worker return (retval);
349*663afb9bSAndroid Build Coastguard Worker }
350*663afb9bSAndroid Build Coastguard Worker
351*663afb9bSAndroid Build Coastguard Worker /* return -1 on error, 0 on success if nothing changed in the event backend,
352*663afb9bSAndroid Build Coastguard Worker * and 1 on success if something did. */
353*663afb9bSAndroid Build Coastguard Worker int
evmap_io_del_(struct event_base * base,evutil_socket_t fd,struct event * ev)354*663afb9bSAndroid Build Coastguard Worker evmap_io_del_(struct event_base *base, evutil_socket_t fd, struct event *ev)
355*663afb9bSAndroid Build Coastguard Worker {
356*663afb9bSAndroid Build Coastguard Worker const struct eventop *evsel = base->evsel;
357*663afb9bSAndroid Build Coastguard Worker struct event_io_map *io = &base->io;
358*663afb9bSAndroid Build Coastguard Worker struct evmap_io *ctx;
359*663afb9bSAndroid Build Coastguard Worker int nread, nwrite, nclose, retval = 0;
360*663afb9bSAndroid Build Coastguard Worker short res = 0, old = 0;
361*663afb9bSAndroid Build Coastguard Worker
362*663afb9bSAndroid Build Coastguard Worker if (fd < 0)
363*663afb9bSAndroid Build Coastguard Worker return 0;
364*663afb9bSAndroid Build Coastguard Worker
365*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(fd == ev->ev_fd);
366*663afb9bSAndroid Build Coastguard Worker
367*663afb9bSAndroid Build Coastguard Worker #ifndef EVMAP_USE_HT
368*663afb9bSAndroid Build Coastguard Worker if (fd >= io->nentries)
369*663afb9bSAndroid Build Coastguard Worker return (-1);
370*663afb9bSAndroid Build Coastguard Worker #endif
371*663afb9bSAndroid Build Coastguard Worker
372*663afb9bSAndroid Build Coastguard Worker GET_IO_SLOT(ctx, io, fd, evmap_io);
373*663afb9bSAndroid Build Coastguard Worker
374*663afb9bSAndroid Build Coastguard Worker nread = ctx->nread;
375*663afb9bSAndroid Build Coastguard Worker nwrite = ctx->nwrite;
376*663afb9bSAndroid Build Coastguard Worker nclose = ctx->nclose;
377*663afb9bSAndroid Build Coastguard Worker
378*663afb9bSAndroid Build Coastguard Worker if (nread)
379*663afb9bSAndroid Build Coastguard Worker old |= EV_READ;
380*663afb9bSAndroid Build Coastguard Worker if (nwrite)
381*663afb9bSAndroid Build Coastguard Worker old |= EV_WRITE;
382*663afb9bSAndroid Build Coastguard Worker if (nclose)
383*663afb9bSAndroid Build Coastguard Worker old |= EV_CLOSED;
384*663afb9bSAndroid Build Coastguard Worker
385*663afb9bSAndroid Build Coastguard Worker if (ev->ev_events & EV_READ) {
386*663afb9bSAndroid Build Coastguard Worker if (--nread == 0)
387*663afb9bSAndroid Build Coastguard Worker res |= EV_READ;
388*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(nread >= 0);
389*663afb9bSAndroid Build Coastguard Worker }
390*663afb9bSAndroid Build Coastguard Worker if (ev->ev_events & EV_WRITE) {
391*663afb9bSAndroid Build Coastguard Worker if (--nwrite == 0)
392*663afb9bSAndroid Build Coastguard Worker res |= EV_WRITE;
393*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(nwrite >= 0);
394*663afb9bSAndroid Build Coastguard Worker }
395*663afb9bSAndroid Build Coastguard Worker if (ev->ev_events & EV_CLOSED) {
396*663afb9bSAndroid Build Coastguard Worker if (--nclose == 0)
397*663afb9bSAndroid Build Coastguard Worker res |= EV_CLOSED;
398*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(nclose >= 0);
399*663afb9bSAndroid Build Coastguard Worker }
400*663afb9bSAndroid Build Coastguard Worker
401*663afb9bSAndroid Build Coastguard Worker if (res) {
402*663afb9bSAndroid Build Coastguard Worker void *extra = ((char*)ctx) + sizeof(struct evmap_io);
403*663afb9bSAndroid Build Coastguard Worker if (evsel->del(base, ev->ev_fd,
404*663afb9bSAndroid Build Coastguard Worker old, (ev->ev_events & EV_ET) | res, extra) == -1) {
405*663afb9bSAndroid Build Coastguard Worker retval = -1;
406*663afb9bSAndroid Build Coastguard Worker } else {
407*663afb9bSAndroid Build Coastguard Worker retval = 1;
408*663afb9bSAndroid Build Coastguard Worker }
409*663afb9bSAndroid Build Coastguard Worker }
410*663afb9bSAndroid Build Coastguard Worker
411*663afb9bSAndroid Build Coastguard Worker ctx->nread = nread;
412*663afb9bSAndroid Build Coastguard Worker ctx->nwrite = nwrite;
413*663afb9bSAndroid Build Coastguard Worker ctx->nclose = nclose;
414*663afb9bSAndroid Build Coastguard Worker LIST_REMOVE(ev, ev_io_next);
415*663afb9bSAndroid Build Coastguard Worker
416*663afb9bSAndroid Build Coastguard Worker return (retval);
417*663afb9bSAndroid Build Coastguard Worker }
418*663afb9bSAndroid Build Coastguard Worker
419*663afb9bSAndroid Build Coastguard Worker void
evmap_io_active_(struct event_base * base,evutil_socket_t fd,short events)420*663afb9bSAndroid Build Coastguard Worker evmap_io_active_(struct event_base *base, evutil_socket_t fd, short events)
421*663afb9bSAndroid Build Coastguard Worker {
422*663afb9bSAndroid Build Coastguard Worker struct event_io_map *io = &base->io;
423*663afb9bSAndroid Build Coastguard Worker struct evmap_io *ctx;
424*663afb9bSAndroid Build Coastguard Worker struct event *ev;
425*663afb9bSAndroid Build Coastguard Worker
426*663afb9bSAndroid Build Coastguard Worker #ifndef EVMAP_USE_HT
427*663afb9bSAndroid Build Coastguard Worker if (fd < 0 || fd >= io->nentries)
428*663afb9bSAndroid Build Coastguard Worker return;
429*663afb9bSAndroid Build Coastguard Worker #endif
430*663afb9bSAndroid Build Coastguard Worker GET_IO_SLOT(ctx, io, fd, evmap_io);
431*663afb9bSAndroid Build Coastguard Worker
432*663afb9bSAndroid Build Coastguard Worker if (NULL == ctx)
433*663afb9bSAndroid Build Coastguard Worker return;
434*663afb9bSAndroid Build Coastguard Worker LIST_FOREACH(ev, &ctx->events, ev_io_next) {
435*663afb9bSAndroid Build Coastguard Worker if (ev->ev_events & (events & ~EV_ET))
436*663afb9bSAndroid Build Coastguard Worker event_active_nolock_(ev, ev->ev_events & events, 1);
437*663afb9bSAndroid Build Coastguard Worker }
438*663afb9bSAndroid Build Coastguard Worker }
439*663afb9bSAndroid Build Coastguard Worker
440*663afb9bSAndroid Build Coastguard Worker /* code specific to signals */
441*663afb9bSAndroid Build Coastguard Worker
442*663afb9bSAndroid Build Coastguard Worker static void
evmap_signal_init(struct evmap_signal * entry)443*663afb9bSAndroid Build Coastguard Worker evmap_signal_init(struct evmap_signal *entry)
444*663afb9bSAndroid Build Coastguard Worker {
445*663afb9bSAndroid Build Coastguard Worker LIST_INIT(&entry->events);
446*663afb9bSAndroid Build Coastguard Worker }
447*663afb9bSAndroid Build Coastguard Worker
448*663afb9bSAndroid Build Coastguard Worker
449*663afb9bSAndroid Build Coastguard Worker int
evmap_signal_add_(struct event_base * base,int sig,struct event * ev)450*663afb9bSAndroid Build Coastguard Worker evmap_signal_add_(struct event_base *base, int sig, struct event *ev)
451*663afb9bSAndroid Build Coastguard Worker {
452*663afb9bSAndroid Build Coastguard Worker const struct eventop *evsel = base->evsigsel;
453*663afb9bSAndroid Build Coastguard Worker struct event_signal_map *map = &base->sigmap;
454*663afb9bSAndroid Build Coastguard Worker struct evmap_signal *ctx = NULL;
455*663afb9bSAndroid Build Coastguard Worker
456*663afb9bSAndroid Build Coastguard Worker if (sig < 0 || sig >= NSIG)
457*663afb9bSAndroid Build Coastguard Worker return (-1);
458*663afb9bSAndroid Build Coastguard Worker
459*663afb9bSAndroid Build Coastguard Worker if (sig >= map->nentries) {
460*663afb9bSAndroid Build Coastguard Worker if (evmap_make_space(
461*663afb9bSAndroid Build Coastguard Worker map, sig, sizeof(struct evmap_signal *)) == -1)
462*663afb9bSAndroid Build Coastguard Worker return (-1);
463*663afb9bSAndroid Build Coastguard Worker }
464*663afb9bSAndroid Build Coastguard Worker GET_SIGNAL_SLOT_AND_CTOR(ctx, map, sig, evmap_signal, evmap_signal_init,
465*663afb9bSAndroid Build Coastguard Worker base->evsigsel->fdinfo_len);
466*663afb9bSAndroid Build Coastguard Worker
467*663afb9bSAndroid Build Coastguard Worker if (LIST_EMPTY(&ctx->events)) {
468*663afb9bSAndroid Build Coastguard Worker if (evsel->add(base, ev->ev_fd, 0, EV_SIGNAL, NULL)
469*663afb9bSAndroid Build Coastguard Worker == -1)
470*663afb9bSAndroid Build Coastguard Worker return (-1);
471*663afb9bSAndroid Build Coastguard Worker }
472*663afb9bSAndroid Build Coastguard Worker
473*663afb9bSAndroid Build Coastguard Worker LIST_INSERT_HEAD(&ctx->events, ev, ev_signal_next);
474*663afb9bSAndroid Build Coastguard Worker
475*663afb9bSAndroid Build Coastguard Worker return (1);
476*663afb9bSAndroid Build Coastguard Worker }
477*663afb9bSAndroid Build Coastguard Worker
478*663afb9bSAndroid Build Coastguard Worker int
evmap_signal_del_(struct event_base * base,int sig,struct event * ev)479*663afb9bSAndroid Build Coastguard Worker evmap_signal_del_(struct event_base *base, int sig, struct event *ev)
480*663afb9bSAndroid Build Coastguard Worker {
481*663afb9bSAndroid Build Coastguard Worker const struct eventop *evsel = base->evsigsel;
482*663afb9bSAndroid Build Coastguard Worker struct event_signal_map *map = &base->sigmap;
483*663afb9bSAndroid Build Coastguard Worker struct evmap_signal *ctx;
484*663afb9bSAndroid Build Coastguard Worker
485*663afb9bSAndroid Build Coastguard Worker if (sig < 0 || sig >= map->nentries)
486*663afb9bSAndroid Build Coastguard Worker return (-1);
487*663afb9bSAndroid Build Coastguard Worker
488*663afb9bSAndroid Build Coastguard Worker GET_SIGNAL_SLOT(ctx, map, sig, evmap_signal);
489*663afb9bSAndroid Build Coastguard Worker
490*663afb9bSAndroid Build Coastguard Worker LIST_REMOVE(ev, ev_signal_next);
491*663afb9bSAndroid Build Coastguard Worker
492*663afb9bSAndroid Build Coastguard Worker if (LIST_FIRST(&ctx->events) == NULL) {
493*663afb9bSAndroid Build Coastguard Worker if (evsel->del(base, ev->ev_fd, 0, EV_SIGNAL, NULL) == -1)
494*663afb9bSAndroid Build Coastguard Worker return (-1);
495*663afb9bSAndroid Build Coastguard Worker }
496*663afb9bSAndroid Build Coastguard Worker
497*663afb9bSAndroid Build Coastguard Worker return (1);
498*663afb9bSAndroid Build Coastguard Worker }
499*663afb9bSAndroid Build Coastguard Worker
500*663afb9bSAndroid Build Coastguard Worker void
evmap_signal_active_(struct event_base * base,evutil_socket_t sig,int ncalls)501*663afb9bSAndroid Build Coastguard Worker evmap_signal_active_(struct event_base *base, evutil_socket_t sig, int ncalls)
502*663afb9bSAndroid Build Coastguard Worker {
503*663afb9bSAndroid Build Coastguard Worker struct event_signal_map *map = &base->sigmap;
504*663afb9bSAndroid Build Coastguard Worker struct evmap_signal *ctx;
505*663afb9bSAndroid Build Coastguard Worker struct event *ev;
506*663afb9bSAndroid Build Coastguard Worker
507*663afb9bSAndroid Build Coastguard Worker if (sig < 0 || sig >= map->nentries)
508*663afb9bSAndroid Build Coastguard Worker return;
509*663afb9bSAndroid Build Coastguard Worker GET_SIGNAL_SLOT(ctx, map, sig, evmap_signal);
510*663afb9bSAndroid Build Coastguard Worker
511*663afb9bSAndroid Build Coastguard Worker if (!ctx)
512*663afb9bSAndroid Build Coastguard Worker return;
513*663afb9bSAndroid Build Coastguard Worker LIST_FOREACH(ev, &ctx->events, ev_signal_next)
514*663afb9bSAndroid Build Coastguard Worker event_active_nolock_(ev, EV_SIGNAL, ncalls);
515*663afb9bSAndroid Build Coastguard Worker }
516*663afb9bSAndroid Build Coastguard Worker
517*663afb9bSAndroid Build Coastguard Worker void *
evmap_io_get_fdinfo_(struct event_io_map * map,evutil_socket_t fd)518*663afb9bSAndroid Build Coastguard Worker evmap_io_get_fdinfo_(struct event_io_map *map, evutil_socket_t fd)
519*663afb9bSAndroid Build Coastguard Worker {
520*663afb9bSAndroid Build Coastguard Worker struct evmap_io *ctx;
521*663afb9bSAndroid Build Coastguard Worker GET_IO_SLOT(ctx, map, fd, evmap_io);
522*663afb9bSAndroid Build Coastguard Worker if (ctx)
523*663afb9bSAndroid Build Coastguard Worker return ((char*)ctx) + sizeof(struct evmap_io);
524*663afb9bSAndroid Build Coastguard Worker else
525*663afb9bSAndroid Build Coastguard Worker return NULL;
526*663afb9bSAndroid Build Coastguard Worker }
527*663afb9bSAndroid Build Coastguard Worker
528*663afb9bSAndroid Build Coastguard Worker /* Callback type for evmap_io_foreach_fd */
529*663afb9bSAndroid Build Coastguard Worker typedef int (*evmap_io_foreach_fd_cb)(
530*663afb9bSAndroid Build Coastguard Worker struct event_base *, evutil_socket_t, struct evmap_io *, void *);
531*663afb9bSAndroid Build Coastguard Worker
532*663afb9bSAndroid Build Coastguard Worker /* Multipurpose helper function: Iterate over every file descriptor event_base
533*663afb9bSAndroid Build Coastguard Worker * for which we could have EV_READ or EV_WRITE events. For each such fd, call
534*663afb9bSAndroid Build Coastguard Worker * fn(base, signum, evmap_io, arg), where fn is the user-provided
535*663afb9bSAndroid Build Coastguard Worker * function, base is the event_base, signum is the signal number, evmap_io
536*663afb9bSAndroid Build Coastguard Worker * is an evmap_io structure containing a list of events pending on the
537*663afb9bSAndroid Build Coastguard Worker * file descriptor, and arg is the user-supplied argument.
538*663afb9bSAndroid Build Coastguard Worker *
539*663afb9bSAndroid Build Coastguard Worker * If fn returns 0, continue on to the next signal. Otherwise, return the same
540*663afb9bSAndroid Build Coastguard Worker * value that fn returned.
541*663afb9bSAndroid Build Coastguard Worker *
542*663afb9bSAndroid Build Coastguard Worker * Note that there is no guarantee that the file descriptors will be processed
543*663afb9bSAndroid Build Coastguard Worker * in any particular order.
544*663afb9bSAndroid Build Coastguard Worker */
545*663afb9bSAndroid Build Coastguard Worker static int
evmap_io_foreach_fd(struct event_base * base,evmap_io_foreach_fd_cb fn,void * arg)546*663afb9bSAndroid Build Coastguard Worker evmap_io_foreach_fd(struct event_base *base,
547*663afb9bSAndroid Build Coastguard Worker evmap_io_foreach_fd_cb fn,
548*663afb9bSAndroid Build Coastguard Worker void *arg)
549*663afb9bSAndroid Build Coastguard Worker {
550*663afb9bSAndroid Build Coastguard Worker evutil_socket_t fd;
551*663afb9bSAndroid Build Coastguard Worker struct event_io_map *iomap = &base->io;
552*663afb9bSAndroid Build Coastguard Worker int r = 0;
553*663afb9bSAndroid Build Coastguard Worker #ifdef EVMAP_USE_HT
554*663afb9bSAndroid Build Coastguard Worker struct event_map_entry **mapent;
555*663afb9bSAndroid Build Coastguard Worker HT_FOREACH(mapent, event_io_map, iomap) {
556*663afb9bSAndroid Build Coastguard Worker struct evmap_io *ctx = &(*mapent)->ent.evmap_io;
557*663afb9bSAndroid Build Coastguard Worker fd = (*mapent)->fd;
558*663afb9bSAndroid Build Coastguard Worker #else
559*663afb9bSAndroid Build Coastguard Worker for (fd = 0; fd < iomap->nentries; ++fd) {
560*663afb9bSAndroid Build Coastguard Worker struct evmap_io *ctx = iomap->entries[fd];
561*663afb9bSAndroid Build Coastguard Worker if (!ctx)
562*663afb9bSAndroid Build Coastguard Worker continue;
563*663afb9bSAndroid Build Coastguard Worker #endif
564*663afb9bSAndroid Build Coastguard Worker if ((r = fn(base, fd, ctx, arg)))
565*663afb9bSAndroid Build Coastguard Worker break;
566*663afb9bSAndroid Build Coastguard Worker }
567*663afb9bSAndroid Build Coastguard Worker return r;
568*663afb9bSAndroid Build Coastguard Worker }
569*663afb9bSAndroid Build Coastguard Worker
570*663afb9bSAndroid Build Coastguard Worker /* Callback type for evmap_signal_foreach_signal */
571*663afb9bSAndroid Build Coastguard Worker typedef int (*evmap_signal_foreach_signal_cb)(
572*663afb9bSAndroid Build Coastguard Worker struct event_base *, int, struct evmap_signal *, void *);
573*663afb9bSAndroid Build Coastguard Worker
574*663afb9bSAndroid Build Coastguard Worker /* Multipurpose helper function: Iterate over every signal number in the
575*663afb9bSAndroid Build Coastguard Worker * event_base for which we could have signal events. For each such signal,
576*663afb9bSAndroid Build Coastguard Worker * call fn(base, signum, evmap_signal, arg), where fn is the user-provided
577*663afb9bSAndroid Build Coastguard Worker * function, base is the event_base, signum is the signal number, evmap_signal
578*663afb9bSAndroid Build Coastguard Worker * is an evmap_signal structure containing a list of events pending on the
579*663afb9bSAndroid Build Coastguard Worker * signal, and arg is the user-supplied argument.
580*663afb9bSAndroid Build Coastguard Worker *
581*663afb9bSAndroid Build Coastguard Worker * If fn returns 0, continue on to the next signal. Otherwise, return the same
582*663afb9bSAndroid Build Coastguard Worker * value that fn returned.
583*663afb9bSAndroid Build Coastguard Worker */
584*663afb9bSAndroid Build Coastguard Worker static int
585*663afb9bSAndroid Build Coastguard Worker evmap_signal_foreach_signal(struct event_base *base,
586*663afb9bSAndroid Build Coastguard Worker evmap_signal_foreach_signal_cb fn,
587*663afb9bSAndroid Build Coastguard Worker void *arg)
588*663afb9bSAndroid Build Coastguard Worker {
589*663afb9bSAndroid Build Coastguard Worker struct event_signal_map *sigmap = &base->sigmap;
590*663afb9bSAndroid Build Coastguard Worker int r = 0;
591*663afb9bSAndroid Build Coastguard Worker int signum;
592*663afb9bSAndroid Build Coastguard Worker
593*663afb9bSAndroid Build Coastguard Worker for (signum = 0; signum < sigmap->nentries; ++signum) {
594*663afb9bSAndroid Build Coastguard Worker struct evmap_signal *ctx = sigmap->entries[signum];
595*663afb9bSAndroid Build Coastguard Worker if (!ctx)
596*663afb9bSAndroid Build Coastguard Worker continue;
597*663afb9bSAndroid Build Coastguard Worker if ((r = fn(base, signum, ctx, arg)))
598*663afb9bSAndroid Build Coastguard Worker break;
599*663afb9bSAndroid Build Coastguard Worker }
600*663afb9bSAndroid Build Coastguard Worker return r;
601*663afb9bSAndroid Build Coastguard Worker }
602*663afb9bSAndroid Build Coastguard Worker
603*663afb9bSAndroid Build Coastguard Worker /* Helper for evmap_reinit_: tell the backend to add every fd for which we have
604*663afb9bSAndroid Build Coastguard Worker * pending events, with the appropriate combination of EV_READ, EV_WRITE, and
605*663afb9bSAndroid Build Coastguard Worker * EV_ET. */
606*663afb9bSAndroid Build Coastguard Worker static int
607*663afb9bSAndroid Build Coastguard Worker evmap_io_reinit_iter_fn(struct event_base *base, evutil_socket_t fd,
608*663afb9bSAndroid Build Coastguard Worker struct evmap_io *ctx, void *arg)
609*663afb9bSAndroid Build Coastguard Worker {
610*663afb9bSAndroid Build Coastguard Worker const struct eventop *evsel = base->evsel;
611*663afb9bSAndroid Build Coastguard Worker void *extra;
612*663afb9bSAndroid Build Coastguard Worker int *result = arg;
613*663afb9bSAndroid Build Coastguard Worker short events = 0;
614*663afb9bSAndroid Build Coastguard Worker struct event *ev;
615*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(ctx);
616*663afb9bSAndroid Build Coastguard Worker
617*663afb9bSAndroid Build Coastguard Worker extra = ((char*)ctx) + sizeof(struct evmap_io);
618*663afb9bSAndroid Build Coastguard Worker if (ctx->nread)
619*663afb9bSAndroid Build Coastguard Worker events |= EV_READ;
620*663afb9bSAndroid Build Coastguard Worker if (ctx->nwrite)
621*663afb9bSAndroid Build Coastguard Worker events |= EV_WRITE;
622*663afb9bSAndroid Build Coastguard Worker if (ctx->nclose)
623*663afb9bSAndroid Build Coastguard Worker events |= EV_CLOSED;
624*663afb9bSAndroid Build Coastguard Worker if (evsel->fdinfo_len)
625*663afb9bSAndroid Build Coastguard Worker memset(extra, 0, evsel->fdinfo_len);
626*663afb9bSAndroid Build Coastguard Worker if (events &&
627*663afb9bSAndroid Build Coastguard Worker (ev = LIST_FIRST(&ctx->events)) &&
628*663afb9bSAndroid Build Coastguard Worker (ev->ev_events & EV_ET))
629*663afb9bSAndroid Build Coastguard Worker events |= EV_ET;
630*663afb9bSAndroid Build Coastguard Worker if (evsel->add(base, fd, 0, events, extra) == -1)
631*663afb9bSAndroid Build Coastguard Worker *result = -1;
632*663afb9bSAndroid Build Coastguard Worker
633*663afb9bSAndroid Build Coastguard Worker return 0;
634*663afb9bSAndroid Build Coastguard Worker }
635*663afb9bSAndroid Build Coastguard Worker
636*663afb9bSAndroid Build Coastguard Worker /* Helper for evmap_reinit_: tell the backend to add every signal for which we
637*663afb9bSAndroid Build Coastguard Worker * have pending events. */
638*663afb9bSAndroid Build Coastguard Worker static int
639*663afb9bSAndroid Build Coastguard Worker evmap_signal_reinit_iter_fn(struct event_base *base,
640*663afb9bSAndroid Build Coastguard Worker int signum, struct evmap_signal *ctx, void *arg)
641*663afb9bSAndroid Build Coastguard Worker {
642*663afb9bSAndroid Build Coastguard Worker const struct eventop *evsel = base->evsigsel;
643*663afb9bSAndroid Build Coastguard Worker int *result = arg;
644*663afb9bSAndroid Build Coastguard Worker
645*663afb9bSAndroid Build Coastguard Worker if (!LIST_EMPTY(&ctx->events)) {
646*663afb9bSAndroid Build Coastguard Worker if (evsel->add(base, signum, 0, EV_SIGNAL, NULL) == -1)
647*663afb9bSAndroid Build Coastguard Worker *result = -1;
648*663afb9bSAndroid Build Coastguard Worker }
649*663afb9bSAndroid Build Coastguard Worker return 0;
650*663afb9bSAndroid Build Coastguard Worker }
651*663afb9bSAndroid Build Coastguard Worker
652*663afb9bSAndroid Build Coastguard Worker int
653*663afb9bSAndroid Build Coastguard Worker evmap_reinit_(struct event_base *base)
654*663afb9bSAndroid Build Coastguard Worker {
655*663afb9bSAndroid Build Coastguard Worker int result = 0;
656*663afb9bSAndroid Build Coastguard Worker
657*663afb9bSAndroid Build Coastguard Worker evmap_io_foreach_fd(base, evmap_io_reinit_iter_fn, &result);
658*663afb9bSAndroid Build Coastguard Worker if (result < 0)
659*663afb9bSAndroid Build Coastguard Worker return -1;
660*663afb9bSAndroid Build Coastguard Worker evmap_signal_foreach_signal(base, evmap_signal_reinit_iter_fn, &result);
661*663afb9bSAndroid Build Coastguard Worker if (result < 0)
662*663afb9bSAndroid Build Coastguard Worker return -1;
663*663afb9bSAndroid Build Coastguard Worker return 0;
664*663afb9bSAndroid Build Coastguard Worker }
665*663afb9bSAndroid Build Coastguard Worker
666*663afb9bSAndroid Build Coastguard Worker /* Helper for evmap_delete_all_: delete every event in an event_dlist. */
667*663afb9bSAndroid Build Coastguard Worker static int
668*663afb9bSAndroid Build Coastguard Worker delete_all_in_dlist(struct event_dlist *dlist)
669*663afb9bSAndroid Build Coastguard Worker {
670*663afb9bSAndroid Build Coastguard Worker struct event *ev;
671*663afb9bSAndroid Build Coastguard Worker while ((ev = LIST_FIRST(dlist)))
672*663afb9bSAndroid Build Coastguard Worker event_del(ev);
673*663afb9bSAndroid Build Coastguard Worker return 0;
674*663afb9bSAndroid Build Coastguard Worker }
675*663afb9bSAndroid Build Coastguard Worker
676*663afb9bSAndroid Build Coastguard Worker /* Helper for evmap_delete_all_: delete every event pending on an fd. */
677*663afb9bSAndroid Build Coastguard Worker static int
678*663afb9bSAndroid Build Coastguard Worker evmap_io_delete_all_iter_fn(struct event_base *base, evutil_socket_t fd,
679*663afb9bSAndroid Build Coastguard Worker struct evmap_io *io_info, void *arg)
680*663afb9bSAndroid Build Coastguard Worker {
681*663afb9bSAndroid Build Coastguard Worker return delete_all_in_dlist(&io_info->events);
682*663afb9bSAndroid Build Coastguard Worker }
683*663afb9bSAndroid Build Coastguard Worker
684*663afb9bSAndroid Build Coastguard Worker /* Helper for evmap_delete_all_: delete every event pending on a signal. */
685*663afb9bSAndroid Build Coastguard Worker static int
686*663afb9bSAndroid Build Coastguard Worker evmap_signal_delete_all_iter_fn(struct event_base *base, int signum,
687*663afb9bSAndroid Build Coastguard Worker struct evmap_signal *sig_info, void *arg)
688*663afb9bSAndroid Build Coastguard Worker {
689*663afb9bSAndroid Build Coastguard Worker return delete_all_in_dlist(&sig_info->events);
690*663afb9bSAndroid Build Coastguard Worker }
691*663afb9bSAndroid Build Coastguard Worker
692*663afb9bSAndroid Build Coastguard Worker void
693*663afb9bSAndroid Build Coastguard Worker evmap_delete_all_(struct event_base *base)
694*663afb9bSAndroid Build Coastguard Worker {
695*663afb9bSAndroid Build Coastguard Worker evmap_signal_foreach_signal(base, evmap_signal_delete_all_iter_fn, NULL);
696*663afb9bSAndroid Build Coastguard Worker evmap_io_foreach_fd(base, evmap_io_delete_all_iter_fn, NULL);
697*663afb9bSAndroid Build Coastguard Worker }
698*663afb9bSAndroid Build Coastguard Worker
699*663afb9bSAndroid Build Coastguard Worker /** Per-fd structure for use with changelists. It keeps track, for each fd or
700*663afb9bSAndroid Build Coastguard Worker * signal using the changelist, of where its entry in the changelist is.
701*663afb9bSAndroid Build Coastguard Worker */
702*663afb9bSAndroid Build Coastguard Worker struct event_changelist_fdinfo {
703*663afb9bSAndroid Build Coastguard Worker int idxplus1; /* this is the index +1, so that memset(0) will make it
704*663afb9bSAndroid Build Coastguard Worker * a no-such-element */
705*663afb9bSAndroid Build Coastguard Worker };
706*663afb9bSAndroid Build Coastguard Worker
707*663afb9bSAndroid Build Coastguard Worker void
708*663afb9bSAndroid Build Coastguard Worker event_changelist_init_(struct event_changelist *changelist)
709*663afb9bSAndroid Build Coastguard Worker {
710*663afb9bSAndroid Build Coastguard Worker changelist->changes = NULL;
711*663afb9bSAndroid Build Coastguard Worker changelist->changes_size = 0;
712*663afb9bSAndroid Build Coastguard Worker changelist->n_changes = 0;
713*663afb9bSAndroid Build Coastguard Worker }
714*663afb9bSAndroid Build Coastguard Worker
715*663afb9bSAndroid Build Coastguard Worker /** Helper: return the changelist_fdinfo corresponding to a given change. */
716*663afb9bSAndroid Build Coastguard Worker static inline struct event_changelist_fdinfo *
717*663afb9bSAndroid Build Coastguard Worker event_change_get_fdinfo(struct event_base *base,
718*663afb9bSAndroid Build Coastguard Worker const struct event_change *change)
719*663afb9bSAndroid Build Coastguard Worker {
720*663afb9bSAndroid Build Coastguard Worker char *ptr;
721*663afb9bSAndroid Build Coastguard Worker if (change->read_change & EV_CHANGE_SIGNAL) {
722*663afb9bSAndroid Build Coastguard Worker struct evmap_signal *ctx;
723*663afb9bSAndroid Build Coastguard Worker GET_SIGNAL_SLOT(ctx, &base->sigmap, change->fd, evmap_signal);
724*663afb9bSAndroid Build Coastguard Worker ptr = ((char*)ctx) + sizeof(struct evmap_signal);
725*663afb9bSAndroid Build Coastguard Worker } else {
726*663afb9bSAndroid Build Coastguard Worker struct evmap_io *ctx;
727*663afb9bSAndroid Build Coastguard Worker GET_IO_SLOT(ctx, &base->io, change->fd, evmap_io);
728*663afb9bSAndroid Build Coastguard Worker ptr = ((char*)ctx) + sizeof(struct evmap_io);
729*663afb9bSAndroid Build Coastguard Worker }
730*663afb9bSAndroid Build Coastguard Worker return (void*)ptr;
731*663afb9bSAndroid Build Coastguard Worker }
732*663afb9bSAndroid Build Coastguard Worker
733*663afb9bSAndroid Build Coastguard Worker /** Callback helper for event_changelist_assert_ok */
734*663afb9bSAndroid Build Coastguard Worker static int
735*663afb9bSAndroid Build Coastguard Worker event_changelist_assert_ok_foreach_iter_fn(
736*663afb9bSAndroid Build Coastguard Worker struct event_base *base,
737*663afb9bSAndroid Build Coastguard Worker evutil_socket_t fd, struct evmap_io *io, void *arg)
738*663afb9bSAndroid Build Coastguard Worker {
739*663afb9bSAndroid Build Coastguard Worker struct event_changelist *changelist = &base->changelist;
740*663afb9bSAndroid Build Coastguard Worker struct event_changelist_fdinfo *f;
741*663afb9bSAndroid Build Coastguard Worker f = (void*)
742*663afb9bSAndroid Build Coastguard Worker ( ((char*)io) + sizeof(struct evmap_io) );
743*663afb9bSAndroid Build Coastguard Worker if (f->idxplus1) {
744*663afb9bSAndroid Build Coastguard Worker struct event_change *c = &changelist->changes[f->idxplus1 - 1];
745*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(c->fd == fd);
746*663afb9bSAndroid Build Coastguard Worker }
747*663afb9bSAndroid Build Coastguard Worker return 0;
748*663afb9bSAndroid Build Coastguard Worker }
749*663afb9bSAndroid Build Coastguard Worker
750*663afb9bSAndroid Build Coastguard Worker /** Make sure that the changelist is consistent with the evmap structures. */
751*663afb9bSAndroid Build Coastguard Worker static void
752*663afb9bSAndroid Build Coastguard Worker event_changelist_assert_ok(struct event_base *base)
753*663afb9bSAndroid Build Coastguard Worker {
754*663afb9bSAndroid Build Coastguard Worker int i;
755*663afb9bSAndroid Build Coastguard Worker struct event_changelist *changelist = &base->changelist;
756*663afb9bSAndroid Build Coastguard Worker
757*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(changelist->changes_size >= changelist->n_changes);
758*663afb9bSAndroid Build Coastguard Worker for (i = 0; i < changelist->n_changes; ++i) {
759*663afb9bSAndroid Build Coastguard Worker struct event_change *c = &changelist->changes[i];
760*663afb9bSAndroid Build Coastguard Worker struct event_changelist_fdinfo *f;
761*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(c->fd >= 0);
762*663afb9bSAndroid Build Coastguard Worker f = event_change_get_fdinfo(base, c);
763*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(f);
764*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(f->idxplus1 == i + 1);
765*663afb9bSAndroid Build Coastguard Worker }
766*663afb9bSAndroid Build Coastguard Worker
767*663afb9bSAndroid Build Coastguard Worker evmap_io_foreach_fd(base,
768*663afb9bSAndroid Build Coastguard Worker event_changelist_assert_ok_foreach_iter_fn,
769*663afb9bSAndroid Build Coastguard Worker NULL);
770*663afb9bSAndroid Build Coastguard Worker }
771*663afb9bSAndroid Build Coastguard Worker
772*663afb9bSAndroid Build Coastguard Worker #ifdef DEBUG_CHANGELIST
773*663afb9bSAndroid Build Coastguard Worker #define event_changelist_check(base) event_changelist_assert_ok((base))
774*663afb9bSAndroid Build Coastguard Worker #else
775*663afb9bSAndroid Build Coastguard Worker #define event_changelist_check(base) ((void)0)
776*663afb9bSAndroid Build Coastguard Worker #endif
777*663afb9bSAndroid Build Coastguard Worker
778*663afb9bSAndroid Build Coastguard Worker void
779*663afb9bSAndroid Build Coastguard Worker event_changelist_remove_all_(struct event_changelist *changelist,
780*663afb9bSAndroid Build Coastguard Worker struct event_base *base)
781*663afb9bSAndroid Build Coastguard Worker {
782*663afb9bSAndroid Build Coastguard Worker int i;
783*663afb9bSAndroid Build Coastguard Worker
784*663afb9bSAndroid Build Coastguard Worker event_changelist_check(base);
785*663afb9bSAndroid Build Coastguard Worker
786*663afb9bSAndroid Build Coastguard Worker for (i = 0; i < changelist->n_changes; ++i) {
787*663afb9bSAndroid Build Coastguard Worker struct event_change *ch = &changelist->changes[i];
788*663afb9bSAndroid Build Coastguard Worker struct event_changelist_fdinfo *fdinfo =
789*663afb9bSAndroid Build Coastguard Worker event_change_get_fdinfo(base, ch);
790*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(fdinfo->idxplus1 == i + 1);
791*663afb9bSAndroid Build Coastguard Worker fdinfo->idxplus1 = 0;
792*663afb9bSAndroid Build Coastguard Worker }
793*663afb9bSAndroid Build Coastguard Worker
794*663afb9bSAndroid Build Coastguard Worker changelist->n_changes = 0;
795*663afb9bSAndroid Build Coastguard Worker
796*663afb9bSAndroid Build Coastguard Worker event_changelist_check(base);
797*663afb9bSAndroid Build Coastguard Worker }
798*663afb9bSAndroid Build Coastguard Worker
799*663afb9bSAndroid Build Coastguard Worker void
800*663afb9bSAndroid Build Coastguard Worker event_changelist_freemem_(struct event_changelist *changelist)
801*663afb9bSAndroid Build Coastguard Worker {
802*663afb9bSAndroid Build Coastguard Worker if (changelist->changes)
803*663afb9bSAndroid Build Coastguard Worker mm_free(changelist->changes);
804*663afb9bSAndroid Build Coastguard Worker event_changelist_init_(changelist); /* zero it all out. */
805*663afb9bSAndroid Build Coastguard Worker }
806*663afb9bSAndroid Build Coastguard Worker
807*663afb9bSAndroid Build Coastguard Worker /** Increase the size of 'changelist' to hold more changes. */
808*663afb9bSAndroid Build Coastguard Worker static int
809*663afb9bSAndroid Build Coastguard Worker event_changelist_grow(struct event_changelist *changelist)
810*663afb9bSAndroid Build Coastguard Worker {
811*663afb9bSAndroid Build Coastguard Worker int new_size;
812*663afb9bSAndroid Build Coastguard Worker struct event_change *new_changes;
813*663afb9bSAndroid Build Coastguard Worker if (changelist->changes_size < 64)
814*663afb9bSAndroid Build Coastguard Worker new_size = 64;
815*663afb9bSAndroid Build Coastguard Worker else
816*663afb9bSAndroid Build Coastguard Worker new_size = changelist->changes_size * 2;
817*663afb9bSAndroid Build Coastguard Worker
818*663afb9bSAndroid Build Coastguard Worker new_changes = mm_realloc(changelist->changes,
819*663afb9bSAndroid Build Coastguard Worker new_size * sizeof(struct event_change));
820*663afb9bSAndroid Build Coastguard Worker
821*663afb9bSAndroid Build Coastguard Worker if (EVUTIL_UNLIKELY(new_changes == NULL))
822*663afb9bSAndroid Build Coastguard Worker return (-1);
823*663afb9bSAndroid Build Coastguard Worker
824*663afb9bSAndroid Build Coastguard Worker changelist->changes = new_changes;
825*663afb9bSAndroid Build Coastguard Worker changelist->changes_size = new_size;
826*663afb9bSAndroid Build Coastguard Worker
827*663afb9bSAndroid Build Coastguard Worker return (0);
828*663afb9bSAndroid Build Coastguard Worker }
829*663afb9bSAndroid Build Coastguard Worker
830*663afb9bSAndroid Build Coastguard Worker /** Return a pointer to the changelist entry for the file descriptor or signal
831*663afb9bSAndroid Build Coastguard Worker * 'fd', whose fdinfo is 'fdinfo'. If none exists, construct it, setting its
832*663afb9bSAndroid Build Coastguard Worker * old_events field to old_events.
833*663afb9bSAndroid Build Coastguard Worker */
834*663afb9bSAndroid Build Coastguard Worker static struct event_change *
835*663afb9bSAndroid Build Coastguard Worker event_changelist_get_or_construct(struct event_changelist *changelist,
836*663afb9bSAndroid Build Coastguard Worker evutil_socket_t fd,
837*663afb9bSAndroid Build Coastguard Worker short old_events,
838*663afb9bSAndroid Build Coastguard Worker struct event_changelist_fdinfo *fdinfo)
839*663afb9bSAndroid Build Coastguard Worker {
840*663afb9bSAndroid Build Coastguard Worker struct event_change *change;
841*663afb9bSAndroid Build Coastguard Worker
842*663afb9bSAndroid Build Coastguard Worker if (fdinfo->idxplus1 == 0) {
843*663afb9bSAndroid Build Coastguard Worker int idx;
844*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(changelist->n_changes <= changelist->changes_size);
845*663afb9bSAndroid Build Coastguard Worker
846*663afb9bSAndroid Build Coastguard Worker if (changelist->n_changes == changelist->changes_size) {
847*663afb9bSAndroid Build Coastguard Worker if (event_changelist_grow(changelist) < 0)
848*663afb9bSAndroid Build Coastguard Worker return NULL;
849*663afb9bSAndroid Build Coastguard Worker }
850*663afb9bSAndroid Build Coastguard Worker
851*663afb9bSAndroid Build Coastguard Worker idx = changelist->n_changes++;
852*663afb9bSAndroid Build Coastguard Worker change = &changelist->changes[idx];
853*663afb9bSAndroid Build Coastguard Worker fdinfo->idxplus1 = idx + 1;
854*663afb9bSAndroid Build Coastguard Worker
855*663afb9bSAndroid Build Coastguard Worker memset(change, 0, sizeof(struct event_change));
856*663afb9bSAndroid Build Coastguard Worker change->fd = fd;
857*663afb9bSAndroid Build Coastguard Worker change->old_events = old_events;
858*663afb9bSAndroid Build Coastguard Worker } else {
859*663afb9bSAndroid Build Coastguard Worker change = &changelist->changes[fdinfo->idxplus1 - 1];
860*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(change->fd == fd);
861*663afb9bSAndroid Build Coastguard Worker }
862*663afb9bSAndroid Build Coastguard Worker return change;
863*663afb9bSAndroid Build Coastguard Worker }
864*663afb9bSAndroid Build Coastguard Worker
865*663afb9bSAndroid Build Coastguard Worker int
866*663afb9bSAndroid Build Coastguard Worker event_changelist_add_(struct event_base *base, evutil_socket_t fd, short old, short events,
867*663afb9bSAndroid Build Coastguard Worker void *p)
868*663afb9bSAndroid Build Coastguard Worker {
869*663afb9bSAndroid Build Coastguard Worker struct event_changelist *changelist = &base->changelist;
870*663afb9bSAndroid Build Coastguard Worker struct event_changelist_fdinfo *fdinfo = p;
871*663afb9bSAndroid Build Coastguard Worker struct event_change *change;
872*663afb9bSAndroid Build Coastguard Worker ev_uint8_t evchange = EV_CHANGE_ADD | (events & (EV_ET|EV_PERSIST|EV_SIGNAL));
873*663afb9bSAndroid Build Coastguard Worker
874*663afb9bSAndroid Build Coastguard Worker event_changelist_check(base);
875*663afb9bSAndroid Build Coastguard Worker
876*663afb9bSAndroid Build Coastguard Worker change = event_changelist_get_or_construct(changelist, fd, old, fdinfo);
877*663afb9bSAndroid Build Coastguard Worker if (!change)
878*663afb9bSAndroid Build Coastguard Worker return -1;
879*663afb9bSAndroid Build Coastguard Worker
880*663afb9bSAndroid Build Coastguard Worker /* An add replaces any previous delete, but doesn't result in a no-op,
881*663afb9bSAndroid Build Coastguard Worker * since the delete might fail (because the fd had been closed since
882*663afb9bSAndroid Build Coastguard Worker * the last add, for instance. */
883*663afb9bSAndroid Build Coastguard Worker
884*663afb9bSAndroid Build Coastguard Worker if (events & (EV_READ|EV_SIGNAL))
885*663afb9bSAndroid Build Coastguard Worker change->read_change = evchange;
886*663afb9bSAndroid Build Coastguard Worker if (events & EV_WRITE)
887*663afb9bSAndroid Build Coastguard Worker change->write_change = evchange;
888*663afb9bSAndroid Build Coastguard Worker if (events & EV_CLOSED)
889*663afb9bSAndroid Build Coastguard Worker change->close_change = evchange;
890*663afb9bSAndroid Build Coastguard Worker
891*663afb9bSAndroid Build Coastguard Worker event_changelist_check(base);
892*663afb9bSAndroid Build Coastguard Worker return (0);
893*663afb9bSAndroid Build Coastguard Worker }
894*663afb9bSAndroid Build Coastguard Worker
895*663afb9bSAndroid Build Coastguard Worker int
896*663afb9bSAndroid Build Coastguard Worker event_changelist_del_(struct event_base *base, evutil_socket_t fd, short old, short events,
897*663afb9bSAndroid Build Coastguard Worker void *p)
898*663afb9bSAndroid Build Coastguard Worker {
899*663afb9bSAndroid Build Coastguard Worker struct event_changelist *changelist = &base->changelist;
900*663afb9bSAndroid Build Coastguard Worker struct event_changelist_fdinfo *fdinfo = p;
901*663afb9bSAndroid Build Coastguard Worker struct event_change *change;
902*663afb9bSAndroid Build Coastguard Worker ev_uint8_t del = EV_CHANGE_DEL | (events & EV_ET);
903*663afb9bSAndroid Build Coastguard Worker
904*663afb9bSAndroid Build Coastguard Worker event_changelist_check(base);
905*663afb9bSAndroid Build Coastguard Worker change = event_changelist_get_or_construct(changelist, fd, old, fdinfo);
906*663afb9bSAndroid Build Coastguard Worker event_changelist_check(base);
907*663afb9bSAndroid Build Coastguard Worker if (!change)
908*663afb9bSAndroid Build Coastguard Worker return -1;
909*663afb9bSAndroid Build Coastguard Worker
910*663afb9bSAndroid Build Coastguard Worker /* A delete on an event set that doesn't contain the event to be
911*663afb9bSAndroid Build Coastguard Worker deleted produces a no-op. This effectively emoves any previous
912*663afb9bSAndroid Build Coastguard Worker uncommitted add, rather than replacing it: on those platforms where
913*663afb9bSAndroid Build Coastguard Worker "add, delete, dispatch" is not the same as "no-op, dispatch", we
914*663afb9bSAndroid Build Coastguard Worker want the no-op behavior.
915*663afb9bSAndroid Build Coastguard Worker
916*663afb9bSAndroid Build Coastguard Worker If we have a no-op item, we could remove it it from the list
917*663afb9bSAndroid Build Coastguard Worker entirely, but really there's not much point: skipping the no-op
918*663afb9bSAndroid Build Coastguard Worker change when we do the dispatch later is far cheaper than rejuggling
919*663afb9bSAndroid Build Coastguard Worker the array now.
920*663afb9bSAndroid Build Coastguard Worker
921*663afb9bSAndroid Build Coastguard Worker As this stands, it also lets through deletions of events that are
922*663afb9bSAndroid Build Coastguard Worker not currently set.
923*663afb9bSAndroid Build Coastguard Worker */
924*663afb9bSAndroid Build Coastguard Worker
925*663afb9bSAndroid Build Coastguard Worker if (events & (EV_READ|EV_SIGNAL)) {
926*663afb9bSAndroid Build Coastguard Worker if (!(change->old_events & (EV_READ | EV_SIGNAL)))
927*663afb9bSAndroid Build Coastguard Worker change->read_change = 0;
928*663afb9bSAndroid Build Coastguard Worker else
929*663afb9bSAndroid Build Coastguard Worker change->read_change = del;
930*663afb9bSAndroid Build Coastguard Worker }
931*663afb9bSAndroid Build Coastguard Worker if (events & EV_WRITE) {
932*663afb9bSAndroid Build Coastguard Worker if (!(change->old_events & EV_WRITE))
933*663afb9bSAndroid Build Coastguard Worker change->write_change = 0;
934*663afb9bSAndroid Build Coastguard Worker else
935*663afb9bSAndroid Build Coastguard Worker change->write_change = del;
936*663afb9bSAndroid Build Coastguard Worker }
937*663afb9bSAndroid Build Coastguard Worker if (events & EV_CLOSED) {
938*663afb9bSAndroid Build Coastguard Worker if (!(change->old_events & EV_CLOSED))
939*663afb9bSAndroid Build Coastguard Worker change->close_change = 0;
940*663afb9bSAndroid Build Coastguard Worker else
941*663afb9bSAndroid Build Coastguard Worker change->close_change = del;
942*663afb9bSAndroid Build Coastguard Worker }
943*663afb9bSAndroid Build Coastguard Worker
944*663afb9bSAndroid Build Coastguard Worker event_changelist_check(base);
945*663afb9bSAndroid Build Coastguard Worker return (0);
946*663afb9bSAndroid Build Coastguard Worker }
947*663afb9bSAndroid Build Coastguard Worker
948*663afb9bSAndroid Build Coastguard Worker /* Helper for evmap_check_integrity_: verify that all of the events pending on
949*663afb9bSAndroid Build Coastguard Worker * given fd are set up correctly, and that the nread and nwrite counts on that
950*663afb9bSAndroid Build Coastguard Worker * fd are correct. */
951*663afb9bSAndroid Build Coastguard Worker static int
952*663afb9bSAndroid Build Coastguard Worker evmap_io_check_integrity_fn(struct event_base *base, evutil_socket_t fd,
953*663afb9bSAndroid Build Coastguard Worker struct evmap_io *io_info, void *arg)
954*663afb9bSAndroid Build Coastguard Worker {
955*663afb9bSAndroid Build Coastguard Worker struct event *ev;
956*663afb9bSAndroid Build Coastguard Worker int n_read = 0, n_write = 0, n_close = 0;
957*663afb9bSAndroid Build Coastguard Worker
958*663afb9bSAndroid Build Coastguard Worker /* First, make sure the list itself isn't corrupt. Otherwise,
959*663afb9bSAndroid Build Coastguard Worker * running LIST_FOREACH could be an exciting adventure. */
960*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT_LIST_OK(&io_info->events, event, ev_io_next);
961*663afb9bSAndroid Build Coastguard Worker
962*663afb9bSAndroid Build Coastguard Worker LIST_FOREACH(ev, &io_info->events, ev_io_next) {
963*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(ev->ev_flags & EVLIST_INSERTED);
964*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(ev->ev_fd == fd);
965*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(!(ev->ev_events & EV_SIGNAL));
966*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT((ev->ev_events & (EV_READ|EV_WRITE|EV_CLOSED)));
967*663afb9bSAndroid Build Coastguard Worker if (ev->ev_events & EV_READ)
968*663afb9bSAndroid Build Coastguard Worker ++n_read;
969*663afb9bSAndroid Build Coastguard Worker if (ev->ev_events & EV_WRITE)
970*663afb9bSAndroid Build Coastguard Worker ++n_write;
971*663afb9bSAndroid Build Coastguard Worker if (ev->ev_events & EV_CLOSED)
972*663afb9bSAndroid Build Coastguard Worker ++n_close;
973*663afb9bSAndroid Build Coastguard Worker }
974*663afb9bSAndroid Build Coastguard Worker
975*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(n_read == io_info->nread);
976*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(n_write == io_info->nwrite);
977*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(n_close == io_info->nclose);
978*663afb9bSAndroid Build Coastguard Worker
979*663afb9bSAndroid Build Coastguard Worker return 0;
980*663afb9bSAndroid Build Coastguard Worker }
981*663afb9bSAndroid Build Coastguard Worker
982*663afb9bSAndroid Build Coastguard Worker /* Helper for evmap_check_integrity_: verify that all of the events pending
983*663afb9bSAndroid Build Coastguard Worker * on given signal are set up correctly. */
984*663afb9bSAndroid Build Coastguard Worker static int
985*663afb9bSAndroid Build Coastguard Worker evmap_signal_check_integrity_fn(struct event_base *base,
986*663afb9bSAndroid Build Coastguard Worker int signum, struct evmap_signal *sig_info, void *arg)
987*663afb9bSAndroid Build Coastguard Worker {
988*663afb9bSAndroid Build Coastguard Worker struct event *ev;
989*663afb9bSAndroid Build Coastguard Worker /* First, make sure the list itself isn't corrupt. */
990*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT_LIST_OK(&sig_info->events, event, ev_signal_next);
991*663afb9bSAndroid Build Coastguard Worker
992*663afb9bSAndroid Build Coastguard Worker LIST_FOREACH(ev, &sig_info->events, ev_io_next) {
993*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(ev->ev_flags & EVLIST_INSERTED);
994*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(ev->ev_fd == signum);
995*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT((ev->ev_events & EV_SIGNAL));
996*663afb9bSAndroid Build Coastguard Worker EVUTIL_ASSERT(!(ev->ev_events & (EV_READ|EV_WRITE|EV_CLOSED)));
997*663afb9bSAndroid Build Coastguard Worker }
998*663afb9bSAndroid Build Coastguard Worker return 0;
999*663afb9bSAndroid Build Coastguard Worker }
1000*663afb9bSAndroid Build Coastguard Worker
1001*663afb9bSAndroid Build Coastguard Worker void
1002*663afb9bSAndroid Build Coastguard Worker evmap_check_integrity_(struct event_base *base)
1003*663afb9bSAndroid Build Coastguard Worker {
1004*663afb9bSAndroid Build Coastguard Worker evmap_io_foreach_fd(base, evmap_io_check_integrity_fn, NULL);
1005*663afb9bSAndroid Build Coastguard Worker evmap_signal_foreach_signal(base, evmap_signal_check_integrity_fn, NULL);
1006*663afb9bSAndroid Build Coastguard Worker
1007*663afb9bSAndroid Build Coastguard Worker if (base->evsel->add == event_changelist_add_)
1008*663afb9bSAndroid Build Coastguard Worker event_changelist_assert_ok(base);
1009*663afb9bSAndroid Build Coastguard Worker }
1010*663afb9bSAndroid Build Coastguard Worker
1011*663afb9bSAndroid Build Coastguard Worker /* Helper type for evmap_foreach_event_: Bundles a function to call on every
1012*663afb9bSAndroid Build Coastguard Worker * event, and the user-provided void* to use as its third argument. */
1013*663afb9bSAndroid Build Coastguard Worker struct evmap_foreach_event_helper {
1014*663afb9bSAndroid Build Coastguard Worker event_base_foreach_event_cb fn;
1015*663afb9bSAndroid Build Coastguard Worker void *arg;
1016*663afb9bSAndroid Build Coastguard Worker };
1017*663afb9bSAndroid Build Coastguard Worker
1018*663afb9bSAndroid Build Coastguard Worker /* Helper for evmap_foreach_event_: calls a provided function on every event
1019*663afb9bSAndroid Build Coastguard Worker * pending on a given fd. */
1020*663afb9bSAndroid Build Coastguard Worker static int
1021*663afb9bSAndroid Build Coastguard Worker evmap_io_foreach_event_fn(struct event_base *base, evutil_socket_t fd,
1022*663afb9bSAndroid Build Coastguard Worker struct evmap_io *io_info, void *arg)
1023*663afb9bSAndroid Build Coastguard Worker {
1024*663afb9bSAndroid Build Coastguard Worker struct evmap_foreach_event_helper *h = arg;
1025*663afb9bSAndroid Build Coastguard Worker struct event *ev;
1026*663afb9bSAndroid Build Coastguard Worker int r;
1027*663afb9bSAndroid Build Coastguard Worker LIST_FOREACH(ev, &io_info->events, ev_io_next) {
1028*663afb9bSAndroid Build Coastguard Worker if ((r = h->fn(base, ev, h->arg)))
1029*663afb9bSAndroid Build Coastguard Worker return r;
1030*663afb9bSAndroid Build Coastguard Worker }
1031*663afb9bSAndroid Build Coastguard Worker return 0;
1032*663afb9bSAndroid Build Coastguard Worker }
1033*663afb9bSAndroid Build Coastguard Worker
1034*663afb9bSAndroid Build Coastguard Worker /* Helper for evmap_foreach_event_: calls a provided function on every event
1035*663afb9bSAndroid Build Coastguard Worker * pending on a given signal. */
1036*663afb9bSAndroid Build Coastguard Worker static int
1037*663afb9bSAndroid Build Coastguard Worker evmap_signal_foreach_event_fn(struct event_base *base, int signum,
1038*663afb9bSAndroid Build Coastguard Worker struct evmap_signal *sig_info, void *arg)
1039*663afb9bSAndroid Build Coastguard Worker {
1040*663afb9bSAndroid Build Coastguard Worker struct event *ev;
1041*663afb9bSAndroid Build Coastguard Worker struct evmap_foreach_event_helper *h = arg;
1042*663afb9bSAndroid Build Coastguard Worker int r;
1043*663afb9bSAndroid Build Coastguard Worker LIST_FOREACH(ev, &sig_info->events, ev_signal_next) {
1044*663afb9bSAndroid Build Coastguard Worker if ((r = h->fn(base, ev, h->arg)))
1045*663afb9bSAndroid Build Coastguard Worker return r;
1046*663afb9bSAndroid Build Coastguard Worker }
1047*663afb9bSAndroid Build Coastguard Worker return 0;
1048*663afb9bSAndroid Build Coastguard Worker }
1049*663afb9bSAndroid Build Coastguard Worker
1050*663afb9bSAndroid Build Coastguard Worker int
1051*663afb9bSAndroid Build Coastguard Worker evmap_foreach_event_(struct event_base *base,
1052*663afb9bSAndroid Build Coastguard Worker event_base_foreach_event_cb fn, void *arg)
1053*663afb9bSAndroid Build Coastguard Worker {
1054*663afb9bSAndroid Build Coastguard Worker struct evmap_foreach_event_helper h;
1055*663afb9bSAndroid Build Coastguard Worker int r;
1056*663afb9bSAndroid Build Coastguard Worker h.fn = fn;
1057*663afb9bSAndroid Build Coastguard Worker h.arg = arg;
1058*663afb9bSAndroid Build Coastguard Worker if ((r = evmap_io_foreach_fd(base, evmap_io_foreach_event_fn, &h)))
1059*663afb9bSAndroid Build Coastguard Worker return r;
1060*663afb9bSAndroid Build Coastguard Worker return evmap_signal_foreach_signal(base, evmap_signal_foreach_event_fn, &h);
1061*663afb9bSAndroid Build Coastguard Worker }
1062*663afb9bSAndroid Build Coastguard Worker
1063