1 /* 2 * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (c) 1995-1999 by Internet Software Consortium 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 15 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /* eventlib.c - implement glue for the eventlib 19 * vix 09sep95 [initial] 20 */ 21 22 #if !defined(LINT) && !defined(CODECENTER) 23 static const char rcsid[] = "$Id: eventlib.c,v 1.10 2006/03/09 23:57:56 marka Exp $"; 24 #endif 25 26 #include "port_before.h" 27 #include "fd_setsize.h" 28 29 #include <sys/types.h> 30 #include <sys/time.h> 31 #include <sys/stat.h> 32 #ifdef SOLARIS2 33 #include <limits.h> 34 #endif /* SOLARIS2 */ 35 36 #include <errno.h> 37 #include <signal.h> 38 #include <stdarg.h> 39 #include <stdlib.h> 40 #include <unistd.h> 41 42 #include <isc/eventlib.h> 43 #include <isc/assertions.h> 44 #include "eventlib_p.h" 45 46 #include "port_after.h" 47 48 int __evOptMonoTime; 49 50 #ifdef USE_POLL 51 #define pselect Pselect 52 #endif /* USE_POLL */ 53 54 /* Forward. */ 55 56 #if defined(NEED_PSELECT) || defined(USE_POLL) 57 static int pselect(int, void *, void *, void *, 58 struct timespec *, 59 const sigset_t *); 60 #endif 61 62 int __evOptMonoTime; 63 64 /* Public. */ 65 66 int 67 evCreate(evContext *opaqueCtx) { 68 evContext_p *ctx; 69 70 /* Make sure the memory heap is initialized. */ 71 if (meminit(0, 0) < 0 && errno != EEXIST) 72 return (-1); 73 74 OKNEW(ctx); 75 76 /* Global. */ 77 ctx->cur = NULL; 78 79 /* Debugging. */ 80 ctx->debug = 0; 81 ctx->output = NULL; 82 83 /* Connections. */ 84 ctx->conns = NULL; 85 INIT_LIST(ctx->accepts); 86 87 /* Files. */ 88 ctx->files = NULL; 89 #ifdef USE_POLL 90 ctx->pollfds = NULL; 91 ctx->maxnfds = 0; 92 ctx->firstfd = 0; 93 emulMaskInit(ctx, rdLast, EV_READ, 1); 94 emulMaskInit(ctx, rdNext, EV_READ, 0); 95 emulMaskInit(ctx, wrLast, EV_WRITE, 1); 96 emulMaskInit(ctx, wrNext, EV_WRITE, 0); 97 emulMaskInit(ctx, exLast, EV_EXCEPT, 1); 98 emulMaskInit(ctx, exNext, EV_EXCEPT, 0); 99 emulMaskInit(ctx, nonblockBefore, EV_WASNONBLOCKING, 0); 100 #endif /* USE_POLL */ 101 FD_ZERO(&ctx->rdNext); 102 FD_ZERO(&ctx->wrNext); 103 FD_ZERO(&ctx->exNext); 104 FD_ZERO(&ctx->nonblockBefore); 105 ctx->fdMax = -1; 106 ctx->fdNext = NULL; 107 ctx->fdCount = 0; /*%< Invalidate {rd,wr,ex}Last. */ 108 #ifndef USE_POLL 109 ctx->highestFD = FD_SETSIZE - 1; 110 memset(ctx->fdTable, 0, sizeof ctx->fdTable); 111 #else 112 ctx->highestFD = INT_MAX / sizeof(struct pollfd); 113 ctx->fdTable = NULL; 114 #endif /* USE_POLL */ 115 #ifdef EVENTLIB_TIME_CHECKS 116 ctx->lastFdCount = 0; 117 #endif 118 119 /* Streams. */ 120 ctx->streams = NULL; 121 ctx->strDone = NULL; 122 ctx->strLast = NULL; 123 124 /* Timers. */ 125 ctx->lastEventTime = evNowTime(); 126 #ifdef EVENTLIB_TIME_CHECKS 127 ctx->lastSelectTime = ctx->lastEventTime; 128 #endif 129 ctx->timers = evCreateTimers(ctx); 130 if (ctx->timers == NULL) 131 return (-1); 132 133 /* Waits. */ 134 ctx->waitLists = NULL; 135 ctx->waitDone.first = ctx->waitDone.last = NULL; 136 ctx->waitDone.prev = ctx->waitDone.next = NULL; 137 138 opaqueCtx->opaque = ctx; 139 return (0); 140 } 141 142 void 143 evSetDebug(evContext opaqueCtx, int level, FILE *output) { 144 evContext_p *ctx = opaqueCtx.opaque; 145 146 ctx->debug = level; 147 ctx->output = output; 148 } 149 150 int 151 evDestroy(evContext opaqueCtx) { 152 evContext_p *ctx = opaqueCtx.opaque; 153 int revs = 424242; /*%< Doug Adams. */ 154 evWaitList *this_wl, *next_wl; 155 evWait *this_wait, *next_wait; 156 157 /* Connections. */ 158 while (revs-- > 0 && ctx->conns != NULL) { 159 evConnID id; 160 161 id.opaque = ctx->conns; 162 (void) evCancelConn(opaqueCtx, id); 163 } 164 INSIST(revs >= 0); 165 166 /* Streams. */ 167 while (revs-- > 0 && ctx->streams != NULL) { 168 evStreamID id; 169 170 id.opaque = ctx->streams; 171 (void) evCancelRW(opaqueCtx, id); 172 } 173 174 /* Files. */ 175 while (revs-- > 0 && ctx->files != NULL) { 176 evFileID id; 177 178 id.opaque = ctx->files; 179 (void) evDeselectFD(opaqueCtx, id); 180 } 181 INSIST(revs >= 0); 182 183 /* Timers. */ 184 evDestroyTimers(ctx); 185 186 /* Waits. */ 187 for (this_wl = ctx->waitLists; 188 revs-- > 0 && this_wl != NULL; 189 this_wl = next_wl) { 190 next_wl = this_wl->next; 191 for (this_wait = this_wl->first; 192 revs-- > 0 && this_wait != NULL; 193 this_wait = next_wait) { 194 next_wait = this_wait->next; 195 FREE(this_wait); 196 } 197 FREE(this_wl); 198 } 199 for (this_wait = ctx->waitDone.first; 200 revs-- > 0 && this_wait != NULL; 201 this_wait = next_wait) { 202 next_wait = this_wait->next; 203 FREE(this_wait); 204 } 205 206 FREE(ctx); 207 return (0); 208 } 209 210 int 211 evGetNext(evContext opaqueCtx, evEvent *opaqueEv, int options) { 212 evContext_p *ctx = opaqueCtx.opaque; 213 struct timespec nextTime; 214 evTimer *nextTimer; 215 evEvent_p *new; 216 int x, pselect_errno, timerPast; 217 #ifdef EVENTLIB_TIME_CHECKS 218 struct timespec interval; 219 #endif 220 221 /* Ensure that exactly one of EV_POLL or EV_WAIT was specified. */ 222 x = ((options & EV_POLL) != 0) + ((options & EV_WAIT) != 0); 223 if (x != 1) 224 EV_ERR(EINVAL); 225 226 /* Get the time of day. We'll do this again after select() blocks. */ 227 ctx->lastEventTime = evNowTime(); 228 229 again: 230 /* Finished accept()'s do not require a select(). */ 231 if (!EMPTY(ctx->accepts)) { 232 OKNEW(new); 233 new->type = Accept; 234 new->u.accept.this = HEAD(ctx->accepts); 235 UNLINK(ctx->accepts, HEAD(ctx->accepts), link); 236 opaqueEv->opaque = new; 237 return (0); 238 } 239 240 /* Stream IO does not require a select(). */ 241 if (ctx->strDone != NULL) { 242 OKNEW(new); 243 new->type = Stream; 244 new->u.stream.this = ctx->strDone; 245 ctx->strDone = ctx->strDone->nextDone; 246 if (ctx->strDone == NULL) 247 ctx->strLast = NULL; 248 opaqueEv->opaque = new; 249 return (0); 250 } 251 252 /* Waits do not require a select(). */ 253 if (ctx->waitDone.first != NULL) { 254 OKNEW(new); 255 new->type = Wait; 256 new->u.wait.this = ctx->waitDone.first; 257 ctx->waitDone.first = ctx->waitDone.first->next; 258 if (ctx->waitDone.first == NULL) 259 ctx->waitDone.last = NULL; 260 opaqueEv->opaque = new; 261 return (0); 262 } 263 264 /* Get the status and content of the next timer. */ 265 if ((nextTimer = heap_element(ctx->timers, 1)) != NULL) { 266 nextTime = nextTimer->due; 267 timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0); 268 } else 269 timerPast = 0; /*%< Make gcc happy. */ 270 evPrintf(ctx, 9, "evGetNext: fdCount %d\n", ctx->fdCount); 271 if (ctx->fdCount == 0) { 272 static const struct timespec NoTime = {0, 0L}; 273 enum { JustPoll, Block, Timer } m; 274 struct timespec t, *tp; 275 276 /* Are there any events at all? */ 277 if ((options & EV_WAIT) != 0 && !nextTimer && ctx->fdMax == -1) 278 EV_ERR(ENOENT); 279 280 /* Figure out what select()'s timeout parameter should be. */ 281 if ((options & EV_POLL) != 0) { 282 m = JustPoll; 283 t = NoTime; 284 tp = &t; 285 } else if (nextTimer == NULL) { 286 m = Block; 287 /* ``t'' unused. */ 288 tp = NULL; 289 } else if (timerPast) { 290 m = JustPoll; 291 t = NoTime; 292 tp = &t; 293 } else { 294 m = Timer; 295 /* ``t'' filled in later. */ 296 tp = &t; 297 } 298 #ifdef EVENTLIB_TIME_CHECKS 299 if (ctx->debug > 0) { 300 interval = evSubTime(ctx->lastEventTime, 301 ctx->lastSelectTime); 302 if (interval.tv_sec > 0 || interval.tv_nsec > 0) 303 evPrintf(ctx, 1, 304 "time between pselect() %u.%09u count %d\n", 305 interval.tv_sec, interval.tv_nsec, 306 ctx->lastFdCount); 307 } 308 #endif 309 do { 310 #ifndef USE_POLL 311 /* XXX need to copy only the bits we are using. */ 312 ctx->rdLast = ctx->rdNext; 313 ctx->wrLast = ctx->wrNext; 314 ctx->exLast = ctx->exNext; 315 #else 316 /* 317 * The pollfd structure uses separate fields for 318 * the input and output events (corresponding to 319 * the ??Next and ??Last fd sets), so there's no 320 * need to copy one to the other. 321 */ 322 #endif /* USE_POLL */ 323 if (m == Timer) { 324 INSIST(tp == &t); 325 t = evSubTime(nextTime, ctx->lastEventTime); 326 } 327 328 /* XXX should predict system's earliness and adjust. */ 329 x = pselect(ctx->fdMax+1, 330 &ctx->rdLast, &ctx->wrLast, &ctx->exLast, 331 tp, NULL); 332 pselect_errno = errno; 333 334 #ifndef USE_POLL 335 evPrintf(ctx, 4, "select() returns %d (err: %s)\n", 336 x, (x == -1) ? strerror(errno) : "none"); 337 #else 338 evPrintf(ctx, 4, "poll() returns %d (err: %s)\n", 339 x, (x == -1) ? strerror(errno) : "none"); 340 #endif /* USE_POLL */ 341 /* Anything but a poll can change the time. */ 342 if (m != JustPoll) 343 ctx->lastEventTime = evNowTime(); 344 345 /* Select() likes to finish about 10ms early. */ 346 } while (x == 0 && m == Timer && 347 evCmpTime(ctx->lastEventTime, nextTime) < 0); 348 #ifdef EVENTLIB_TIME_CHECKS 349 ctx->lastSelectTime = ctx->lastEventTime; 350 #endif 351 if (x < 0) { 352 if (pselect_errno == EINTR) { 353 if ((options & EV_NULL) != 0) 354 goto again; 355 OKNEW(new); 356 new->type = Null; 357 /* No data. */ 358 opaqueEv->opaque = new; 359 return (0); 360 } 361 if (pselect_errno == EBADF) { 362 for (x = 0; x <= ctx->fdMax; x++) { 363 struct stat sb; 364 365 if (FD_ISSET(x, &ctx->rdNext) == 0 && 366 FD_ISSET(x, &ctx->wrNext) == 0 && 367 FD_ISSET(x, &ctx->exNext) == 0) 368 continue; 369 if (fstat(x, &sb) == -1 && 370 errno == EBADF) 371 evPrintf(ctx, 1, "EBADF: %d\n", 372 x); 373 } 374 abort(); 375 } 376 EV_ERR(pselect_errno); 377 } 378 if (x == 0 && (nextTimer == NULL || !timerPast) && 379 (options & EV_POLL)) 380 EV_ERR(EWOULDBLOCK); 381 ctx->fdCount = x; 382 #ifdef EVENTLIB_TIME_CHECKS 383 ctx->lastFdCount = x; 384 #endif 385 } 386 INSIST(nextTimer || ctx->fdCount); 387 388 /* Timers go first since we'd like them to be accurate. */ 389 if (nextTimer && !timerPast) { 390 /* Has anything happened since we blocked? */ 391 timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0); 392 } 393 if (nextTimer && timerPast) { 394 OKNEW(new); 395 new->type = Timer; 396 new->u.timer.this = nextTimer; 397 opaqueEv->opaque = new; 398 return (0); 399 } 400 401 /* No timers, so there should be a ready file descriptor. */ 402 x = 0; 403 while (ctx->fdCount > 0) { 404 evFile *fid; 405 int fd, eventmask; 406 407 if (ctx->fdNext == NULL) { 408 if (++x == 2) { 409 /* 410 * Hitting the end twice means that the last 411 * select() found some FD's which have since 412 * been deselected. 413 * 414 * On some systems, the count returned by 415 * selects is the total number of bits in 416 * all masks that are set, and on others it's 417 * the number of fd's that have some bit set, 418 * and on others, it's just broken. We 419 * always assume that it's the number of 420 * bits set in all masks, because that's what 421 * the man page says it should do, and 422 * the worst that can happen is we do an 423 * extra select(). 424 */ 425 ctx->fdCount = 0; 426 break; 427 } 428 ctx->fdNext = ctx->files; 429 } 430 fid = ctx->fdNext; 431 ctx->fdNext = fid->next; 432 433 fd = fid->fd; 434 eventmask = 0; 435 if (FD_ISSET(fd, &ctx->rdLast)) 436 eventmask |= EV_READ; 437 if (FD_ISSET(fd, &ctx->wrLast)) 438 eventmask |= EV_WRITE; 439 if (FD_ISSET(fd, &ctx->exLast)) 440 eventmask |= EV_EXCEPT; 441 eventmask &= fid->eventmask; 442 if (eventmask != 0) { 443 if ((eventmask & EV_READ) != 0) { 444 FD_CLR(fd, &ctx->rdLast); 445 ctx->fdCount--; 446 } 447 if ((eventmask & EV_WRITE) != 0) { 448 FD_CLR(fd, &ctx->wrLast); 449 ctx->fdCount--; 450 } 451 if ((eventmask & EV_EXCEPT) != 0) { 452 FD_CLR(fd, &ctx->exLast); 453 ctx->fdCount--; 454 } 455 OKNEW(new); 456 new->type = File; 457 new->u.file.this = fid; 458 new->u.file.eventmask = eventmask; 459 opaqueEv->opaque = new; 460 return (0); 461 } 462 } 463 if (ctx->fdCount < 0) { 464 /* 465 * select()'s count is off on a number of systems, and 466 * can result in fdCount < 0. 467 */ 468 evPrintf(ctx, 4, "fdCount < 0 (%d)\n", ctx->fdCount); 469 ctx->fdCount = 0; 470 } 471 472 /* We get here if the caller deselect()'s an FD. Gag me with a goto. */ 473 goto again; 474 } 475 476 int 477 evDispatch(evContext opaqueCtx, evEvent opaqueEv) { 478 evContext_p *ctx = opaqueCtx.opaque; 479 evEvent_p *ev = opaqueEv.opaque; 480 #ifdef EVENTLIB_TIME_CHECKS 481 void *func; 482 struct timespec start_time; 483 struct timespec interval; 484 #endif 485 486 #ifdef EVENTLIB_TIME_CHECKS 487 if (ctx->debug > 0) 488 start_time = evNowTime(); 489 #endif 490 ctx->cur = ev; 491 switch (ev->type) { 492 case Accept: { 493 evAccept *this = ev->u.accept.this; 494 495 evPrintf(ctx, 5, 496 "Dispatch.Accept: fd %d -> %d, func %p, uap %p\n", 497 this->conn->fd, this->fd, 498 this->conn->func, this->conn->uap); 499 errno = this->ioErrno; 500 (this->conn->func)(opaqueCtx, this->conn->uap, this->fd, 501 &this->la, this->lalen, 502 &this->ra, this->ralen); 503 #ifdef EVENTLIB_TIME_CHECKS 504 func = this->conn->func; 505 #endif 506 break; 507 } 508 case File: { 509 evFile *this = ev->u.file.this; 510 int eventmask = ev->u.file.eventmask; 511 512 evPrintf(ctx, 5, 513 "Dispatch.File: fd %d, mask 0x%x, func %p, uap %p\n", 514 this->fd, this->eventmask, this->func, this->uap); 515 (this->func)(opaqueCtx, this->uap, this->fd, eventmask); 516 #ifdef EVENTLIB_TIME_CHECKS 517 func = this->func; 518 #endif 519 break; 520 } 521 case Stream: { 522 evStream *this = ev->u.stream.this; 523 524 evPrintf(ctx, 5, 525 "Dispatch.Stream: fd %d, func %p, uap %p\n", 526 this->fd, this->func, this->uap); 527 errno = this->ioErrno; 528 (this->func)(opaqueCtx, this->uap, this->fd, this->ioDone); 529 #ifdef EVENTLIB_TIME_CHECKS 530 func = this->func; 531 #endif 532 break; 533 } 534 case Timer: { 535 evTimer *this = ev->u.timer.this; 536 537 evPrintf(ctx, 5, "Dispatch.Timer: func %p, uap %p\n", 538 this->func, this->uap); 539 (this->func)(opaqueCtx, this->uap, this->due, this->inter); 540 #ifdef EVENTLIB_TIME_CHECKS 541 func = this->func; 542 #endif 543 break; 544 } 545 case Wait: { 546 evWait *this = ev->u.wait.this; 547 548 evPrintf(ctx, 5, 549 "Dispatch.Wait: tag %p, func %p, uap %p\n", 550 this->tag, this->func, this->uap); 551 (this->func)(opaqueCtx, this->uap, this->tag); 552 #ifdef EVENTLIB_TIME_CHECKS 553 func = this->func; 554 #endif 555 break; 556 } 557 case Null: { 558 /* No work. */ 559 #ifdef EVENTLIB_TIME_CHECKS 560 func = NULL; 561 #endif 562 break; 563 } 564 default: { 565 abort(); 566 } 567 } 568 #ifdef EVENTLIB_TIME_CHECKS 569 if (ctx->debug > 0) { 570 interval = evSubTime(evNowTime(), start_time); 571 /* 572 * Complain if it took longer than 50 milliseconds. 573 * 574 * We call getuid() to make an easy to find mark in a kernel 575 * trace. 576 */ 577 if (interval.tv_sec > 0 || interval.tv_nsec > 50000000) 578 evPrintf(ctx, 1, 579 "dispatch interval %u.%09u uid %d type %d func %p\n", 580 interval.tv_sec, interval.tv_nsec, 581 getuid(), ev->type, func); 582 } 583 #endif 584 ctx->cur = NULL; 585 evDrop(opaqueCtx, opaqueEv); 586 return (0); 587 } 588 589 void 590 evDrop(evContext opaqueCtx, evEvent opaqueEv) { 591 evContext_p *ctx = opaqueCtx.opaque; 592 evEvent_p *ev = opaqueEv.opaque; 593 594 switch (ev->type) { 595 case Accept: { 596 FREE(ev->u.accept.this); 597 break; 598 } 599 case File: { 600 /* No work. */ 601 break; 602 } 603 case Stream: { 604 evStreamID id; 605 606 id.opaque = ev->u.stream.this; 607 (void) evCancelRW(opaqueCtx, id); 608 break; 609 } 610 case Timer: { 611 evTimer *this = ev->u.timer.this; 612 evTimerID opaque; 613 614 /* Check to see whether the user func cleared the timer. */ 615 if (heap_element(ctx->timers, this->index) != this) { 616 evPrintf(ctx, 5, "Dispatch.Timer: timer rm'd?\n"); 617 break; 618 } 619 /* 620 * Timer is still there. Delete it if it has expired, 621 * otherwise set it according to its next interval. 622 */ 623 if (this->inter.tv_sec == (time_t)0 && 624 this->inter.tv_nsec == 0L) { 625 opaque.opaque = this; 626 (void) evClearTimer(opaqueCtx, opaque); 627 } else { 628 opaque.opaque = this; 629 (void) evResetTimer(opaqueCtx, opaque, this->func, 630 this->uap, 631 evAddTime((this->mode & EV_TMR_RATE) ? 632 this->due : 633 ctx->lastEventTime, 634 this->inter), 635 this->inter); 636 } 637 break; 638 } 639 case Wait: { 640 FREE(ev->u.wait.this); 641 break; 642 } 643 case Null: { 644 /* No work. */ 645 break; 646 } 647 default: { 648 abort(); 649 } 650 } 651 FREE(ev); 652 } 653 654 int 655 evMainLoop(evContext opaqueCtx) { 656 evEvent event; 657 int x; 658 659 while ((x = evGetNext(opaqueCtx, &event, EV_WAIT)) == 0) 660 if ((x = evDispatch(opaqueCtx, event)) < 0) 661 break; 662 return (x); 663 } 664 665 int 666 evHighestFD(evContext opaqueCtx) { 667 evContext_p *ctx = opaqueCtx.opaque; 668 669 return (ctx->highestFD); 670 } 671 672 void 673 evPrintf(const evContext_p *ctx, int level, const char *fmt, ...) { 674 va_list ap; 675 676 va_start(ap, fmt); 677 if (ctx->output != NULL && ctx->debug >= level) { 678 vfprintf(ctx->output, fmt, ap); 679 fflush(ctx->output); 680 } 681 va_end(ap); 682 } 683 684 int 685 evSetOption(evContext *opaqueCtx, const char *option, int value) { 686 /* evContext_p *ctx = opaqueCtx->opaque; */ 687 688 UNUSED(opaqueCtx); 689 UNUSED(value); 690 #ifndef CLOCK_MONOTONIC 691 UNUSED(option); 692 #endif 693 694 #ifdef CLOCK_MONOTONIC 695 if (strcmp(option, "monotime") == 0) { 696 if (opaqueCtx != NULL) 697 errno = EINVAL; 698 if (value == 0 || value == 1) { 699 __evOptMonoTime = value; 700 return (0); 701 } else { 702 errno = EINVAL; 703 return (-1); 704 } 705 } 706 #endif 707 errno = ENOENT; 708 return (-1); 709 } 710 711 int 712 evGetOption(evContext *opaqueCtx, const char *option, int *value) { 713 /* evContext_p *ctx = opaqueCtx->opaque; */ 714 715 UNUSED(opaqueCtx); 716 #ifndef CLOCK_MONOTONIC 717 UNUSED(value); 718 UNUSED(option); 719 #endif 720 721 #ifdef CLOCK_MONOTONIC 722 if (strcmp(option, "monotime") == 0) { 723 if (opaqueCtx != NULL) 724 errno = EINVAL; 725 *value = __evOptMonoTime; 726 return (0); 727 } 728 #endif 729 errno = ENOENT; 730 return (-1); 731 } 732 733 #if defined(NEED_PSELECT) || defined(USE_POLL) 734 /* XXX needs to move to the porting library. */ 735 static int 736 pselect(int nfds, void *rfds, void *wfds, void *efds, 737 struct timespec *tsp, 738 const sigset_t *sigmask) 739 { 740 struct timeval tv, *tvp; 741 sigset_t sigs; 742 int n; 743 #ifdef USE_POLL 744 int polltimeout = INFTIM; 745 evContext_p *ctx; 746 struct pollfd *fds; 747 nfds_t pnfds; 748 749 UNUSED(nfds); 750 #endif /* USE_POLL */ 751 752 if (tsp) { 753 tvp = &tv; 754 tv = evTimeVal(*tsp); 755 #ifdef USE_POLL 756 polltimeout = 1000 * tv.tv_sec + tv.tv_usec / 1000; 757 #endif /* USE_POLL */ 758 } else 759 tvp = NULL; 760 if (sigmask) 761 sigprocmask(SIG_SETMASK, sigmask, &sigs); 762 #ifndef USE_POLL 763 n = select(nfds, rfds, wfds, efds, tvp); 764 #else 765 /* 766 * rfds, wfds, and efds should all be from the same evContext_p, 767 * so any of them will do. If they're all NULL, the caller is 768 * presumably calling us to block. 769 */ 770 if (rfds != NULL) 771 ctx = ((__evEmulMask *)rfds)->ctx; 772 else if (wfds != NULL) 773 ctx = ((__evEmulMask *)wfds)->ctx; 774 else if (efds != NULL) 775 ctx = ((__evEmulMask *)efds)->ctx; 776 else 777 ctx = NULL; 778 if (ctx != NULL && ctx->fdMax != -1) { 779 fds = &(ctx->pollfds[ctx->firstfd]); 780 pnfds = ctx->fdMax - ctx->firstfd + 1; 781 } else { 782 fds = NULL; 783 pnfds = 0; 784 } 785 n = poll(fds, pnfds, polltimeout); 786 if (n > 0) { 787 int i, e; 788 789 INSIST(ctx != NULL); 790 for (e = 0, i = ctx->firstfd; i <= ctx->fdMax; i++) { 791 if (ctx->pollfds[i].fd < 0) 792 continue; 793 if (FD_ISSET(i, &ctx->rdLast)) 794 e++; 795 if (FD_ISSET(i, &ctx->wrLast)) 796 e++; 797 if (FD_ISSET(i, &ctx->exLast)) 798 e++; 799 } 800 n = e; 801 } 802 #endif /* USE_POLL */ 803 if (sigmask) 804 sigprocmask(SIG_SETMASK, &sigs, NULL); 805 if (tsp) 806 *tsp = evTimeSpec(tv); 807 return (n); 808 } 809 #endif 810 811 #ifdef USE_POLL 812 int 813 evPollfdRealloc(evContext_p *ctx, int pollfd_chunk_size, int fd) { 814 815 int i, maxnfds; 816 void *pollfds, *fdTable; 817 818 if (fd < ctx->maxnfds) 819 return (0); 820 821 /* Don't allow ridiculously small values for pollfd_chunk_size */ 822 if (pollfd_chunk_size < 20) 823 pollfd_chunk_size = 20; 824 825 maxnfds = (1 + (fd/pollfd_chunk_size)) * pollfd_chunk_size; 826 827 pollfds = realloc(ctx->pollfds, maxnfds * sizeof(*ctx->pollfds)); 828 if (pollfds != NULL) 829 ctx->pollfds = pollfds; 830 fdTable = realloc(ctx->fdTable, maxnfds * sizeof(*ctx->fdTable)); 831 if (fdTable != NULL) 832 ctx->fdTable = fdTable; 833 834 if (pollfds == NULL || fdTable == NULL) { 835 evPrintf(ctx, 2, "pollfd() realloc (%ld) failed\n", 836 (long)maxnfds*sizeof(struct pollfd)); 837 return (-1); 838 } 839 840 for (i = ctx->maxnfds; i < maxnfds; i++) { 841 ctx->pollfds[i].fd = -1; 842 ctx->pollfds[i].events = 0; 843 ctx->fdTable[i] = 0; 844 } 845 846 ctx->maxnfds = maxnfds; 847 848 return (0); 849 } 850 851 /* Find the appropriate 'events' or 'revents' field in the pollfds array */ 852 short * 853 __fd_eventfield(int fd, __evEmulMask *maskp) { 854 855 evContext_p *ctx = (evContext_p *)maskp->ctx; 856 857 if (!maskp->result || maskp->type == EV_WASNONBLOCKING) 858 return (&(ctx->pollfds[fd].events)); 859 else 860 return (&(ctx->pollfds[fd].revents)); 861 } 862 863 /* Translate to poll(2) event */ 864 short 865 __poll_event(__evEmulMask *maskp) { 866 867 switch ((maskp)->type) { 868 case EV_READ: 869 return (POLLRDNORM); 870 case EV_WRITE: 871 return (POLLWRNORM); 872 case EV_EXCEPT: 873 return (POLLRDBAND | POLLPRI | POLLWRBAND); 874 case EV_WASNONBLOCKING: 875 return (POLLHUP); 876 default: 877 return (0); 878 } 879 } 880 881 /* 882 * Clear the events corresponding to the specified mask. If this leaves 883 * the events mask empty (apart from the POLLHUP bit), set the fd field 884 * to -1 so that poll(2) will ignore this fd. 885 */ 886 void 887 __fd_clr(int fd, __evEmulMask *maskp) { 888 889 evContext_p *ctx = maskp->ctx; 890 891 *__fd_eventfield(fd, maskp) &= ~__poll_event(maskp); 892 if ((ctx->pollfds[fd].events & ~POLLHUP) == 0) { 893 ctx->pollfds[fd].fd = -1; 894 if (fd == ctx->fdMax) 895 while (ctx->fdMax > ctx->firstfd && 896 ctx->pollfds[ctx->fdMax].fd < 0) 897 ctx->fdMax--; 898 if (fd == ctx->firstfd) 899 while (ctx->firstfd <= ctx->fdMax && 900 ctx->pollfds[ctx->firstfd].fd < 0) 901 ctx->firstfd++; 902 /* 903 * Do we have a empty set of descriptors? 904 */ 905 if (ctx->firstfd > ctx->fdMax) { 906 ctx->fdMax = -1; 907 ctx->firstfd = 0; 908 } 909 } 910 } 911 912 /* 913 * Set the events bit(s) corresponding to the specified mask. If the events 914 * field has any other bits than POLLHUP set, also set the fd field so that 915 * poll(2) will watch this fd. 916 */ 917 void 918 __fd_set(int fd, __evEmulMask *maskp) { 919 920 evContext_p *ctx = maskp->ctx; 921 922 *__fd_eventfield(fd, maskp) |= __poll_event(maskp); 923 if ((ctx->pollfds[fd].events & ~POLLHUP) != 0) { 924 ctx->pollfds[fd].fd = fd; 925 if (fd < ctx->firstfd || ctx->fdMax == -1) 926 ctx->firstfd = fd; 927 if (fd > ctx->fdMax) 928 ctx->fdMax = fd; 929 } 930 } 931 #endif /* USE_POLL */ 932 933 /*! \file */ 934