tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

evmap.c (29011B)


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