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