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