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