1e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/*
2e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson
3e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *
4e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * Redistribution and use in source and binary forms, with or without
5e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * modification, are permitted provided that the following conditions
6e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * are met:
7e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 1. Redistributions of source code must retain the above copyright
8e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *    notice, this list of conditions and the following disclaimer.
9e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 2. Redistributions in binary form must reproduce the above copyright
10e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *    notice, this list of conditions and the following disclaimer in the
11e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *    documentation and/or other materials provided with the distribution.
12e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 3. The name of the author may not be used to endorse or promote products
13e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *    derived from this software without specific prior written permission.
14e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley *
15e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */
26e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event2/event-config.h"
27e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
28e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef WIN32
29e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <winsock2.h>
30e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define WIN32_LEAN_AND_MEAN
31e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <windows.h>
32e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#undef WIN32_LEAN_AND_MEAN
33e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif
34e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <sys/types.h>
35e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#if !defined(WIN32) && defined(_EVENT_HAVE_SYS_TIME_H)
36e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <sys/time.h>
37e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif
38e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <sys/queue.h>
39e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <stdio.h>
40e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <stdlib.h>
41e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifndef WIN32
42e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <unistd.h>
43e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif
44e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <errno.h>
45e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <signal.h>
46e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <string.h>
47e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include <time.h>
48e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
49e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "event-internal.h"
50e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "evmap-internal.h"
51e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "mm-internal.h"
52e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#include "changelist-internal.h"
53e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
54e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/** An entry for an evmap_io list: notes all the events that want to read or
55e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	write on a given fd, and the number of each.
56e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley  */
57e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystruct evmap_io {
58e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_list events;
59e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	ev_uint16_t nread;
60e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	ev_uint16_t nwrite;
61e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley};
62e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
63e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* An entry for an evmap_signal list: notes all the events that want to know
64e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley   when a signal triggers. */
65e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystruct evmap_signal {
66e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_list events;
67e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley};
68e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
69e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* On some platforms, fds start at 0 and increment by 1 as they are
70e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley   allocated, and old numbers get used.  For these platforms, we
71e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley   implement io maps just like signal maps: as an array of pointers to
72e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley   struct evmap_io.  But on other platforms (windows), sockets are not
73e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley   0-indexed, not necessarily consecutive, and not necessarily reused.
74e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley   There, we use a hashtable to implement evmap_io.
75e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley*/
76e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef EVMAP_USE_HT
77e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystruct event_map_entry {
78e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	HT_ENTRY(event_map_entry) map_node;
79e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	evutil_socket_t fd;
80e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	union { /* This is a union in case we need to make more things that can
81e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			   be in the hashtable. */
82e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		struct evmap_io evmap_io;
83e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	} ent;
84e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley};
85e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
86e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Helper used by the event_io_map hashtable code; tries to return a good hash
87e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * of the fd in e->fd. */
88e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic inline unsigned
89e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyhashsocket(struct event_map_entry *e)
90e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
91e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	/* On win32, in practice, the low 2-3 bits of a SOCKET seem not to
92e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	 * matter.  Our hashtable implementation really likes low-order bits,
93e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	 * though, so let's do the rotate-and-add trick. */
94e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	unsigned h = (unsigned) e->fd;
95e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	h += (h >> 2) | (h << 30);
96e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	return h;
97e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
98e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
99e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Helper used by the event_io_map hashtable code; returns true iff e1 and e2
100e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * have the same e->fd. */
101e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic inline int
102e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyeqsocket(struct event_map_entry *e1, struct event_map_entry *e2)
103e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
104e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	return e1->fd == e2->fd;
105e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
106e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
107e867981d427db5e0b860d67485838e1f9e8c37daChristopher WileyHT_PROTOTYPE(event_io_map, event_map_entry, map_node, hashsocket, eqsocket)
108e867981d427db5e0b860d67485838e1f9e8c37daChristopher WileyHT_GENERATE(event_io_map, event_map_entry, map_node, hashsocket, eqsocket,
109e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			0.5, mm_malloc, mm_realloc, mm_free)
110e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
111e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define GET_IO_SLOT(x, map, slot, type)					\
112e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	do {								\
113e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		struct event_map_entry _key, *_ent;			\
114e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		_key.fd = slot;						\
115e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		_ent = HT_FIND(event_io_map, map, &_key);		\
116e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		(x) = _ent ? &_ent->ent.type : NULL;			\
117e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	} while (0);
118e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
119e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define GET_IO_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len)	\
120e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	do {								\
121e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		struct event_map_entry _key, *_ent;			\
122e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		_key.fd = slot;						\
123e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		_HT_FIND_OR_INSERT(event_io_map, map_node, hashsocket, map, \
124e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		    event_map_entry, &_key, ptr,			\
125e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		    {							\
126e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			    _ent = *ptr;				\
127e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		    },							\
128e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		    {							\
129e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			    _ent = mm_calloc(1,sizeof(struct event_map_entry)+fdinfo_len); \
130e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			    if (EVUTIL_UNLIKELY(_ent == NULL))		\
131e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley				    return (-1);			\
132e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			    _ent->fd = slot;				\
133e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			    (ctor)(&_ent->ent.type);			\
134e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			    _HT_FOI_INSERT(map_node, map, &_key, _ent, ptr) \
135e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley				});					\
136e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		(x) = &_ent->ent.type;					\
137e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	} while (0)
138e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
139e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid evmap_io_initmap(struct event_io_map *ctx)
140e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
141e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	HT_INIT(event_io_map, ctx);
142e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
143e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
144e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid evmap_io_clear(struct event_io_map *ctx)
145e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
146e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_map_entry **ent, **next, *this;
147e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	for (ent = HT_START(event_io_map, ctx); ent; ent = next) {
148e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		this = *ent;
149e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		next = HT_NEXT_RMV(event_io_map, ctx, ent);
150e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		mm_free(this);
151e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
152e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	HT_CLEAR(event_io_map, ctx); /* remove all storage held by the ctx. */
153e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
154e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif
155e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
156e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* Set the variable 'x' to the field in event_map 'map' with fields of type
157e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley   'struct type *' corresponding to the fd or signal 'slot'.  Set 'x' to NULL
158e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley   if there are no entries for 'slot'.  Does no bounds-checking. */
159e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define GET_SIGNAL_SLOT(x, map, slot, type)			\
160e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	(x) = (struct type *)((map)->entries[slot])
161e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* As GET_SLOT, but construct the entry for 'slot' if it is not present,
162e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley   by allocating enough memory for a 'struct type', and initializing the new
163e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley   value by calling the function 'ctor' on it.  Makes the function
164e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley   return -1 on allocation failure.
165e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */
166e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define GET_SIGNAL_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len)	\
167e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	do {								\
168e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if ((map)->entries[slot] == NULL) {			\
169e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			(map)->entries[slot] =				\
170e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			    mm_calloc(1,sizeof(struct type)+fdinfo_len); \
171e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			if (EVUTIL_UNLIKELY((map)->entries[slot] == NULL)) \
172e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley				return (-1);				\
173e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			(ctor)((struct type *)(map)->entries[slot]);	\
174e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		}							\
175e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		(x) = (struct type *)((map)->entries[slot]);		\
176e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	} while (0)
177e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
178e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* If we aren't using hashtables, then define the IO_SLOT macros and functions
179e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley   as thin aliases over the SIGNAL_SLOT versions. */
180e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifndef EVMAP_USE_HT
181e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define GET_IO_SLOT(x,map,slot,type) GET_SIGNAL_SLOT(x,map,slot,type)
182e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define GET_IO_SLOT_AND_CTOR(x,map,slot,type,ctor,fdinfo_len)	\
183e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	GET_SIGNAL_SLOT_AND_CTOR(x,map,slot,type,ctor,fdinfo_len)
184e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define FDINFO_OFFSET sizeof(struct evmap_io)
185e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid
186e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevmap_io_initmap(struct event_io_map* ctx)
187e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
188e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	evmap_signal_initmap(ctx);
189e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
190e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid
191e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevmap_io_clear(struct event_io_map* ctx)
192e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
193e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	evmap_signal_clear(ctx);
194e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
195e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif
196e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
197e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
198e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/** Expand 'map' with new entries of width 'msize' until it is big enough
199e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	to store a value in 'slot'.
200e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */
201e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int
202e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevmap_make_space(struct event_signal_map *map, int slot, int msize)
203e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
204e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (map->nentries <= slot) {
205e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		int nentries = map->nentries ? map->nentries : 32;
206e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		void **tmp;
207e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
208e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		while (nentries <= slot)
209e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			nentries <<= 1;
210e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
211e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		tmp = (void **)mm_realloc(map->entries, nentries * msize);
212e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (tmp == NULL)
213e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			return (-1);
214e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
215e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		memset(&tmp[map->nentries], 0,
216e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		    (nentries - map->nentries) * msize);
217e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
218e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		map->nentries = nentries;
219e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		map->entries = tmp;
220e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
221e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
222e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	return (0);
223e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
224e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
225e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid
226e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevmap_signal_initmap(struct event_signal_map *ctx)
227e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
228e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	ctx->nentries = 0;
229e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	ctx->entries = NULL;
230e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
231e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
232e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid
233e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevmap_signal_clear(struct event_signal_map *ctx)
234e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
235e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (ctx->entries != NULL) {
236e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		int i;
237e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		for (i = 0; i < ctx->nentries; ++i) {
238e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			if (ctx->entries[i] != NULL)
239e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley				mm_free(ctx->entries[i]);
240e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		}
241e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		mm_free(ctx->entries);
242e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		ctx->entries = NULL;
243e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
244e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	ctx->nentries = 0;
245e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
246e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
247e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
248e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* code specific to file descriptors */
249e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
250e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/** Constructor for struct evmap_io */
251e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void
252e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevmap_io_init(struct evmap_io *entry)
253e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
254e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	TAILQ_INIT(&entry->events);
255e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	entry->nread = 0;
256e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	entry->nwrite = 0;
257e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
258e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
259e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
260e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* return -1 on error, 0 on success if nothing changed in the event backend,
261e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * and 1 on success if something did. */
262e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint
263e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevmap_io_add(struct event_base *base, evutil_socket_t fd, struct event *ev)
264e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
265e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	const struct eventop *evsel = base->evsel;
266e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_io_map *io = &base->io;
267e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct evmap_io *ctx = NULL;
268e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	int nread, nwrite, retval = 0;
269e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	short res = 0, old = 0;
270e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event *old_ev;
271e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
272e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	EVUTIL_ASSERT(fd == ev->ev_fd);
273e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
274e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (fd < 0)
275e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		return 0;
276e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
277e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifndef EVMAP_USE_HT
278e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (fd >= io->nentries) {
279e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (evmap_make_space(io, fd, sizeof(struct evmap_io *)) == -1)
280e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			return (-1);
281e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
282e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif
283e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	GET_IO_SLOT_AND_CTOR(ctx, io, fd, evmap_io, evmap_io_init,
284e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley						 evsel->fdinfo_len);
285e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
286e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	nread = ctx->nread;
287e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	nwrite = ctx->nwrite;
288e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
289e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (nread)
290e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		old |= EV_READ;
291e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (nwrite)
292e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		old |= EV_WRITE;
293e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
294e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (ev->ev_events & EV_READ) {
295e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (++nread == 1)
296e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			res |= EV_READ;
297e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
298e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (ev->ev_events & EV_WRITE) {
299e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (++nwrite == 1)
300e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			res |= EV_WRITE;
301e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
302e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (EVUTIL_UNLIKELY(nread > 0xffff || nwrite > 0xffff)) {
303e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		event_warnx("Too many events reading or writing on fd %d",
304e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		    (int)fd);
305e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		return -1;
306e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
307e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (EVENT_DEBUG_MODE_IS_ON() &&
308e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	    (old_ev = TAILQ_FIRST(&ctx->events)) &&
309e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	    (old_ev->ev_events&EV_ET) != (ev->ev_events&EV_ET)) {
310e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		event_warnx("Tried to mix edge-triggered and non-edge-triggered"
311e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		    " events on fd %d", (int)fd);
312e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		return -1;
313e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
314e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
315e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (res) {
316e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		void *extra = ((char*)ctx) + sizeof(struct evmap_io);
317e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		/* XXX(niels): we cannot mix edge-triggered and
318e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		 * level-triggered, we should probably assert on
319e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		 * this. */
320e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (evsel->add(base, ev->ev_fd,
321e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			old, (ev->ev_events & EV_ET) | res, extra) == -1)
322e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			return (-1);
323e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		retval = 1;
324e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
325e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
326e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	ctx->nread = (ev_uint16_t) nread;
327e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	ctx->nwrite = (ev_uint16_t) nwrite;
328e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	TAILQ_INSERT_TAIL(&ctx->events, ev, ev_io_next);
329e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
330e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	return (retval);
331e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
332e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
333e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* return -1 on error, 0 on success if nothing changed in the event backend,
334e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * and 1 on success if something did. */
335e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint
336e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevmap_io_del(struct event_base *base, evutil_socket_t fd, struct event *ev)
337e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
338e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	const struct eventop *evsel = base->evsel;
339e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_io_map *io = &base->io;
340e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct evmap_io *ctx;
341e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	int nread, nwrite, retval = 0;
342e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	short res = 0, old = 0;
343e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
344e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (fd < 0)
345e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		return 0;
346e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
347e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	EVUTIL_ASSERT(fd == ev->ev_fd);
348e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
349e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifndef EVMAP_USE_HT
350e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (fd >= io->nentries)
351e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		return (-1);
352e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif
353e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
354e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	GET_IO_SLOT(ctx, io, fd, evmap_io);
355e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
356e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	nread = ctx->nread;
357e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	nwrite = ctx->nwrite;
358e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
359e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (nread)
360e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		old |= EV_READ;
361e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (nwrite)
362e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		old |= EV_WRITE;
363e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
364e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (ev->ev_events & EV_READ) {
365e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (--nread == 0)
366e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			res |= EV_READ;
367e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		EVUTIL_ASSERT(nread >= 0);
368e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
369e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (ev->ev_events & EV_WRITE) {
370e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (--nwrite == 0)
371e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			res |= EV_WRITE;
372e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		EVUTIL_ASSERT(nwrite >= 0);
373e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
374e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
375e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (res) {
376e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		void *extra = ((char*)ctx) + sizeof(struct evmap_io);
377e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (evsel->del(base, ev->ev_fd, old, res, extra) == -1)
378e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			return (-1);
379e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		retval = 1;
380e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
381e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
382e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	ctx->nread = nread;
383e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	ctx->nwrite = nwrite;
384e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	TAILQ_REMOVE(&ctx->events, ev, ev_io_next);
385e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
386e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	return (retval);
387e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
388e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
389e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid
390e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevmap_io_active(struct event_base *base, evutil_socket_t fd, short events)
391e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
392e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_io_map *io = &base->io;
393e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct evmap_io *ctx;
394e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event *ev;
395e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
396e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifndef EVMAP_USE_HT
397e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	EVUTIL_ASSERT(fd < io->nentries);
398e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif
399e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	GET_IO_SLOT(ctx, io, fd, evmap_io);
400e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
401e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	EVUTIL_ASSERT(ctx);
402e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	TAILQ_FOREACH(ev, &ctx->events, ev_io_next) {
403e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (ev->ev_events & events)
404e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			event_active_nolock(ev, ev->ev_events & events, 1);
405e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
406e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
407e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
408e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/* code specific to signals */
409e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
410e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void
411e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevmap_signal_init(struct evmap_signal *entry)
412e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
413e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	TAILQ_INIT(&entry->events);
414e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
415e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
416e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
417e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint
418e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevmap_signal_add(struct event_base *base, int sig, struct event *ev)
419e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
420e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	const struct eventop *evsel = base->evsigsel;
421e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_signal_map *map = &base->sigmap;
422e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct evmap_signal *ctx = NULL;
423e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
424e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (sig >= map->nentries) {
425e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (evmap_make_space(
426e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			map, sig, sizeof(struct evmap_signal *)) == -1)
427e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			return (-1);
428e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
429e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	GET_SIGNAL_SLOT_AND_CTOR(ctx, map, sig, evmap_signal, evmap_signal_init,
430e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	    base->evsigsel->fdinfo_len);
431e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
432e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (TAILQ_EMPTY(&ctx->events)) {
433e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (evsel->add(base, ev->ev_fd, 0, EV_SIGNAL, NULL)
434e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		    == -1)
435e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			return (-1);
436e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
437e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
438e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	TAILQ_INSERT_TAIL(&ctx->events, ev, ev_signal_next);
439e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
440e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	return (1);
441e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
442e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
443e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint
444e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevmap_signal_del(struct event_base *base, int sig, struct event *ev)
445e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
446e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	const struct eventop *evsel = base->evsigsel;
447e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_signal_map *map = &base->sigmap;
448e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct evmap_signal *ctx;
449e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
450e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (sig >= map->nentries)
451e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		return (-1);
452e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
453e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	GET_SIGNAL_SLOT(ctx, map, sig, evmap_signal);
454e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
455e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (TAILQ_FIRST(&ctx->events) == TAILQ_LAST(&ctx->events, event_list)) {
456e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (evsel->del(base, ev->ev_fd, 0, EV_SIGNAL, NULL) == -1)
457e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			return (-1);
458e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
459e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
460e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	TAILQ_REMOVE(&ctx->events, ev, ev_signal_next);
461e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
462e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	return (1);
463e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
464e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
465e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid
466e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevmap_signal_active(struct event_base *base, evutil_socket_t sig, int ncalls)
467e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
468e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_signal_map *map = &base->sigmap;
469e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct evmap_signal *ctx;
470e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event *ev;
471e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
472e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	EVUTIL_ASSERT(sig < map->nentries);
473e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	GET_SIGNAL_SLOT(ctx, map, sig, evmap_signal);
474e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
475e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	TAILQ_FOREACH(ev, &ctx->events, ev_signal_next)
476e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		event_active_nolock(ev, EV_SIGNAL, ncalls);
477e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
478e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
479e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid *
480e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevmap_io_get_fdinfo(struct event_io_map *map, evutil_socket_t fd)
481e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
482e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct evmap_io *ctx;
483e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	GET_IO_SLOT(ctx, map, fd, evmap_io);
484e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (ctx)
485e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		return ((char*)ctx) + sizeof(struct evmap_io);
486e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	else
487e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		return NULL;
488e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
489e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
490e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/** Per-fd structure for use with changelists.  It keeps track, for each fd or
491e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * signal using the changelist, of where its entry in the changelist is.
492e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */
493e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystruct event_changelist_fdinfo {
494e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	int idxplus1; /* this is the index +1, so that memset(0) will make it
495e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		       * a no-such-element */
496e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley};
497e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
498e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid
499e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevent_changelist_init(struct event_changelist *changelist)
500e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
501e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	changelist->changes = NULL;
502e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	changelist->changes_size = 0;
503e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	changelist->n_changes = 0;
504e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
505e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
506e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/** Helper: return the changelist_fdinfo corresponding to a given change. */
507e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic inline struct event_changelist_fdinfo *
508e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevent_change_get_fdinfo(struct event_base *base,
509e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley    const struct event_change *change)
510e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
511e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	char *ptr;
512e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (change->read_change & EV_CHANGE_SIGNAL) {
513e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		struct evmap_signal *ctx;
514e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		GET_SIGNAL_SLOT(ctx, &base->sigmap, change->fd, evmap_signal);
515e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		ptr = ((char*)ctx) + sizeof(struct evmap_signal);
516e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	} else {
517e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		struct evmap_io *ctx;
518e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		GET_IO_SLOT(ctx, &base->io, change->fd, evmap_io);
519e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		ptr = ((char*)ctx) + sizeof(struct evmap_io);
520e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
521e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	return (void*)ptr;
522e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
523e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
524e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef DEBUG_CHANGELIST
525e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/** Make sure that the changelist is consistent with the evmap structures. */
526e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic void
527e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevent_changelist_check(struct event_base *base)
528e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
529e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	int i;
530e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_changelist *changelist = &base->changelist;
531e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
532e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	EVUTIL_ASSERT(changelist->changes_size >= changelist->n_changes);
533e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	for (i = 0; i < changelist->n_changes; ++i) {
534e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		struct event_change *c = &changelist->changes[i];
535e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		struct event_changelist_fdinfo *f;
536e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		EVUTIL_ASSERT(c->fd >= 0);
537e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		f = event_change_get_fdinfo(base, c);
538e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		EVUTIL_ASSERT(f);
539e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		EVUTIL_ASSERT(f->idxplus1 == i + 1);
540e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
541e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
542e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	for (i = 0; i < base->io.nentries; ++i) {
543e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		struct evmap_io *io = base->io.entries[i];
544e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		struct event_changelist_fdinfo *f;
545e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (!io)
546e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			continue;
547e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		f = (void*)
548e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		    ( ((char*)io) + sizeof(struct evmap_io) );
549e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (f->idxplus1) {
550e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			struct event_change *c = &changelist->changes[f->idxplus1 - 1];
551e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			EVUTIL_ASSERT(c->fd == i);
552e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		}
553e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
554e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
555e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else
556e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define event_changelist_check(base)  ((void)0)
557e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif
558e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
559e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid
560e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevent_changelist_remove_all(struct event_changelist *changelist,
561e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley    struct event_base *base)
562e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
563e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	int i;
564e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
565e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	event_changelist_check(base);
566e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
567e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	for (i = 0; i < changelist->n_changes; ++i) {
568e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		struct event_change *ch = &changelist->changes[i];
569e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		struct event_changelist_fdinfo *fdinfo =
570e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		    event_change_get_fdinfo(base, ch);
571e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		EVUTIL_ASSERT(fdinfo->idxplus1 == i + 1);
572e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		fdinfo->idxplus1 = 0;
573e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
574e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
575e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	changelist->n_changes = 0;
576e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
577e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	event_changelist_check(base);
578e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
579e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
580e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid
581e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevent_changelist_freemem(struct event_changelist *changelist)
582e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
583e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (changelist->changes)
584e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		mm_free(changelist->changes);
585e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	event_changelist_init(changelist); /* zero it all out. */
586e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
587e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
588e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/** Increase the size of 'changelist' to hold more changes. */
589e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic int
590e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevent_changelist_grow(struct event_changelist *changelist)
591e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
592e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	int new_size;
593e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_change *new_changes;
594e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (changelist->changes_size < 64)
595e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		new_size = 64;
596e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	else
597e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		new_size = changelist->changes_size * 2;
598e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
599e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	new_changes = mm_realloc(changelist->changes,
600e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	    new_size * sizeof(struct event_change));
601e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
602e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (EVUTIL_UNLIKELY(new_changes == NULL))
603e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		return (-1);
604e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
605e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	changelist->changes = new_changes;
606e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	changelist->changes_size = new_size;
607e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
608e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	return (0);
609e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
610e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
611e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley/** Return a pointer to the changelist entry for the file descriptor or signal
612e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * 'fd', whose fdinfo is 'fdinfo'.  If none exists, construct it, setting its
613e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley * old_events field to old_events.
614e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley */
615e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileystatic struct event_change *
616e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevent_changelist_get_or_construct(struct event_changelist *changelist,
617e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley    evutil_socket_t fd,
618e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley    short old_events,
619e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley    struct event_changelist_fdinfo *fdinfo)
620e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
621e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_change *change;
622e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
623e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (fdinfo->idxplus1 == 0) {
624e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		int idx;
625e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		EVUTIL_ASSERT(changelist->n_changes <= changelist->changes_size);
626e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
627e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (changelist->n_changes == changelist->changes_size) {
628e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			if (event_changelist_grow(changelist) < 0)
629e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley				return NULL;
630e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		}
631e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
632e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		idx = changelist->n_changes++;
633e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		change = &changelist->changes[idx];
634e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		fdinfo->idxplus1 = idx + 1;
635e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
636e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		memset(change, 0, sizeof(struct event_change));
637e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		change->fd = fd;
638e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		change->old_events = old_events;
639e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	} else {
640e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		change = &changelist->changes[fdinfo->idxplus1 - 1];
641e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		EVUTIL_ASSERT(change->fd == fd);
642e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
643e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	return change;
644e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
645e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
646e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint
647e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevent_changelist_add(struct event_base *base, evutil_socket_t fd, short old, short events,
648e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley    void *p)
649e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
650e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_changelist *changelist = &base->changelist;
651e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_changelist_fdinfo *fdinfo = p;
652e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_change *change;
653e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
654e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	event_changelist_check(base);
655e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
656e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	change = event_changelist_get_or_construct(changelist, fd, old, fdinfo);
657e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (!change)
658e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		return -1;
659e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
660e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	/* An add replaces any previous delete, but doesn't result in a no-op,
661e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	 * since the delete might fail (because the fd had been closed since
662e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	 * the last add, for instance. */
663e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
664e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (events & (EV_READ|EV_SIGNAL)) {
665e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		change->read_change = EV_CHANGE_ADD |
666e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		    (events & (EV_ET|EV_PERSIST|EV_SIGNAL));
667e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
668e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (events & EV_WRITE) {
669e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		change->write_change = EV_CHANGE_ADD |
670e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		    (events & (EV_ET|EV_PERSIST|EV_SIGNAL));
671e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
672e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
673e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	event_changelist_check(base);
674e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	return (0);
675e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
676e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
677e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyint
678e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevent_changelist_del(struct event_base *base, evutil_socket_t fd, short old, short events,
679e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley    void *p)
680e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
681e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_changelist *changelist = &base->changelist;
682e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_changelist_fdinfo *fdinfo = p;
683e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_change *change;
684e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
685e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	event_changelist_check(base);
686e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	change = event_changelist_get_or_construct(changelist, fd, old, fdinfo);
687e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	event_changelist_check(base);
688e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (!change)
689e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		return -1;
690e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
691e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	/* A delete removes any previous add, rather than replacing it:
692e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	   on those platforms where "add, delete, dispatch" is not the same
693e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	   as "no-op, dispatch", we want the no-op behavior.
694e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
695e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	   As well as checking the current operation we should also check
696e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	   the original set of events to make sure were not ignoring
697e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	   the case where the add operation is present on an event that
698e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	   was already set.
699e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
700e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	   If we have a no-op item, we could remove it it from the list
701e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	   entirely, but really there's not much point: skipping the no-op
702e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	   change when we do the dispatch later is far cheaper than rejuggling
703e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	   the array now.
704e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
705e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	   As this stands, it also lets through deletions of events that are
706e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	   not currently set.
707e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	 */
708e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
709e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (events & (EV_READ|EV_SIGNAL)) {
710e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (!(change->old_events & (EV_READ | EV_SIGNAL)) &&
711e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		    (change->read_change & EV_CHANGE_ADD))
712e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			change->read_change = 0;
713e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		else
714e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			change->read_change = EV_CHANGE_DEL;
715e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
716e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	if (events & EV_WRITE) {
717e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (!(change->old_events & EV_WRITE) &&
718e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		    (change->write_change & EV_CHANGE_ADD))
719e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			change->write_change = 0;
720e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		else
721e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			change->write_change = EV_CHANGE_DEL;
722e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
723e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
724e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	event_changelist_check(base);
725e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	return (0);
726e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
727e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
728e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyvoid
729e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wileyevmap_check_integrity(struct event_base *base)
730e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley{
731e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define EVLIST_X_SIGFOUND 0x1000
732e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#define EVLIST_X_IOFOUND 0x2000
733e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
734e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	evutil_socket_t i;
735e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event *ev;
736e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_io_map *io = &base->io;
737e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_signal_map *sigmap = &base->sigmap;
738e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef EVMAP_USE_HT
739e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	struct event_map_entry **mapent;
740e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif
741e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	int nsignals, ntimers, nio;
742e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	nsignals = ntimers = nio = 0;
743e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
744e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
745e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		EVUTIL_ASSERT(ev->ev_flags & EVLIST_INSERTED);
746e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		EVUTIL_ASSERT(ev->ev_flags & EVLIST_INIT);
747e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		ev->ev_flags &= ~(EVLIST_X_SIGFOUND|EVLIST_X_IOFOUND);
748e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
749e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
750e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#ifdef EVMAP_USE_HT
751e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	HT_FOREACH(mapent, event_io_map, io) {
752e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		struct evmap_io *ctx = &(*mapent)->ent.evmap_io;
753e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		i = (*mapent)->fd;
754e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#else
755e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	for (i = 0; i < io->nentries; ++i) {
756e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		struct evmap_io *ctx = io->entries[i];
757e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
758e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (!ctx)
759e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			continue;
760e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley#endif
761e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
762e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		TAILQ_FOREACH(ev, &ctx->events, ev_io_next) {
763e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			EVUTIL_ASSERT(!(ev->ev_flags & EVLIST_X_IOFOUND));
764e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			EVUTIL_ASSERT(ev->ev_fd == i);
765e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			ev->ev_flags |= EVLIST_X_IOFOUND;
766e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			nio++;
767e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		}
768e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
769e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
770e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	for (i = 0; i < sigmap->nentries; ++i) {
771e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		struct evmap_signal *ctx = sigmap->entries[i];
772e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (!ctx)
773e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			continue;
774e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
775e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		TAILQ_FOREACH(ev, &ctx->events, ev_signal_next) {
776e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			EVUTIL_ASSERT(!(ev->ev_flags & EVLIST_X_SIGFOUND));
777e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			EVUTIL_ASSERT(ev->ev_fd == i);
778e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			ev->ev_flags |= EVLIST_X_SIGFOUND;
779e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			nsignals++;
780e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		}
781e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
782e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
783e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	TAILQ_FOREACH(ev, &base->eventqueue, ev_next) {
784e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (ev->ev_events & (EV_READ|EV_WRITE)) {
785e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			EVUTIL_ASSERT(ev->ev_flags & EVLIST_X_IOFOUND);
786e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			--nio;
787e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		}
788e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		if (ev->ev_events & EV_SIGNAL) {
789e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			EVUTIL_ASSERT(ev->ev_flags & EVLIST_X_SIGFOUND);
790e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley			--nsignals;
791e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley		}
792e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	}
793e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley
794e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	EVUTIL_ASSERT(nio == 0);
795e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	EVUTIL_ASSERT(nsignals == 0);
796e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	/* There is no "EVUTIL_ASSERT(ntimers == 0)": eventqueue is only for
797e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	 * pending signals and io events.
798e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley	 */
799e867981d427db5e0b860d67485838e1f9e8c37daChristopher Wiley}
800