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