diff options
author | dldmitry <dldmitry@yandex-team.ru> | 2022-02-10 16:47:18 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:47:18 +0300 |
commit | 7b11682e84e98d5d48de2807faa6fd392685ae7e (patch) | |
tree | 9814fbd1c3effac9b8377c5d604b367b14e2db55 /contrib/libs/libevent/evmap.c | |
parent | 10129030876638368b8965c627671fe44be079bc (diff) | |
download | ydb-7b11682e84e98d5d48de2807faa6fd392685ae7e.tar.gz |
Restoring authorship annotation for <dldmitry@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/libs/libevent/evmap.c')
-rw-r--r-- | contrib/libs/libevent/evmap.c | 1282 |
1 files changed, 641 insertions, 641 deletions
diff --git a/contrib/libs/libevent/evmap.c b/contrib/libs/libevent/evmap.c index bda36a4dce..e4e35c6877 100644 --- a/contrib/libs/libevent/evmap.c +++ b/contrib/libs/libevent/evmap.c @@ -1,530 +1,530 @@ -/* - * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -#include "event2/event-config.h" +/* + * Copyright (c) 2007-2012 Niels Provos and Nick Mathewson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "event2/event-config.h" #include "evconfig-private.h" - + #ifdef _WIN32 -#include <winsock2.h> -#define WIN32_LEAN_AND_MEAN -#include <windows.h> -#undef WIN32_LEAN_AND_MEAN -#endif -#include <sys/types.h> +#include <winsock2.h> +#define WIN32_LEAN_AND_MEAN +#include <windows.h> +#undef WIN32_LEAN_AND_MEAN +#endif +#include <sys/types.h> #if !defined(_WIN32) && defined(EVENT__HAVE_SYS_TIME_H) -#include <sys/time.h> -#endif -#include <sys/queue.h> -#include <stdio.h> -#include <stdlib.h> +#include <sys/time.h> +#endif +#include <sys/queue.h> +#include <stdio.h> +#include <stdlib.h> #ifndef _WIN32 -#include <unistd.h> -#endif -#include <errno.h> +#include <unistd.h> +#endif +#include <errno.h> #include <limits.h> -#include <signal.h> -#include <string.h> -#include <time.h> - -#include "event-internal.h" -#include "evmap-internal.h" -#include "mm-internal.h" -#include "changelist-internal.h" - -/** An entry for an evmap_io list: notes all the events that want to read or - write on a given fd, and the number of each. - */ -struct evmap_io { +#include <signal.h> +#include <string.h> +#include <time.h> + +#include "event-internal.h" +#include "evmap-internal.h" +#include "mm-internal.h" +#include "changelist-internal.h" + +/** An entry for an evmap_io list: notes all the events that want to read or + write on a given fd, and the number of each. + */ +struct evmap_io { struct event_dlist events; - ev_uint16_t nread; - ev_uint16_t nwrite; + ev_uint16_t nread; + ev_uint16_t nwrite; ev_uint16_t nclose; -}; - -/* An entry for an evmap_signal list: notes all the events that want to know - when a signal triggers. */ -struct evmap_signal { +}; + +/* An entry for an evmap_signal list: notes all the events that want to know + when a signal triggers. */ +struct evmap_signal { struct event_dlist events; -}; - -/* On some platforms, fds start at 0 and increment by 1 as they are - allocated, and old numbers get used. For these platforms, we - implement io maps just like signal maps: as an array of pointers to - struct evmap_io. But on other platforms (windows), sockets are not - 0-indexed, not necessarily consecutive, and not necessarily reused. - There, we use a hashtable to implement evmap_io. -*/ -#ifdef EVMAP_USE_HT -struct event_map_entry { - HT_ENTRY(event_map_entry) map_node; - evutil_socket_t fd; - union { /* This is a union in case we need to make more things that can - be in the hashtable. */ - struct evmap_io evmap_io; - } ent; -}; - -/* Helper used by the event_io_map hashtable code; tries to return a good hash - * of the fd in e->fd. */ -static inline unsigned -hashsocket(struct event_map_entry *e) -{ - /* On win32, in practice, the low 2-3 bits of a SOCKET seem not to - * matter. Our hashtable implementation really likes low-order bits, - * though, so let's do the rotate-and-add trick. */ - unsigned h = (unsigned) e->fd; - h += (h >> 2) | (h << 30); - return h; -} - -/* Helper used by the event_io_map hashtable code; returns true iff e1 and e2 - * have the same e->fd. */ -static inline int -eqsocket(struct event_map_entry *e1, struct event_map_entry *e2) -{ - return e1->fd == e2->fd; -} - -HT_PROTOTYPE(event_io_map, event_map_entry, map_node, hashsocket, eqsocket) -HT_GENERATE(event_io_map, event_map_entry, map_node, hashsocket, eqsocket, - 0.5, mm_malloc, mm_realloc, mm_free) - -#define GET_IO_SLOT(x, map, slot, type) \ - do { \ +}; + +/* On some platforms, fds start at 0 and increment by 1 as they are + allocated, and old numbers get used. For these platforms, we + implement io maps just like signal maps: as an array of pointers to + struct evmap_io. But on other platforms (windows), sockets are not + 0-indexed, not necessarily consecutive, and not necessarily reused. + There, we use a hashtable to implement evmap_io. +*/ +#ifdef EVMAP_USE_HT +struct event_map_entry { + HT_ENTRY(event_map_entry) map_node; + evutil_socket_t fd; + union { /* This is a union in case we need to make more things that can + be in the hashtable. */ + struct evmap_io evmap_io; + } ent; +}; + +/* Helper used by the event_io_map hashtable code; tries to return a good hash + * of the fd in e->fd. */ +static inline unsigned +hashsocket(struct event_map_entry *e) +{ + /* On win32, in practice, the low 2-3 bits of a SOCKET seem not to + * matter. Our hashtable implementation really likes low-order bits, + * though, so let's do the rotate-and-add trick. */ + unsigned h = (unsigned) e->fd; + h += (h >> 2) | (h << 30); + return h; +} + +/* Helper used by the event_io_map hashtable code; returns true iff e1 and e2 + * have the same e->fd. */ +static inline int +eqsocket(struct event_map_entry *e1, struct event_map_entry *e2) +{ + return e1->fd == e2->fd; +} + +HT_PROTOTYPE(event_io_map, event_map_entry, map_node, hashsocket, eqsocket) +HT_GENERATE(event_io_map, event_map_entry, map_node, hashsocket, eqsocket, + 0.5, mm_malloc, mm_realloc, mm_free) + +#define GET_IO_SLOT(x, map, slot, type) \ + do { \ struct event_map_entry key_, *ent_; \ key_.fd = slot; \ ent_ = HT_FIND(event_io_map, map, &key_); \ (x) = ent_ ? &ent_->ent.type : NULL; \ - } while (0); - -#define GET_IO_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len) \ - do { \ + } while (0); + +#define GET_IO_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len) \ + do { \ struct event_map_entry key_, *ent_; \ key_.fd = slot; \ HT_FIND_OR_INSERT_(event_io_map, map_node, hashsocket, map, \ event_map_entry, &key_, ptr, \ - { \ + { \ ent_ = *ptr; \ - }, \ - { \ + }, \ + { \ ent_ = mm_calloc(1,sizeof(struct event_map_entry)+fdinfo_len); \ if (EVUTIL_UNLIKELY(ent_ == NULL)) \ - return (-1); \ + return (-1); \ ent_->fd = slot; \ (ctor)(&ent_->ent.type); \ HT_FOI_INSERT_(map_node, map, &key_, ent_, ptr) \ - }); \ + }); \ (x) = &ent_->ent.type; \ - } while (0) - + } while (0) + void evmap_io_initmap_(struct event_io_map *ctx) -{ - HT_INIT(event_io_map, ctx); -} - +{ + HT_INIT(event_io_map, ctx); +} + void evmap_io_clear_(struct event_io_map *ctx) -{ - struct event_map_entry **ent, **next, *this; - for (ent = HT_START(event_io_map, ctx); ent; ent = next) { - this = *ent; - next = HT_NEXT_RMV(event_io_map, ctx, ent); - mm_free(this); - } - HT_CLEAR(event_io_map, ctx); /* remove all storage held by the ctx. */ -} -#endif - -/* Set the variable 'x' to the field in event_map 'map' with fields of type - 'struct type *' corresponding to the fd or signal 'slot'. Set 'x' to NULL - if there are no entries for 'slot'. Does no bounds-checking. */ -#define GET_SIGNAL_SLOT(x, map, slot, type) \ - (x) = (struct type *)((map)->entries[slot]) -/* As GET_SLOT, but construct the entry for 'slot' if it is not present, - by allocating enough memory for a 'struct type', and initializing the new - value by calling the function 'ctor' on it. Makes the function - return -1 on allocation failure. - */ -#define GET_SIGNAL_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len) \ - do { \ - if ((map)->entries[slot] == NULL) { \ - (map)->entries[slot] = \ - mm_calloc(1,sizeof(struct type)+fdinfo_len); \ - if (EVUTIL_UNLIKELY((map)->entries[slot] == NULL)) \ - return (-1); \ - (ctor)((struct type *)(map)->entries[slot]); \ - } \ - (x) = (struct type *)((map)->entries[slot]); \ - } while (0) - -/* If we aren't using hashtables, then define the IO_SLOT macros and functions - as thin aliases over the SIGNAL_SLOT versions. */ -#ifndef EVMAP_USE_HT -#define GET_IO_SLOT(x,map,slot,type) GET_SIGNAL_SLOT(x,map,slot,type) -#define GET_IO_SLOT_AND_CTOR(x,map,slot,type,ctor,fdinfo_len) \ - GET_SIGNAL_SLOT_AND_CTOR(x,map,slot,type,ctor,fdinfo_len) -#define FDINFO_OFFSET sizeof(struct evmap_io) -void +{ + struct event_map_entry **ent, **next, *this; + for (ent = HT_START(event_io_map, ctx); ent; ent = next) { + this = *ent; + next = HT_NEXT_RMV(event_io_map, ctx, ent); + mm_free(this); + } + HT_CLEAR(event_io_map, ctx); /* remove all storage held by the ctx. */ +} +#endif + +/* Set the variable 'x' to the field in event_map 'map' with fields of type + 'struct type *' corresponding to the fd or signal 'slot'. Set 'x' to NULL + if there are no entries for 'slot'. Does no bounds-checking. */ +#define GET_SIGNAL_SLOT(x, map, slot, type) \ + (x) = (struct type *)((map)->entries[slot]) +/* As GET_SLOT, but construct the entry for 'slot' if it is not present, + by allocating enough memory for a 'struct type', and initializing the new + value by calling the function 'ctor' on it. Makes the function + return -1 on allocation failure. + */ +#define GET_SIGNAL_SLOT_AND_CTOR(x, map, slot, type, ctor, fdinfo_len) \ + do { \ + if ((map)->entries[slot] == NULL) { \ + (map)->entries[slot] = \ + mm_calloc(1,sizeof(struct type)+fdinfo_len); \ + if (EVUTIL_UNLIKELY((map)->entries[slot] == NULL)) \ + return (-1); \ + (ctor)((struct type *)(map)->entries[slot]); \ + } \ + (x) = (struct type *)((map)->entries[slot]); \ + } while (0) + +/* If we aren't using hashtables, then define the IO_SLOT macros and functions + as thin aliases over the SIGNAL_SLOT versions. */ +#ifndef EVMAP_USE_HT +#define GET_IO_SLOT(x,map,slot,type) GET_SIGNAL_SLOT(x,map,slot,type) +#define GET_IO_SLOT_AND_CTOR(x,map,slot,type,ctor,fdinfo_len) \ + GET_SIGNAL_SLOT_AND_CTOR(x,map,slot,type,ctor,fdinfo_len) +#define FDINFO_OFFSET sizeof(struct evmap_io) +void evmap_io_initmap_(struct event_io_map* ctx) -{ +{ evmap_signal_initmap_(ctx); -} -void +} +void evmap_io_clear_(struct event_io_map* ctx) -{ +{ evmap_signal_clear_(ctx); -} -#endif - - -/** Expand 'map' with new entries of width 'msize' until it is big enough - to store a value in 'slot'. - */ -static int -evmap_make_space(struct event_signal_map *map, int slot, int msize) -{ - if (map->nentries <= slot) { - int nentries = map->nentries ? map->nentries : 32; - void **tmp; - +} +#endif + + +/** Expand 'map' with new entries of width 'msize' until it is big enough + to store a value in 'slot'. + */ +static int +evmap_make_space(struct event_signal_map *map, int slot, int msize) +{ + if (map->nentries <= slot) { + int nentries = map->nentries ? map->nentries : 32; + void **tmp; + if (slot > INT_MAX / 2) return (-1); - while (nentries <= slot) - nentries <<= 1; - + while (nentries <= slot) + nentries <<= 1; + if (nentries > INT_MAX / msize) return (-1); - tmp = (void **)mm_realloc(map->entries, nentries * msize); - if (tmp == NULL) - return (-1); - - memset(&tmp[map->nentries], 0, - (nentries - map->nentries) * msize); - - map->nentries = nentries; - map->entries = tmp; - } - - return (0); -} - -void + tmp = (void **)mm_realloc(map->entries, nentries * msize); + if (tmp == NULL) + return (-1); + + memset(&tmp[map->nentries], 0, + (nentries - map->nentries) * msize); + + map->nentries = nentries; + map->entries = tmp; + } + + return (0); +} + +void evmap_signal_initmap_(struct event_signal_map *ctx) -{ - ctx->nentries = 0; - ctx->entries = NULL; -} - -void +{ + ctx->nentries = 0; + ctx->entries = NULL; +} + +void evmap_signal_clear_(struct event_signal_map *ctx) -{ - if (ctx->entries != NULL) { - int i; - for (i = 0; i < ctx->nentries; ++i) { - if (ctx->entries[i] != NULL) - mm_free(ctx->entries[i]); - } - mm_free(ctx->entries); - ctx->entries = NULL; - } - ctx->nentries = 0; -} - - -/* code specific to file descriptors */ - -/** Constructor for struct evmap_io */ -static void -evmap_io_init(struct evmap_io *entry) -{ +{ + if (ctx->entries != NULL) { + int i; + for (i = 0; i < ctx->nentries; ++i) { + if (ctx->entries[i] != NULL) + mm_free(ctx->entries[i]); + } + mm_free(ctx->entries); + ctx->entries = NULL; + } + ctx->nentries = 0; +} + + +/* code specific to file descriptors */ + +/** Constructor for struct evmap_io */ +static void +evmap_io_init(struct evmap_io *entry) +{ LIST_INIT(&entry->events); - entry->nread = 0; - entry->nwrite = 0; + entry->nread = 0; + entry->nwrite = 0; entry->nclose = 0; -} - - -/* return -1 on error, 0 on success if nothing changed in the event backend, - * and 1 on success if something did. */ -int +} + + +/* return -1 on error, 0 on success if nothing changed in the event backend, + * and 1 on success if something did. */ +int evmap_io_add_(struct event_base *base, evutil_socket_t fd, struct event *ev) -{ - const struct eventop *evsel = base->evsel; - struct event_io_map *io = &base->io; - struct evmap_io *ctx = NULL; +{ + const struct eventop *evsel = base->evsel; + struct event_io_map *io = &base->io; + struct evmap_io *ctx = NULL; int nread, nwrite, nclose, retval = 0; - short res = 0, old = 0; - struct event *old_ev; - - EVUTIL_ASSERT(fd == ev->ev_fd); - - if (fd < 0) - return 0; - -#ifndef EVMAP_USE_HT - if (fd >= io->nentries) { - if (evmap_make_space(io, fd, sizeof(struct evmap_io *)) == -1) - return (-1); - } -#endif - GET_IO_SLOT_AND_CTOR(ctx, io, fd, evmap_io, evmap_io_init, - evsel->fdinfo_len); - - nread = ctx->nread; - nwrite = ctx->nwrite; + short res = 0, old = 0; + struct event *old_ev; + + EVUTIL_ASSERT(fd == ev->ev_fd); + + if (fd < 0) + return 0; + +#ifndef EVMAP_USE_HT + if (fd >= io->nentries) { + if (evmap_make_space(io, fd, sizeof(struct evmap_io *)) == -1) + return (-1); + } +#endif + GET_IO_SLOT_AND_CTOR(ctx, io, fd, evmap_io, evmap_io_init, + evsel->fdinfo_len); + + nread = ctx->nread; + nwrite = ctx->nwrite; nclose = ctx->nclose; - - if (nread) - old |= EV_READ; - if (nwrite) - old |= EV_WRITE; + + if (nread) + old |= EV_READ; + if (nwrite) + old |= EV_WRITE; if (nclose) old |= EV_CLOSED; - - if (ev->ev_events & EV_READ) { - if (++nread == 1) - res |= EV_READ; - } - if (ev->ev_events & EV_WRITE) { - if (++nwrite == 1) - res |= EV_WRITE; - } + + if (ev->ev_events & EV_READ) { + if (++nread == 1) + res |= EV_READ; + } + if (ev->ev_events & EV_WRITE) { + if (++nwrite == 1) + res |= EV_WRITE; + } if (ev->ev_events & EV_CLOSED) { if (++nclose == 1) res |= EV_CLOSED; } if (EVUTIL_UNLIKELY(nread > 0xffff || nwrite > 0xffff || nclose > 0xffff)) { - event_warnx("Too many events reading or writing on fd %d", - (int)fd); - return -1; - } - if (EVENT_DEBUG_MODE_IS_ON() && + event_warnx("Too many events reading or writing on fd %d", + (int)fd); + return -1; + } + if (EVENT_DEBUG_MODE_IS_ON() && (old_ev = LIST_FIRST(&ctx->events)) && - (old_ev->ev_events&EV_ET) != (ev->ev_events&EV_ET)) { - event_warnx("Tried to mix edge-triggered and non-edge-triggered" - " events on fd %d", (int)fd); - return -1; - } - - if (res) { - void *extra = ((char*)ctx) + sizeof(struct evmap_io); - /* XXX(niels): we cannot mix edge-triggered and - * level-triggered, we should probably assert on - * this. */ - if (evsel->add(base, ev->ev_fd, - old, (ev->ev_events & EV_ET) | res, extra) == -1) - return (-1); - retval = 1; - } - - ctx->nread = (ev_uint16_t) nread; - ctx->nwrite = (ev_uint16_t) nwrite; + (old_ev->ev_events&EV_ET) != (ev->ev_events&EV_ET)) { + event_warnx("Tried to mix edge-triggered and non-edge-triggered" + " events on fd %d", (int)fd); + return -1; + } + + if (res) { + void *extra = ((char*)ctx) + sizeof(struct evmap_io); + /* XXX(niels): we cannot mix edge-triggered and + * level-triggered, we should probably assert on + * this. */ + if (evsel->add(base, ev->ev_fd, + old, (ev->ev_events & EV_ET) | res, extra) == -1) + return (-1); + retval = 1; + } + + ctx->nread = (ev_uint16_t) nread; + ctx->nwrite = (ev_uint16_t) nwrite; ctx->nclose = (ev_uint16_t) nclose; LIST_INSERT_HEAD(&ctx->events, ev, ev_io_next); - - return (retval); -} - -/* return -1 on error, 0 on success if nothing changed in the event backend, - * and 1 on success if something did. */ -int + + return (retval); +} + +/* return -1 on error, 0 on success if nothing changed in the event backend, + * and 1 on success if something did. */ +int evmap_io_del_(struct event_base *base, evutil_socket_t fd, struct event *ev) -{ - const struct eventop *evsel = base->evsel; - struct event_io_map *io = &base->io; - struct evmap_io *ctx; +{ + const struct eventop *evsel = base->evsel; + struct event_io_map *io = &base->io; + struct evmap_io *ctx; int nread, nwrite, nclose, retval = 0; - short res = 0, old = 0; - - if (fd < 0) - return 0; - - EVUTIL_ASSERT(fd == ev->ev_fd); - -#ifndef EVMAP_USE_HT - if (fd >= io->nentries) - return (-1); -#endif - - GET_IO_SLOT(ctx, io, fd, evmap_io); - - nread = ctx->nread; - nwrite = ctx->nwrite; + short res = 0, old = 0; + + if (fd < 0) + return 0; + + EVUTIL_ASSERT(fd == ev->ev_fd); + +#ifndef EVMAP_USE_HT + if (fd >= io->nentries) + return (-1); +#endif + + GET_IO_SLOT(ctx, io, fd, evmap_io); + + nread = ctx->nread; + nwrite = ctx->nwrite; nclose = ctx->nclose; - - if (nread) - old |= EV_READ; - if (nwrite) - old |= EV_WRITE; + + if (nread) + old |= EV_READ; + if (nwrite) + old |= EV_WRITE; if (nclose) old |= EV_CLOSED; - - if (ev->ev_events & EV_READ) { - if (--nread == 0) - res |= EV_READ; - EVUTIL_ASSERT(nread >= 0); - } - if (ev->ev_events & EV_WRITE) { - if (--nwrite == 0) - res |= EV_WRITE; - EVUTIL_ASSERT(nwrite >= 0); - } + + if (ev->ev_events & EV_READ) { + if (--nread == 0) + res |= EV_READ; + EVUTIL_ASSERT(nread >= 0); + } + if (ev->ev_events & EV_WRITE) { + if (--nwrite == 0) + res |= EV_WRITE; + EVUTIL_ASSERT(nwrite >= 0); + } if (ev->ev_events & EV_CLOSED) { if (--nclose == 0) res |= EV_CLOSED; EVUTIL_ASSERT(nclose >= 0); } - - if (res) { - void *extra = ((char*)ctx) + sizeof(struct evmap_io); + + if (res) { + void *extra = ((char*)ctx) + sizeof(struct evmap_io); if (evsel->del(base, ev->ev_fd, old, (ev->ev_events & EV_ET) | res, extra) == -1) { retval = -1; } else { retval = 1; } - } - - ctx->nread = nread; - ctx->nwrite = nwrite; + } + + ctx->nread = nread; + ctx->nwrite = nwrite; ctx->nclose = nclose; LIST_REMOVE(ev, ev_io_next); - - return (retval); -} - -void + + return (retval); +} + +void evmap_io_active_(struct event_base *base, evutil_socket_t fd, short events) -{ - struct event_io_map *io = &base->io; - struct evmap_io *ctx; - struct event *ev; - -#ifndef EVMAP_USE_HT +{ + struct event_io_map *io = &base->io; + struct evmap_io *ctx; + struct event *ev; + +#ifndef EVMAP_USE_HT if (fd < 0 || fd >= io->nentries) return; -#endif - GET_IO_SLOT(ctx, io, fd, evmap_io); - +#endif + GET_IO_SLOT(ctx, io, fd, evmap_io); + if (NULL == ctx) return; LIST_FOREACH(ev, &ctx->events, ev_io_next) { if (ev->ev_events & (events & ~EV_ET)) event_active_nolock_(ev, ev->ev_events & events, 1); - } -} - -/* code specific to signals */ - -static void -evmap_signal_init(struct evmap_signal *entry) -{ + } +} + +/* code specific to signals */ + +static void +evmap_signal_init(struct evmap_signal *entry) +{ LIST_INIT(&entry->events); -} - - -int +} + + +int evmap_signal_add_(struct event_base *base, int sig, struct event *ev) -{ - const struct eventop *evsel = base->evsigsel; - struct event_signal_map *map = &base->sigmap; - struct evmap_signal *ctx = NULL; - +{ + const struct eventop *evsel = base->evsigsel; + struct event_signal_map *map = &base->sigmap; + struct evmap_signal *ctx = NULL; + if (sig < 0 || sig >= NSIG) return (-1); - if (sig >= map->nentries) { - if (evmap_make_space( - map, sig, sizeof(struct evmap_signal *)) == -1) - return (-1); - } - GET_SIGNAL_SLOT_AND_CTOR(ctx, map, sig, evmap_signal, evmap_signal_init, - base->evsigsel->fdinfo_len); - + if (sig >= map->nentries) { + if (evmap_make_space( + map, sig, sizeof(struct evmap_signal *)) == -1) + return (-1); + } + GET_SIGNAL_SLOT_AND_CTOR(ctx, map, sig, evmap_signal, evmap_signal_init, + base->evsigsel->fdinfo_len); + if (LIST_EMPTY(&ctx->events)) { - if (evsel->add(base, ev->ev_fd, 0, EV_SIGNAL, NULL) - == -1) - return (-1); - } - + if (evsel->add(base, ev->ev_fd, 0, EV_SIGNAL, NULL) + == -1) + return (-1); + } + LIST_INSERT_HEAD(&ctx->events, ev, ev_signal_next); - - return (1); -} - -int + + return (1); +} + +int evmap_signal_del_(struct event_base *base, int sig, struct event *ev) -{ - const struct eventop *evsel = base->evsigsel; - struct event_signal_map *map = &base->sigmap; - struct evmap_signal *ctx; - +{ + const struct eventop *evsel = base->evsigsel; + struct event_signal_map *map = &base->sigmap; + struct evmap_signal *ctx; + if (sig < 0 || sig >= map->nentries) - return (-1); - - GET_SIGNAL_SLOT(ctx, map, sig, evmap_signal); - + return (-1); + + GET_SIGNAL_SLOT(ctx, map, sig, evmap_signal); + LIST_REMOVE(ev, ev_signal_next); if (LIST_FIRST(&ctx->events) == NULL) { - if (evsel->del(base, ev->ev_fd, 0, EV_SIGNAL, NULL) == -1) - return (-1); - } - - return (1); -} - -void + if (evsel->del(base, ev->ev_fd, 0, EV_SIGNAL, NULL) == -1) + return (-1); + } + + return (1); +} + +void evmap_signal_active_(struct event_base *base, evutil_socket_t sig, int ncalls) -{ - struct event_signal_map *map = &base->sigmap; - struct evmap_signal *ctx; - struct event *ev; - +{ + struct event_signal_map *map = &base->sigmap; + struct evmap_signal *ctx; + struct event *ev; + if (sig < 0 || sig >= map->nentries) return; - GET_SIGNAL_SLOT(ctx, map, sig, evmap_signal); - + GET_SIGNAL_SLOT(ctx, map, sig, evmap_signal); + if (!ctx) return; LIST_FOREACH(ev, &ctx->events, ev_signal_next) event_active_nolock_(ev, EV_SIGNAL, ncalls); -} - -void * +} + +void * evmap_io_get_fdinfo_(struct event_io_map *map, evutil_socket_t fd) -{ - struct evmap_io *ctx; - GET_IO_SLOT(ctx, map, fd, evmap_io); - if (ctx) - return ((char*)ctx) + sizeof(struct evmap_io); - else - return NULL; -} - +{ + struct evmap_io *ctx; + GET_IO_SLOT(ctx, map, fd, evmap_io); + if (ctx) + return ((char*)ctx) + sizeof(struct evmap_io); + else + return NULL; +} + /* Callback type for evmap_io_foreach_fd */ typedef int (*evmap_io_foreach_fd_cb)( struct event_base *, evutil_socket_t, struct evmap_io *, void *); @@ -696,40 +696,40 @@ evmap_delete_all_(struct event_base *base) evmap_io_foreach_fd(base, evmap_io_delete_all_iter_fn, NULL); } -/** Per-fd structure for use with changelists. It keeps track, for each fd or - * signal using the changelist, of where its entry in the changelist is. - */ -struct event_changelist_fdinfo { - int idxplus1; /* this is the index +1, so that memset(0) will make it - * a no-such-element */ -}; - -void +/** Per-fd structure for use with changelists. It keeps track, for each fd or + * signal using the changelist, of where its entry in the changelist is. + */ +struct event_changelist_fdinfo { + int idxplus1; /* this is the index +1, so that memset(0) will make it + * a no-such-element */ +}; + +void event_changelist_init_(struct event_changelist *changelist) -{ - changelist->changes = NULL; - changelist->changes_size = 0; - changelist->n_changes = 0; -} - -/** Helper: return the changelist_fdinfo corresponding to a given change. */ -static inline struct event_changelist_fdinfo * -event_change_get_fdinfo(struct event_base *base, - const struct event_change *change) -{ - char *ptr; - if (change->read_change & EV_CHANGE_SIGNAL) { - struct evmap_signal *ctx; - GET_SIGNAL_SLOT(ctx, &base->sigmap, change->fd, evmap_signal); - ptr = ((char*)ctx) + sizeof(struct evmap_signal); - } else { - struct evmap_io *ctx; - GET_IO_SLOT(ctx, &base->io, change->fd, evmap_io); - ptr = ((char*)ctx) + sizeof(struct evmap_io); - } - return (void*)ptr; -} - +{ + changelist->changes = NULL; + changelist->changes_size = 0; + changelist->n_changes = 0; +} + +/** Helper: return the changelist_fdinfo corresponding to a given change. */ +static inline struct event_changelist_fdinfo * +event_change_get_fdinfo(struct event_base *base, + const struct event_change *change) +{ + char *ptr; + if (change->read_change & EV_CHANGE_SIGNAL) { + struct evmap_signal *ctx; + GET_SIGNAL_SLOT(ctx, &base->sigmap, change->fd, evmap_signal); + ptr = ((char*)ctx) + sizeof(struct evmap_signal); + } else { + struct evmap_io *ctx; + GET_IO_SLOT(ctx, &base->io, change->fd, evmap_io); + ptr = ((char*)ctx) + sizeof(struct evmap_io); + } + return (void*)ptr; +} + /** Callback helper for event_changelist_assert_ok */ static int event_changelist_assert_ok_foreach_iter_fn( @@ -747,220 +747,220 @@ event_changelist_assert_ok_foreach_iter_fn( return 0; } -/** Make sure that the changelist is consistent with the evmap structures. */ -static void +/** Make sure that the changelist is consistent with the evmap structures. */ +static void event_changelist_assert_ok(struct event_base *base) -{ - int i; - struct event_changelist *changelist = &base->changelist; - - EVUTIL_ASSERT(changelist->changes_size >= changelist->n_changes); - for (i = 0; i < changelist->n_changes; ++i) { - struct event_change *c = &changelist->changes[i]; - struct event_changelist_fdinfo *f; - EVUTIL_ASSERT(c->fd >= 0); - f = event_change_get_fdinfo(base, c); - EVUTIL_ASSERT(f); - EVUTIL_ASSERT(f->idxplus1 == i + 1); - } - +{ + int i; + struct event_changelist *changelist = &base->changelist; + + EVUTIL_ASSERT(changelist->changes_size >= changelist->n_changes); + for (i = 0; i < changelist->n_changes; ++i) { + struct event_change *c = &changelist->changes[i]; + struct event_changelist_fdinfo *f; + EVUTIL_ASSERT(c->fd >= 0); + f = event_change_get_fdinfo(base, c); + EVUTIL_ASSERT(f); + EVUTIL_ASSERT(f->idxplus1 == i + 1); + } + evmap_io_foreach_fd(base, event_changelist_assert_ok_foreach_iter_fn, NULL); -} +} #ifdef DEBUG_CHANGELIST #define event_changelist_check(base) event_changelist_assert_ok((base)) -#else -#define event_changelist_check(base) ((void)0) -#endif - -void +#else +#define event_changelist_check(base) ((void)0) +#endif + +void event_changelist_remove_all_(struct event_changelist *changelist, - struct event_base *base) -{ - int i; - - event_changelist_check(base); - - for (i = 0; i < changelist->n_changes; ++i) { - struct event_change *ch = &changelist->changes[i]; - struct event_changelist_fdinfo *fdinfo = - event_change_get_fdinfo(base, ch); - EVUTIL_ASSERT(fdinfo->idxplus1 == i + 1); - fdinfo->idxplus1 = 0; - } - - changelist->n_changes = 0; - - event_changelist_check(base); -} - -void + struct event_base *base) +{ + int i; + + event_changelist_check(base); + + for (i = 0; i < changelist->n_changes; ++i) { + struct event_change *ch = &changelist->changes[i]; + struct event_changelist_fdinfo *fdinfo = + event_change_get_fdinfo(base, ch); + EVUTIL_ASSERT(fdinfo->idxplus1 == i + 1); + fdinfo->idxplus1 = 0; + } + + changelist->n_changes = 0; + + event_changelist_check(base); +} + +void event_changelist_freemem_(struct event_changelist *changelist) -{ - if (changelist->changes) - mm_free(changelist->changes); +{ + if (changelist->changes) + mm_free(changelist->changes); event_changelist_init_(changelist); /* zero it all out. */ -} - -/** Increase the size of 'changelist' to hold more changes. */ -static int -event_changelist_grow(struct event_changelist *changelist) -{ - int new_size; - struct event_change *new_changes; - if (changelist->changes_size < 64) - new_size = 64; - else - new_size = changelist->changes_size * 2; - - new_changes = mm_realloc(changelist->changes, - new_size * sizeof(struct event_change)); - - if (EVUTIL_UNLIKELY(new_changes == NULL)) - return (-1); - - changelist->changes = new_changes; - changelist->changes_size = new_size; - - return (0); -} - -/** Return a pointer to the changelist entry for the file descriptor or signal - * 'fd', whose fdinfo is 'fdinfo'. If none exists, construct it, setting its - * old_events field to old_events. - */ -static struct event_change * -event_changelist_get_or_construct(struct event_changelist *changelist, - evutil_socket_t fd, - short old_events, - struct event_changelist_fdinfo *fdinfo) -{ - struct event_change *change; - - if (fdinfo->idxplus1 == 0) { - int idx; - EVUTIL_ASSERT(changelist->n_changes <= changelist->changes_size); - - if (changelist->n_changes == changelist->changes_size) { - if (event_changelist_grow(changelist) < 0) - return NULL; - } - - idx = changelist->n_changes++; - change = &changelist->changes[idx]; - fdinfo->idxplus1 = idx + 1; - - memset(change, 0, sizeof(struct event_change)); - change->fd = fd; - change->old_events = old_events; - } else { - change = &changelist->changes[fdinfo->idxplus1 - 1]; - EVUTIL_ASSERT(change->fd == fd); - } - return change; -} - -int +} + +/** Increase the size of 'changelist' to hold more changes. */ +static int +event_changelist_grow(struct event_changelist *changelist) +{ + int new_size; + struct event_change *new_changes; + if (changelist->changes_size < 64) + new_size = 64; + else + new_size = changelist->changes_size * 2; + + new_changes = mm_realloc(changelist->changes, + new_size * sizeof(struct event_change)); + + if (EVUTIL_UNLIKELY(new_changes == NULL)) + return (-1); + + changelist->changes = new_changes; + changelist->changes_size = new_size; + + return (0); +} + +/** Return a pointer to the changelist entry for the file descriptor or signal + * 'fd', whose fdinfo is 'fdinfo'. If none exists, construct it, setting its + * old_events field to old_events. + */ +static struct event_change * +event_changelist_get_or_construct(struct event_changelist *changelist, + evutil_socket_t fd, + short old_events, + struct event_changelist_fdinfo *fdinfo) +{ + struct event_change *change; + + if (fdinfo->idxplus1 == 0) { + int idx; + EVUTIL_ASSERT(changelist->n_changes <= changelist->changes_size); + + if (changelist->n_changes == changelist->changes_size) { + if (event_changelist_grow(changelist) < 0) + return NULL; + } + + idx = changelist->n_changes++; + change = &changelist->changes[idx]; + fdinfo->idxplus1 = idx + 1; + + memset(change, 0, sizeof(struct event_change)); + change->fd = fd; + change->old_events = old_events; + } else { + change = &changelist->changes[fdinfo->idxplus1 - 1]; + EVUTIL_ASSERT(change->fd == fd); + } + return change; +} + +int event_changelist_add_(struct event_base *base, evutil_socket_t fd, short old, short events, - void *p) -{ - struct event_changelist *changelist = &base->changelist; - struct event_changelist_fdinfo *fdinfo = p; - struct event_change *change; + void *p) +{ + struct event_changelist *changelist = &base->changelist; + struct event_changelist_fdinfo *fdinfo = p; + struct event_change *change; ev_uint8_t evchange = EV_CHANGE_ADD | (events & (EV_ET|EV_PERSIST|EV_SIGNAL)); - - event_changelist_check(base); - - change = event_changelist_get_or_construct(changelist, fd, old, fdinfo); - if (!change) - return -1; - - /* An add replaces any previous delete, but doesn't result in a no-op, - * since the delete might fail (because the fd had been closed since - * the last add, for instance. */ - + + event_changelist_check(base); + + change = event_changelist_get_or_construct(changelist, fd, old, fdinfo); + if (!change) + return -1; + + /* An add replaces any previous delete, but doesn't result in a no-op, + * since the delete might fail (because the fd had been closed since + * the last add, for instance. */ + if (events & (EV_READ|EV_SIGNAL)) change->read_change = evchange; if (events & EV_WRITE) change->write_change = evchange; if (events & EV_CLOSED) change->close_change = evchange; - - event_changelist_check(base); - return (0); -} - -int + + event_changelist_check(base); + return (0); +} + +int event_changelist_del_(struct event_base *base, evutil_socket_t fd, short old, short events, - void *p) -{ - struct event_changelist *changelist = &base->changelist; - struct event_changelist_fdinfo *fdinfo = p; - struct event_change *change; + void *p) +{ + struct event_changelist *changelist = &base->changelist; + struct event_changelist_fdinfo *fdinfo = p; + struct event_change *change; ev_uint8_t del = EV_CHANGE_DEL | (events & EV_ET); - - event_changelist_check(base); - change = event_changelist_get_or_construct(changelist, fd, old, fdinfo); - event_changelist_check(base); - if (!change) - return -1; - + + event_changelist_check(base); + change = event_changelist_get_or_construct(changelist, fd, old, fdinfo); + event_changelist_check(base); + if (!change) + return -1; + /* A delete on an event set that doesn't contain the event to be deleted produces a no-op. This effectively emoves any previous uncommitted add, rather than replacing it: on those platforms where "add, delete, dispatch" is not the same as "no-op, dispatch", we want the no-op behavior. - - If we have a no-op item, we could remove it it from the list - entirely, but really there's not much point: skipping the no-op - change when we do the dispatch later is far cheaper than rejuggling - the array now. - - As this stands, it also lets through deletions of events that are - not currently set. - */ - - if (events & (EV_READ|EV_SIGNAL)) { + + If we have a no-op item, we could remove it it from the list + entirely, but really there's not much point: skipping the no-op + change when we do the dispatch later is far cheaper than rejuggling + the array now. + + As this stands, it also lets through deletions of events that are + not currently set. + */ + + if (events & (EV_READ|EV_SIGNAL)) { if (!(change->old_events & (EV_READ | EV_SIGNAL))) - change->read_change = 0; - else + change->read_change = 0; + else change->read_change = del; - } - if (events & EV_WRITE) { + } + if (events & EV_WRITE) { if (!(change->old_events & EV_WRITE)) - change->write_change = 0; - else + change->write_change = 0; + else change->write_change = del; - } + } if (events & EV_CLOSED) { if (!(change->old_events & EV_CLOSED)) change->close_change = 0; else change->close_change = del; } - - event_changelist_check(base); - return (0); -} - + + event_changelist_check(base); + return (0); +} + /* Helper for evmap_check_integrity_: verify that all of the events pending on * given fd are set up correctly, and that the nread and nwrite counts on that * fd are correct. */ static int evmap_io_check_integrity_fn(struct event_base *base, evutil_socket_t fd, struct evmap_io *io_info, void *arg) -{ - struct event *ev; +{ + struct event *ev; int n_read = 0, n_write = 0, n_close = 0; - + /* First, make sure the list itself isn't corrupt. Otherwise, * running LIST_FOREACH could be an exciting adventure. */ EVUTIL_ASSERT_LIST_OK(&io_info->events, event, ev_io_next); LIST_FOREACH(ev, &io_info->events, ev_io_next) { - EVUTIL_ASSERT(ev->ev_flags & EVLIST_INSERTED); + EVUTIL_ASSERT(ev->ev_flags & EVLIST_INSERTED); EVUTIL_ASSERT(ev->ev_fd == fd); EVUTIL_ASSERT(!(ev->ev_events & EV_SIGNAL)); EVUTIL_ASSERT((ev->ev_events & (EV_READ|EV_WRITE|EV_CLOSED))); @@ -970,15 +970,15 @@ evmap_io_check_integrity_fn(struct event_base *base, evutil_socket_t fd, ++n_write; if (ev->ev_events & EV_CLOSED) ++n_close; - } - + } + EVUTIL_ASSERT(n_read == io_info->nread); EVUTIL_ASSERT(n_write == io_info->nwrite); EVUTIL_ASSERT(n_close == io_info->nclose); - + return 0; } - + /* Helper for evmap_check_integrity_: verify that all of the events pending * on given signal are set up correctly. */ static int @@ -994,16 +994,16 @@ evmap_signal_check_integrity_fn(struct event_base *base, EVUTIL_ASSERT(ev->ev_fd == signum); EVUTIL_ASSERT((ev->ev_events & EV_SIGNAL)); EVUTIL_ASSERT(!(ev->ev_events & (EV_READ|EV_WRITE|EV_CLOSED))); - } + } return 0; } - + void evmap_check_integrity_(struct event_base *base) { evmap_io_foreach_fd(base, evmap_io_check_integrity_fn, NULL); evmap_signal_foreach_signal(base, evmap_signal_check_integrity_fn, NULL); - + if (base->evsel->add == event_changelist_add_) event_changelist_assert_ok(base); } @@ -1027,10 +1027,10 @@ evmap_io_foreach_event_fn(struct event_base *base, evutil_socket_t fd, LIST_FOREACH(ev, &io_info->events, ev_io_next) { if ((r = h->fn(base, ev, h->arg))) return r; - } + } return 0; } - + /* Helper for evmap_foreach_event_: calls a provided function on every event * pending on a given signal. */ static int @@ -1043,10 +1043,10 @@ evmap_signal_foreach_event_fn(struct event_base *base, int signum, LIST_FOREACH(ev, &sig_info->events, ev_signal_next) { if ((r = h->fn(base, ev, h->arg))) return r; - } + } return 0; } - + int evmap_foreach_event_(struct event_base *base, event_base_foreach_event_cb fn, void *arg) @@ -1058,5 +1058,5 @@ evmap_foreach_event_(struct event_base *base, if ((r = evmap_io_foreach_fd(base, evmap_io_foreach_event_fn, &h))) return r; return evmap_signal_foreach_signal(base, evmap_signal_foreach_event_fn, &h); -} +} |