17c478bd9Sstevel@tonic-gate /*
2*9525b14bSRao Shoaib * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
37c478bd9Sstevel@tonic-gate * Copyright (c) 1995-1999 by Internet Software Consortium
47c478bd9Sstevel@tonic-gate *
57c478bd9Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any
67c478bd9Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above
77c478bd9Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies.
87c478bd9Sstevel@tonic-gate *
9*9525b14bSRao Shoaib * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
10*9525b14bSRao Shoaib * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*9525b14bSRao Shoaib * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
12*9525b14bSRao Shoaib * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*9525b14bSRao Shoaib * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*9525b14bSRao Shoaib * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15*9525b14bSRao Shoaib * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
167c478bd9Sstevel@tonic-gate */
177c478bd9Sstevel@tonic-gate
187c478bd9Sstevel@tonic-gate /* eventlib.c - implement glue for the eventlib
197c478bd9Sstevel@tonic-gate * vix 09sep95 [initial]
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate
227c478bd9Sstevel@tonic-gate #if !defined(LINT) && !defined(CODECENTER)
23*9525b14bSRao Shoaib static const char rcsid[] = "$Id: eventlib.c,v 1.10 2006/03/09 23:57:56 marka Exp $";
247c478bd9Sstevel@tonic-gate #endif
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include "port_before.h"
277c478bd9Sstevel@tonic-gate #include "fd_setsize.h"
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate #include <sys/types.h>
307c478bd9Sstevel@tonic-gate #include <sys/time.h>
317c478bd9Sstevel@tonic-gate #include <sys/stat.h>
32*9525b14bSRao Shoaib #ifdef SOLARIS2
337c478bd9Sstevel@tonic-gate #include <limits.h>
34*9525b14bSRao Shoaib #endif /* SOLARIS2 */
357c478bd9Sstevel@tonic-gate
367c478bd9Sstevel@tonic-gate #include <errno.h>
377c478bd9Sstevel@tonic-gate #include <signal.h>
387c478bd9Sstevel@tonic-gate #include <stdarg.h>
397c478bd9Sstevel@tonic-gate #include <stdlib.h>
407c478bd9Sstevel@tonic-gate #include <unistd.h>
417c478bd9Sstevel@tonic-gate
427c478bd9Sstevel@tonic-gate #include <isc/eventlib.h>
437c478bd9Sstevel@tonic-gate #include <isc/assertions.h>
447c478bd9Sstevel@tonic-gate #include "eventlib_p.h"
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate #include "port_after.h"
477c478bd9Sstevel@tonic-gate
48*9525b14bSRao Shoaib int __evOptMonoTime;
49*9525b14bSRao Shoaib
50*9525b14bSRao Shoaib #ifdef USE_POLL
517c478bd9Sstevel@tonic-gate #define pselect Pselect
52*9525b14bSRao Shoaib #endif /* USE_POLL */
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate /* Forward. */
557c478bd9Sstevel@tonic-gate
56*9525b14bSRao Shoaib #if defined(NEED_PSELECT) || defined(USE_POLL)
577c478bd9Sstevel@tonic-gate static int pselect(int, void *, void *, void *,
587c478bd9Sstevel@tonic-gate struct timespec *,
597c478bd9Sstevel@tonic-gate const sigset_t *);
607c478bd9Sstevel@tonic-gate #endif
617c478bd9Sstevel@tonic-gate
62*9525b14bSRao Shoaib int __evOptMonoTime;
63*9525b14bSRao Shoaib
647c478bd9Sstevel@tonic-gate /* Public. */
657c478bd9Sstevel@tonic-gate
667c478bd9Sstevel@tonic-gate int
evCreate(evContext * opaqueCtx)677c478bd9Sstevel@tonic-gate evCreate(evContext *opaqueCtx) {
687c478bd9Sstevel@tonic-gate evContext_p *ctx;
697c478bd9Sstevel@tonic-gate
707c478bd9Sstevel@tonic-gate /* Make sure the memory heap is initialized. */
717c478bd9Sstevel@tonic-gate if (meminit(0, 0) < 0 && errno != EEXIST)
727c478bd9Sstevel@tonic-gate return (-1);
737c478bd9Sstevel@tonic-gate
747c478bd9Sstevel@tonic-gate OKNEW(ctx);
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate /* Global. */
777c478bd9Sstevel@tonic-gate ctx->cur = NULL;
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate /* Debugging. */
807c478bd9Sstevel@tonic-gate ctx->debug = 0;
817c478bd9Sstevel@tonic-gate ctx->output = NULL;
827c478bd9Sstevel@tonic-gate
837c478bd9Sstevel@tonic-gate /* Connections. */
847c478bd9Sstevel@tonic-gate ctx->conns = NULL;
857c478bd9Sstevel@tonic-gate INIT_LIST(ctx->accepts);
867c478bd9Sstevel@tonic-gate
877c478bd9Sstevel@tonic-gate /* Files. */
887c478bd9Sstevel@tonic-gate ctx->files = NULL;
89*9525b14bSRao Shoaib #ifdef USE_POLL
90*9525b14bSRao Shoaib ctx->pollfds = NULL;
917c478bd9Sstevel@tonic-gate ctx->maxnfds = 0;
927c478bd9Sstevel@tonic-gate ctx->firstfd = 0;
937c478bd9Sstevel@tonic-gate emulMaskInit(ctx, rdLast, EV_READ, 1);
947c478bd9Sstevel@tonic-gate emulMaskInit(ctx, rdNext, EV_READ, 0);
957c478bd9Sstevel@tonic-gate emulMaskInit(ctx, wrLast, EV_WRITE, 1);
967c478bd9Sstevel@tonic-gate emulMaskInit(ctx, wrNext, EV_WRITE, 0);
977c478bd9Sstevel@tonic-gate emulMaskInit(ctx, exLast, EV_EXCEPT, 1);
987c478bd9Sstevel@tonic-gate emulMaskInit(ctx, exNext, EV_EXCEPT, 0);
997c478bd9Sstevel@tonic-gate emulMaskInit(ctx, nonblockBefore, EV_WASNONBLOCKING, 0);
100*9525b14bSRao Shoaib #endif /* USE_POLL */
1017c478bd9Sstevel@tonic-gate FD_ZERO(&ctx->rdNext);
1027c478bd9Sstevel@tonic-gate FD_ZERO(&ctx->wrNext);
1037c478bd9Sstevel@tonic-gate FD_ZERO(&ctx->exNext);
1047c478bd9Sstevel@tonic-gate FD_ZERO(&ctx->nonblockBefore);
1057c478bd9Sstevel@tonic-gate ctx->fdMax = -1;
1067c478bd9Sstevel@tonic-gate ctx->fdNext = NULL;
107*9525b14bSRao Shoaib ctx->fdCount = 0; /*%< Invalidate {rd,wr,ex}Last. */
108*9525b14bSRao Shoaib #ifndef USE_POLL
1097c478bd9Sstevel@tonic-gate ctx->highestFD = FD_SETSIZE - 1;
110*9525b14bSRao Shoaib memset(ctx->fdTable, 0, sizeof ctx->fdTable);
111*9525b14bSRao Shoaib #else
112*9525b14bSRao Shoaib ctx->highestFD = INT_MAX / sizeof(struct pollfd);
113*9525b14bSRao Shoaib ctx->fdTable = NULL;
114*9525b14bSRao Shoaib #endif /* USE_POLL */
1157c478bd9Sstevel@tonic-gate #ifdef EVENTLIB_TIME_CHECKS
1167c478bd9Sstevel@tonic-gate ctx->lastFdCount = 0;
1177c478bd9Sstevel@tonic-gate #endif
1187c478bd9Sstevel@tonic-gate
1197c478bd9Sstevel@tonic-gate /* Streams. */
1207c478bd9Sstevel@tonic-gate ctx->streams = NULL;
1217c478bd9Sstevel@tonic-gate ctx->strDone = NULL;
1227c478bd9Sstevel@tonic-gate ctx->strLast = NULL;
1237c478bd9Sstevel@tonic-gate
1247c478bd9Sstevel@tonic-gate /* Timers. */
1257c478bd9Sstevel@tonic-gate ctx->lastEventTime = evNowTime();
1267c478bd9Sstevel@tonic-gate #ifdef EVENTLIB_TIME_CHECKS
1277c478bd9Sstevel@tonic-gate ctx->lastSelectTime = ctx->lastEventTime;
1287c478bd9Sstevel@tonic-gate #endif
1297c478bd9Sstevel@tonic-gate ctx->timers = evCreateTimers(ctx);
1307c478bd9Sstevel@tonic-gate if (ctx->timers == NULL)
1317c478bd9Sstevel@tonic-gate return (-1);
1327c478bd9Sstevel@tonic-gate
1337c478bd9Sstevel@tonic-gate /* Waits. */
1347c478bd9Sstevel@tonic-gate ctx->waitLists = NULL;
1357c478bd9Sstevel@tonic-gate ctx->waitDone.first = ctx->waitDone.last = NULL;
1367c478bd9Sstevel@tonic-gate ctx->waitDone.prev = ctx->waitDone.next = NULL;
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate opaqueCtx->opaque = ctx;
1397c478bd9Sstevel@tonic-gate return (0);
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate
1427c478bd9Sstevel@tonic-gate void
evSetDebug(evContext opaqueCtx,int level,FILE * output)1437c478bd9Sstevel@tonic-gate evSetDebug(evContext opaqueCtx, int level, FILE *output) {
1447c478bd9Sstevel@tonic-gate evContext_p *ctx = opaqueCtx.opaque;
1457c478bd9Sstevel@tonic-gate
1467c478bd9Sstevel@tonic-gate ctx->debug = level;
1477c478bd9Sstevel@tonic-gate ctx->output = output;
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate int
evDestroy(evContext opaqueCtx)1517c478bd9Sstevel@tonic-gate evDestroy(evContext opaqueCtx) {
1527c478bd9Sstevel@tonic-gate evContext_p *ctx = opaqueCtx.opaque;
153*9525b14bSRao Shoaib int revs = 424242; /*%< Doug Adams. */
1547c478bd9Sstevel@tonic-gate evWaitList *this_wl, *next_wl;
1557c478bd9Sstevel@tonic-gate evWait *this_wait, *next_wait;
1567c478bd9Sstevel@tonic-gate
1577c478bd9Sstevel@tonic-gate /* Connections. */
1587c478bd9Sstevel@tonic-gate while (revs-- > 0 && ctx->conns != NULL) {
1597c478bd9Sstevel@tonic-gate evConnID id;
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate id.opaque = ctx->conns;
1627c478bd9Sstevel@tonic-gate (void) evCancelConn(opaqueCtx, id);
1637c478bd9Sstevel@tonic-gate }
1647c478bd9Sstevel@tonic-gate INSIST(revs >= 0);
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate /* Streams. */
1677c478bd9Sstevel@tonic-gate while (revs-- > 0 && ctx->streams != NULL) {
1687c478bd9Sstevel@tonic-gate evStreamID id;
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate id.opaque = ctx->streams;
1717c478bd9Sstevel@tonic-gate (void) evCancelRW(opaqueCtx, id);
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate
1747c478bd9Sstevel@tonic-gate /* Files. */
1757c478bd9Sstevel@tonic-gate while (revs-- > 0 && ctx->files != NULL) {
1767c478bd9Sstevel@tonic-gate evFileID id;
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate id.opaque = ctx->files;
1797c478bd9Sstevel@tonic-gate (void) evDeselectFD(opaqueCtx, id);
1807c478bd9Sstevel@tonic-gate }
1817c478bd9Sstevel@tonic-gate INSIST(revs >= 0);
1827c478bd9Sstevel@tonic-gate
1837c478bd9Sstevel@tonic-gate /* Timers. */
1847c478bd9Sstevel@tonic-gate evDestroyTimers(ctx);
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate /* Waits. */
1877c478bd9Sstevel@tonic-gate for (this_wl = ctx->waitLists;
1887c478bd9Sstevel@tonic-gate revs-- > 0 && this_wl != NULL;
1897c478bd9Sstevel@tonic-gate this_wl = next_wl) {
1907c478bd9Sstevel@tonic-gate next_wl = this_wl->next;
1917c478bd9Sstevel@tonic-gate for (this_wait = this_wl->first;
1927c478bd9Sstevel@tonic-gate revs-- > 0 && this_wait != NULL;
1937c478bd9Sstevel@tonic-gate this_wait = next_wait) {
1947c478bd9Sstevel@tonic-gate next_wait = this_wait->next;
1957c478bd9Sstevel@tonic-gate FREE(this_wait);
1967c478bd9Sstevel@tonic-gate }
1977c478bd9Sstevel@tonic-gate FREE(this_wl);
1987c478bd9Sstevel@tonic-gate }
1997c478bd9Sstevel@tonic-gate for (this_wait = ctx->waitDone.first;
2007c478bd9Sstevel@tonic-gate revs-- > 0 && this_wait != NULL;
2017c478bd9Sstevel@tonic-gate this_wait = next_wait) {
2027c478bd9Sstevel@tonic-gate next_wait = this_wait->next;
2037c478bd9Sstevel@tonic-gate FREE(this_wait);
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate FREE(ctx);
2077c478bd9Sstevel@tonic-gate return (0);
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate int
evGetNext(evContext opaqueCtx,evEvent * opaqueEv,int options)2117c478bd9Sstevel@tonic-gate evGetNext(evContext opaqueCtx, evEvent *opaqueEv, int options) {
2127c478bd9Sstevel@tonic-gate evContext_p *ctx = opaqueCtx.opaque;
2137c478bd9Sstevel@tonic-gate struct timespec nextTime;
2147c478bd9Sstevel@tonic-gate evTimer *nextTimer;
2157c478bd9Sstevel@tonic-gate evEvent_p *new;
2167c478bd9Sstevel@tonic-gate int x, pselect_errno, timerPast;
2177c478bd9Sstevel@tonic-gate #ifdef EVENTLIB_TIME_CHECKS
2187c478bd9Sstevel@tonic-gate struct timespec interval;
2197c478bd9Sstevel@tonic-gate #endif
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate /* Ensure that exactly one of EV_POLL or EV_WAIT was specified. */
2227c478bd9Sstevel@tonic-gate x = ((options & EV_POLL) != 0) + ((options & EV_WAIT) != 0);
2237c478bd9Sstevel@tonic-gate if (x != 1)
2247c478bd9Sstevel@tonic-gate EV_ERR(EINVAL);
2257c478bd9Sstevel@tonic-gate
2267c478bd9Sstevel@tonic-gate /* Get the time of day. We'll do this again after select() blocks. */
2277c478bd9Sstevel@tonic-gate ctx->lastEventTime = evNowTime();
2287c478bd9Sstevel@tonic-gate
2297c478bd9Sstevel@tonic-gate again:
2307c478bd9Sstevel@tonic-gate /* Finished accept()'s do not require a select(). */
2317c478bd9Sstevel@tonic-gate if (!EMPTY(ctx->accepts)) {
2327c478bd9Sstevel@tonic-gate OKNEW(new);
2337c478bd9Sstevel@tonic-gate new->type = Accept;
2347c478bd9Sstevel@tonic-gate new->u.accept.this = HEAD(ctx->accepts);
2357c478bd9Sstevel@tonic-gate UNLINK(ctx->accepts, HEAD(ctx->accepts), link);
2367c478bd9Sstevel@tonic-gate opaqueEv->opaque = new;
2377c478bd9Sstevel@tonic-gate return (0);
2387c478bd9Sstevel@tonic-gate }
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate /* Stream IO does not require a select(). */
2417c478bd9Sstevel@tonic-gate if (ctx->strDone != NULL) {
2427c478bd9Sstevel@tonic-gate OKNEW(new);
2437c478bd9Sstevel@tonic-gate new->type = Stream;
2447c478bd9Sstevel@tonic-gate new->u.stream.this = ctx->strDone;
2457c478bd9Sstevel@tonic-gate ctx->strDone = ctx->strDone->nextDone;
2467c478bd9Sstevel@tonic-gate if (ctx->strDone == NULL)
2477c478bd9Sstevel@tonic-gate ctx->strLast = NULL;
2487c478bd9Sstevel@tonic-gate opaqueEv->opaque = new;
2497c478bd9Sstevel@tonic-gate return (0);
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate
2527c478bd9Sstevel@tonic-gate /* Waits do not require a select(). */
2537c478bd9Sstevel@tonic-gate if (ctx->waitDone.first != NULL) {
2547c478bd9Sstevel@tonic-gate OKNEW(new);
2557c478bd9Sstevel@tonic-gate new->type = Wait;
2567c478bd9Sstevel@tonic-gate new->u.wait.this = ctx->waitDone.first;
2577c478bd9Sstevel@tonic-gate ctx->waitDone.first = ctx->waitDone.first->next;
2587c478bd9Sstevel@tonic-gate if (ctx->waitDone.first == NULL)
2597c478bd9Sstevel@tonic-gate ctx->waitDone.last = NULL;
2607c478bd9Sstevel@tonic-gate opaqueEv->opaque = new;
2617c478bd9Sstevel@tonic-gate return (0);
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate /* Get the status and content of the next timer. */
2657c478bd9Sstevel@tonic-gate if ((nextTimer = heap_element(ctx->timers, 1)) != NULL) {
2667c478bd9Sstevel@tonic-gate nextTime = nextTimer->due;
2677c478bd9Sstevel@tonic-gate timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0);
2687c478bd9Sstevel@tonic-gate } else
269*9525b14bSRao Shoaib timerPast = 0; /*%< Make gcc happy. */
2707c478bd9Sstevel@tonic-gate evPrintf(ctx, 9, "evGetNext: fdCount %d\n", ctx->fdCount);
2717c478bd9Sstevel@tonic-gate if (ctx->fdCount == 0) {
2727c478bd9Sstevel@tonic-gate static const struct timespec NoTime = {0, 0L};
2737c478bd9Sstevel@tonic-gate enum { JustPoll, Block, Timer } m;
2747c478bd9Sstevel@tonic-gate struct timespec t, *tp;
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate /* Are there any events at all? */
2777c478bd9Sstevel@tonic-gate if ((options & EV_WAIT) != 0 && !nextTimer && ctx->fdMax == -1)
2787c478bd9Sstevel@tonic-gate EV_ERR(ENOENT);
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate /* Figure out what select()'s timeout parameter should be. */
2817c478bd9Sstevel@tonic-gate if ((options & EV_POLL) != 0) {
2827c478bd9Sstevel@tonic-gate m = JustPoll;
2837c478bd9Sstevel@tonic-gate t = NoTime;
2847c478bd9Sstevel@tonic-gate tp = &t;
2857c478bd9Sstevel@tonic-gate } else if (nextTimer == NULL) {
2867c478bd9Sstevel@tonic-gate m = Block;
2877c478bd9Sstevel@tonic-gate /* ``t'' unused. */
2887c478bd9Sstevel@tonic-gate tp = NULL;
2897c478bd9Sstevel@tonic-gate } else if (timerPast) {
2907c478bd9Sstevel@tonic-gate m = JustPoll;
2917c478bd9Sstevel@tonic-gate t = NoTime;
2927c478bd9Sstevel@tonic-gate tp = &t;
2937c478bd9Sstevel@tonic-gate } else {
2947c478bd9Sstevel@tonic-gate m = Timer;
2957c478bd9Sstevel@tonic-gate /* ``t'' filled in later. */
2967c478bd9Sstevel@tonic-gate tp = &t;
2977c478bd9Sstevel@tonic-gate }
2987c478bd9Sstevel@tonic-gate #ifdef EVENTLIB_TIME_CHECKS
2997c478bd9Sstevel@tonic-gate if (ctx->debug > 0) {
3007c478bd9Sstevel@tonic-gate interval = evSubTime(ctx->lastEventTime,
3017c478bd9Sstevel@tonic-gate ctx->lastSelectTime);
302*9525b14bSRao Shoaib if (interval.tv_sec > 0 || interval.tv_nsec > 0)
3037c478bd9Sstevel@tonic-gate evPrintf(ctx, 1,
3047c478bd9Sstevel@tonic-gate "time between pselect() %u.%09u count %d\n",
3057c478bd9Sstevel@tonic-gate interval.tv_sec, interval.tv_nsec,
3067c478bd9Sstevel@tonic-gate ctx->lastFdCount);
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate #endif
3097c478bd9Sstevel@tonic-gate do {
310*9525b14bSRao Shoaib #ifndef USE_POLL
311*9525b14bSRao Shoaib /* XXX need to copy only the bits we are using. */
312*9525b14bSRao Shoaib ctx->rdLast = ctx->rdNext;
313*9525b14bSRao Shoaib ctx->wrLast = ctx->wrNext;
314*9525b14bSRao Shoaib ctx->exLast = ctx->exNext;
315*9525b14bSRao Shoaib #else
3167c478bd9Sstevel@tonic-gate /*
3177c478bd9Sstevel@tonic-gate * The pollfd structure uses separate fields for
3187c478bd9Sstevel@tonic-gate * the input and output events (corresponding to
3197c478bd9Sstevel@tonic-gate * the ??Next and ??Last fd sets), so there's no
3207c478bd9Sstevel@tonic-gate * need to copy one to the other.
3217c478bd9Sstevel@tonic-gate */
322*9525b14bSRao Shoaib #endif /* USE_POLL */
3237c478bd9Sstevel@tonic-gate if (m == Timer) {
3247c478bd9Sstevel@tonic-gate INSIST(tp == &t);
3257c478bd9Sstevel@tonic-gate t = evSubTime(nextTime, ctx->lastEventTime);
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate /* XXX should predict system's earliness and adjust. */
3297c478bd9Sstevel@tonic-gate x = pselect(ctx->fdMax+1,
3307c478bd9Sstevel@tonic-gate &ctx->rdLast, &ctx->wrLast, &ctx->exLast,
3317c478bd9Sstevel@tonic-gate tp, NULL);
3327c478bd9Sstevel@tonic-gate pselect_errno = errno;
3337c478bd9Sstevel@tonic-gate
334*9525b14bSRao Shoaib #ifndef USE_POLL
3357c478bd9Sstevel@tonic-gate evPrintf(ctx, 4, "select() returns %d (err: %s)\n",
3367c478bd9Sstevel@tonic-gate x, (x == -1) ? strerror(errno) : "none");
337*9525b14bSRao Shoaib #else
338*9525b14bSRao Shoaib evPrintf(ctx, 4, "poll() returns %d (err: %s)\n",
339*9525b14bSRao Shoaib x, (x == -1) ? strerror(errno) : "none");
340*9525b14bSRao Shoaib #endif /* USE_POLL */
3417c478bd9Sstevel@tonic-gate /* Anything but a poll can change the time. */
3427c478bd9Sstevel@tonic-gate if (m != JustPoll)
3437c478bd9Sstevel@tonic-gate ctx->lastEventTime = evNowTime();
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate /* Select() likes to finish about 10ms early. */
3467c478bd9Sstevel@tonic-gate } while (x == 0 && m == Timer &&
3477c478bd9Sstevel@tonic-gate evCmpTime(ctx->lastEventTime, nextTime) < 0);
3487c478bd9Sstevel@tonic-gate #ifdef EVENTLIB_TIME_CHECKS
3497c478bd9Sstevel@tonic-gate ctx->lastSelectTime = ctx->lastEventTime;
3507c478bd9Sstevel@tonic-gate #endif
3517c478bd9Sstevel@tonic-gate if (x < 0) {
3527c478bd9Sstevel@tonic-gate if (pselect_errno == EINTR) {
3537c478bd9Sstevel@tonic-gate if ((options & EV_NULL) != 0)
3547c478bd9Sstevel@tonic-gate goto again;
3557c478bd9Sstevel@tonic-gate OKNEW(new);
3567c478bd9Sstevel@tonic-gate new->type = Null;
3577c478bd9Sstevel@tonic-gate /* No data. */
3587c478bd9Sstevel@tonic-gate opaqueEv->opaque = new;
3597c478bd9Sstevel@tonic-gate return (0);
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate if (pselect_errno == EBADF) {
3627c478bd9Sstevel@tonic-gate for (x = 0; x <= ctx->fdMax; x++) {
3637c478bd9Sstevel@tonic-gate struct stat sb;
3647c478bd9Sstevel@tonic-gate
3657c478bd9Sstevel@tonic-gate if (FD_ISSET(x, &ctx->rdNext) == 0 &&
3667c478bd9Sstevel@tonic-gate FD_ISSET(x, &ctx->wrNext) == 0 &&
3677c478bd9Sstevel@tonic-gate FD_ISSET(x, &ctx->exNext) == 0)
3687c478bd9Sstevel@tonic-gate continue;
3697c478bd9Sstevel@tonic-gate if (fstat(x, &sb) == -1 &&
3707c478bd9Sstevel@tonic-gate errno == EBADF)
3717c478bd9Sstevel@tonic-gate evPrintf(ctx, 1, "EBADF: %d\n",
3727c478bd9Sstevel@tonic-gate x);
3737c478bd9Sstevel@tonic-gate }
3747c478bd9Sstevel@tonic-gate abort();
3757c478bd9Sstevel@tonic-gate }
3767c478bd9Sstevel@tonic-gate EV_ERR(pselect_errno);
3777c478bd9Sstevel@tonic-gate }
3787c478bd9Sstevel@tonic-gate if (x == 0 && (nextTimer == NULL || !timerPast) &&
3797c478bd9Sstevel@tonic-gate (options & EV_POLL))
3807c478bd9Sstevel@tonic-gate EV_ERR(EWOULDBLOCK);
3817c478bd9Sstevel@tonic-gate ctx->fdCount = x;
3827c478bd9Sstevel@tonic-gate #ifdef EVENTLIB_TIME_CHECKS
3837c478bd9Sstevel@tonic-gate ctx->lastFdCount = x;
3847c478bd9Sstevel@tonic-gate #endif
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate INSIST(nextTimer || ctx->fdCount);
3877c478bd9Sstevel@tonic-gate
3887c478bd9Sstevel@tonic-gate /* Timers go first since we'd like them to be accurate. */
3897c478bd9Sstevel@tonic-gate if (nextTimer && !timerPast) {
3907c478bd9Sstevel@tonic-gate /* Has anything happened since we blocked? */
3917c478bd9Sstevel@tonic-gate timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0);
3927c478bd9Sstevel@tonic-gate }
3937c478bd9Sstevel@tonic-gate if (nextTimer && timerPast) {
3947c478bd9Sstevel@tonic-gate OKNEW(new);
3957c478bd9Sstevel@tonic-gate new->type = Timer;
3967c478bd9Sstevel@tonic-gate new->u.timer.this = nextTimer;
3977c478bd9Sstevel@tonic-gate opaqueEv->opaque = new;
3987c478bd9Sstevel@tonic-gate return (0);
3997c478bd9Sstevel@tonic-gate }
4007c478bd9Sstevel@tonic-gate
4017c478bd9Sstevel@tonic-gate /* No timers, so there should be a ready file descriptor. */
4027c478bd9Sstevel@tonic-gate x = 0;
4037c478bd9Sstevel@tonic-gate while (ctx->fdCount > 0) {
4047c478bd9Sstevel@tonic-gate evFile *fid;
4057c478bd9Sstevel@tonic-gate int fd, eventmask;
4067c478bd9Sstevel@tonic-gate
4077c478bd9Sstevel@tonic-gate if (ctx->fdNext == NULL) {
4087c478bd9Sstevel@tonic-gate if (++x == 2) {
4097c478bd9Sstevel@tonic-gate /*
4107c478bd9Sstevel@tonic-gate * Hitting the end twice means that the last
4117c478bd9Sstevel@tonic-gate * select() found some FD's which have since
4127c478bd9Sstevel@tonic-gate * been deselected.
4137c478bd9Sstevel@tonic-gate *
4147c478bd9Sstevel@tonic-gate * On some systems, the count returned by
4157c478bd9Sstevel@tonic-gate * selects is the total number of bits in
4167c478bd9Sstevel@tonic-gate * all masks that are set, and on others it's
4177c478bd9Sstevel@tonic-gate * the number of fd's that have some bit set,
4187c478bd9Sstevel@tonic-gate * and on others, it's just broken. We
4197c478bd9Sstevel@tonic-gate * always assume that it's the number of
4207c478bd9Sstevel@tonic-gate * bits set in all masks, because that's what
4217c478bd9Sstevel@tonic-gate * the man page says it should do, and
4227c478bd9Sstevel@tonic-gate * the worst that can happen is we do an
4237c478bd9Sstevel@tonic-gate * extra select().
4247c478bd9Sstevel@tonic-gate */
4257c478bd9Sstevel@tonic-gate ctx->fdCount = 0;
4267c478bd9Sstevel@tonic-gate break;
4277c478bd9Sstevel@tonic-gate }
4287c478bd9Sstevel@tonic-gate ctx->fdNext = ctx->files;
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate fid = ctx->fdNext;
4317c478bd9Sstevel@tonic-gate ctx->fdNext = fid->next;
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate fd = fid->fd;
4347c478bd9Sstevel@tonic-gate eventmask = 0;
4357c478bd9Sstevel@tonic-gate if (FD_ISSET(fd, &ctx->rdLast))
4367c478bd9Sstevel@tonic-gate eventmask |= EV_READ;
4377c478bd9Sstevel@tonic-gate if (FD_ISSET(fd, &ctx->wrLast))
4387c478bd9Sstevel@tonic-gate eventmask |= EV_WRITE;
4397c478bd9Sstevel@tonic-gate if (FD_ISSET(fd, &ctx->exLast))
4407c478bd9Sstevel@tonic-gate eventmask |= EV_EXCEPT;
4417c478bd9Sstevel@tonic-gate eventmask &= fid->eventmask;
4427c478bd9Sstevel@tonic-gate if (eventmask != 0) {
4437c478bd9Sstevel@tonic-gate if ((eventmask & EV_READ) != 0) {
4447c478bd9Sstevel@tonic-gate FD_CLR(fd, &ctx->rdLast);
4457c478bd9Sstevel@tonic-gate ctx->fdCount--;
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate if ((eventmask & EV_WRITE) != 0) {
4487c478bd9Sstevel@tonic-gate FD_CLR(fd, &ctx->wrLast);
4497c478bd9Sstevel@tonic-gate ctx->fdCount--;
4507c478bd9Sstevel@tonic-gate }
4517c478bd9Sstevel@tonic-gate if ((eventmask & EV_EXCEPT) != 0) {
4527c478bd9Sstevel@tonic-gate FD_CLR(fd, &ctx->exLast);
4537c478bd9Sstevel@tonic-gate ctx->fdCount--;
4547c478bd9Sstevel@tonic-gate }
4557c478bd9Sstevel@tonic-gate OKNEW(new);
4567c478bd9Sstevel@tonic-gate new->type = File;
4577c478bd9Sstevel@tonic-gate new->u.file.this = fid;
4587c478bd9Sstevel@tonic-gate new->u.file.eventmask = eventmask;
4597c478bd9Sstevel@tonic-gate opaqueEv->opaque = new;
4607c478bd9Sstevel@tonic-gate return (0);
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate }
4637c478bd9Sstevel@tonic-gate if (ctx->fdCount < 0) {
4647c478bd9Sstevel@tonic-gate /*
4657c478bd9Sstevel@tonic-gate * select()'s count is off on a number of systems, and
4667c478bd9Sstevel@tonic-gate * can result in fdCount < 0.
4677c478bd9Sstevel@tonic-gate */
4687c478bd9Sstevel@tonic-gate evPrintf(ctx, 4, "fdCount < 0 (%d)\n", ctx->fdCount);
4697c478bd9Sstevel@tonic-gate ctx->fdCount = 0;
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate
4727c478bd9Sstevel@tonic-gate /* We get here if the caller deselect()'s an FD. Gag me with a goto. */
4737c478bd9Sstevel@tonic-gate goto again;
4747c478bd9Sstevel@tonic-gate }
4757c478bd9Sstevel@tonic-gate
4767c478bd9Sstevel@tonic-gate int
evDispatch(evContext opaqueCtx,evEvent opaqueEv)4777c478bd9Sstevel@tonic-gate evDispatch(evContext opaqueCtx, evEvent opaqueEv) {
4787c478bd9Sstevel@tonic-gate evContext_p *ctx = opaqueCtx.opaque;
4797c478bd9Sstevel@tonic-gate evEvent_p *ev = opaqueEv.opaque;
4807c478bd9Sstevel@tonic-gate #ifdef EVENTLIB_TIME_CHECKS
4817c478bd9Sstevel@tonic-gate void *func;
4827c478bd9Sstevel@tonic-gate struct timespec start_time;
4837c478bd9Sstevel@tonic-gate struct timespec interval;
4847c478bd9Sstevel@tonic-gate #endif
4857c478bd9Sstevel@tonic-gate
4867c478bd9Sstevel@tonic-gate #ifdef EVENTLIB_TIME_CHECKS
4877c478bd9Sstevel@tonic-gate if (ctx->debug > 0)
4887c478bd9Sstevel@tonic-gate start_time = evNowTime();
4897c478bd9Sstevel@tonic-gate #endif
4907c478bd9Sstevel@tonic-gate ctx->cur = ev;
4917c478bd9Sstevel@tonic-gate switch (ev->type) {
4927c478bd9Sstevel@tonic-gate case Accept: {
4937c478bd9Sstevel@tonic-gate evAccept *this = ev->u.accept.this;
4947c478bd9Sstevel@tonic-gate
4957c478bd9Sstevel@tonic-gate evPrintf(ctx, 5,
4967c478bd9Sstevel@tonic-gate "Dispatch.Accept: fd %d -> %d, func %p, uap %p\n",
4977c478bd9Sstevel@tonic-gate this->conn->fd, this->fd,
4987c478bd9Sstevel@tonic-gate this->conn->func, this->conn->uap);
4997c478bd9Sstevel@tonic-gate errno = this->ioErrno;
5007c478bd9Sstevel@tonic-gate (this->conn->func)(opaqueCtx, this->conn->uap, this->fd,
5017c478bd9Sstevel@tonic-gate &this->la, this->lalen,
5027c478bd9Sstevel@tonic-gate &this->ra, this->ralen);
5037c478bd9Sstevel@tonic-gate #ifdef EVENTLIB_TIME_CHECKS
5047c478bd9Sstevel@tonic-gate func = this->conn->func;
5057c478bd9Sstevel@tonic-gate #endif
5067c478bd9Sstevel@tonic-gate break;
5077c478bd9Sstevel@tonic-gate }
5087c478bd9Sstevel@tonic-gate case File: {
5097c478bd9Sstevel@tonic-gate evFile *this = ev->u.file.this;
5107c478bd9Sstevel@tonic-gate int eventmask = ev->u.file.eventmask;
5117c478bd9Sstevel@tonic-gate
5127c478bd9Sstevel@tonic-gate evPrintf(ctx, 5,
5137c478bd9Sstevel@tonic-gate "Dispatch.File: fd %d, mask 0x%x, func %p, uap %p\n",
5147c478bd9Sstevel@tonic-gate this->fd, this->eventmask, this->func, this->uap);
5157c478bd9Sstevel@tonic-gate (this->func)(opaqueCtx, this->uap, this->fd, eventmask);
5167c478bd9Sstevel@tonic-gate #ifdef EVENTLIB_TIME_CHECKS
5177c478bd9Sstevel@tonic-gate func = this->func;
5187c478bd9Sstevel@tonic-gate #endif
5197c478bd9Sstevel@tonic-gate break;
5207c478bd9Sstevel@tonic-gate }
5217c478bd9Sstevel@tonic-gate case Stream: {
5227c478bd9Sstevel@tonic-gate evStream *this = ev->u.stream.this;
5237c478bd9Sstevel@tonic-gate
5247c478bd9Sstevel@tonic-gate evPrintf(ctx, 5,
5257c478bd9Sstevel@tonic-gate "Dispatch.Stream: fd %d, func %p, uap %p\n",
5267c478bd9Sstevel@tonic-gate this->fd, this->func, this->uap);
5277c478bd9Sstevel@tonic-gate errno = this->ioErrno;
5287c478bd9Sstevel@tonic-gate (this->func)(opaqueCtx, this->uap, this->fd, this->ioDone);
5297c478bd9Sstevel@tonic-gate #ifdef EVENTLIB_TIME_CHECKS
5307c478bd9Sstevel@tonic-gate func = this->func;
5317c478bd9Sstevel@tonic-gate #endif
5327c478bd9Sstevel@tonic-gate break;
5337c478bd9Sstevel@tonic-gate }
5347c478bd9Sstevel@tonic-gate case Timer: {
5357c478bd9Sstevel@tonic-gate evTimer *this = ev->u.timer.this;
5367c478bd9Sstevel@tonic-gate
5377c478bd9Sstevel@tonic-gate evPrintf(ctx, 5, "Dispatch.Timer: func %p, uap %p\n",
5387c478bd9Sstevel@tonic-gate this->func, this->uap);
5397c478bd9Sstevel@tonic-gate (this->func)(opaqueCtx, this->uap, this->due, this->inter);
5407c478bd9Sstevel@tonic-gate #ifdef EVENTLIB_TIME_CHECKS
5417c478bd9Sstevel@tonic-gate func = this->func;
5427c478bd9Sstevel@tonic-gate #endif
5437c478bd9Sstevel@tonic-gate break;
5447c478bd9Sstevel@tonic-gate }
5457c478bd9Sstevel@tonic-gate case Wait: {
5467c478bd9Sstevel@tonic-gate evWait *this = ev->u.wait.this;
5477c478bd9Sstevel@tonic-gate
5487c478bd9Sstevel@tonic-gate evPrintf(ctx, 5,
5497c478bd9Sstevel@tonic-gate "Dispatch.Wait: tag %p, func %p, uap %p\n",
5507c478bd9Sstevel@tonic-gate this->tag, this->func, this->uap);
5517c478bd9Sstevel@tonic-gate (this->func)(opaqueCtx, this->uap, this->tag);
5527c478bd9Sstevel@tonic-gate #ifdef EVENTLIB_TIME_CHECKS
5537c478bd9Sstevel@tonic-gate func = this->func;
5547c478bd9Sstevel@tonic-gate #endif
5557c478bd9Sstevel@tonic-gate break;
5567c478bd9Sstevel@tonic-gate }
5577c478bd9Sstevel@tonic-gate case Null: {
5587c478bd9Sstevel@tonic-gate /* No work. */
5597c478bd9Sstevel@tonic-gate #ifdef EVENTLIB_TIME_CHECKS
5607c478bd9Sstevel@tonic-gate func = NULL;
5617c478bd9Sstevel@tonic-gate #endif
5627c478bd9Sstevel@tonic-gate break;
5637c478bd9Sstevel@tonic-gate }
5647c478bd9Sstevel@tonic-gate default: {
5657c478bd9Sstevel@tonic-gate abort();
5667c478bd9Sstevel@tonic-gate }
5677c478bd9Sstevel@tonic-gate }
5687c478bd9Sstevel@tonic-gate #ifdef EVENTLIB_TIME_CHECKS
5697c478bd9Sstevel@tonic-gate if (ctx->debug > 0) {
5707c478bd9Sstevel@tonic-gate interval = evSubTime(evNowTime(), start_time);
5717c478bd9Sstevel@tonic-gate /*
5727c478bd9Sstevel@tonic-gate * Complain if it took longer than 50 milliseconds.
5737c478bd9Sstevel@tonic-gate *
5747c478bd9Sstevel@tonic-gate * We call getuid() to make an easy to find mark in a kernel
5757c478bd9Sstevel@tonic-gate * trace.
5767c478bd9Sstevel@tonic-gate */
5777c478bd9Sstevel@tonic-gate if (interval.tv_sec > 0 || interval.tv_nsec > 50000000)
5787c478bd9Sstevel@tonic-gate evPrintf(ctx, 1,
5797c478bd9Sstevel@tonic-gate "dispatch interval %u.%09u uid %d type %d func %p\n",
5807c478bd9Sstevel@tonic-gate interval.tv_sec, interval.tv_nsec,
5817c478bd9Sstevel@tonic-gate getuid(), ev->type, func);
5827c478bd9Sstevel@tonic-gate }
5837c478bd9Sstevel@tonic-gate #endif
5847c478bd9Sstevel@tonic-gate ctx->cur = NULL;
5857c478bd9Sstevel@tonic-gate evDrop(opaqueCtx, opaqueEv);
5867c478bd9Sstevel@tonic-gate return (0);
5877c478bd9Sstevel@tonic-gate }
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate void
evDrop(evContext opaqueCtx,evEvent opaqueEv)5907c478bd9Sstevel@tonic-gate evDrop(evContext opaqueCtx, evEvent opaqueEv) {
5917c478bd9Sstevel@tonic-gate evContext_p *ctx = opaqueCtx.opaque;
5927c478bd9Sstevel@tonic-gate evEvent_p *ev = opaqueEv.opaque;
5937c478bd9Sstevel@tonic-gate
5947c478bd9Sstevel@tonic-gate switch (ev->type) {
5957c478bd9Sstevel@tonic-gate case Accept: {
5967c478bd9Sstevel@tonic-gate FREE(ev->u.accept.this);
5977c478bd9Sstevel@tonic-gate break;
5987c478bd9Sstevel@tonic-gate }
5997c478bd9Sstevel@tonic-gate case File: {
6007c478bd9Sstevel@tonic-gate /* No work. */
6017c478bd9Sstevel@tonic-gate break;
6027c478bd9Sstevel@tonic-gate }
6037c478bd9Sstevel@tonic-gate case Stream: {
6047c478bd9Sstevel@tonic-gate evStreamID id;
6057c478bd9Sstevel@tonic-gate
6067c478bd9Sstevel@tonic-gate id.opaque = ev->u.stream.this;
6077c478bd9Sstevel@tonic-gate (void) evCancelRW(opaqueCtx, id);
6087c478bd9Sstevel@tonic-gate break;
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate case Timer: {
6117c478bd9Sstevel@tonic-gate evTimer *this = ev->u.timer.this;
6127c478bd9Sstevel@tonic-gate evTimerID opaque;
6137c478bd9Sstevel@tonic-gate
6147c478bd9Sstevel@tonic-gate /* Check to see whether the user func cleared the timer. */
6157c478bd9Sstevel@tonic-gate if (heap_element(ctx->timers, this->index) != this) {
6167c478bd9Sstevel@tonic-gate evPrintf(ctx, 5, "Dispatch.Timer: timer rm'd?\n");
6177c478bd9Sstevel@tonic-gate break;
6187c478bd9Sstevel@tonic-gate }
6197c478bd9Sstevel@tonic-gate /*
6207c478bd9Sstevel@tonic-gate * Timer is still there. Delete it if it has expired,
6217c478bd9Sstevel@tonic-gate * otherwise set it according to its next interval.
6227c478bd9Sstevel@tonic-gate */
623*9525b14bSRao Shoaib if (this->inter.tv_sec == (time_t)0 &&
624*9525b14bSRao Shoaib this->inter.tv_nsec == 0L) {
6257c478bd9Sstevel@tonic-gate opaque.opaque = this;
6267c478bd9Sstevel@tonic-gate (void) evClearTimer(opaqueCtx, opaque);
6277c478bd9Sstevel@tonic-gate } else {
6287c478bd9Sstevel@tonic-gate opaque.opaque = this;
6297c478bd9Sstevel@tonic-gate (void) evResetTimer(opaqueCtx, opaque, this->func,
6307c478bd9Sstevel@tonic-gate this->uap,
631*9525b14bSRao Shoaib evAddTime((this->mode & EV_TMR_RATE) ?
632*9525b14bSRao Shoaib this->due :
633*9525b14bSRao Shoaib ctx->lastEventTime,
6347c478bd9Sstevel@tonic-gate this->inter),
6357c478bd9Sstevel@tonic-gate this->inter);
6367c478bd9Sstevel@tonic-gate }
6377c478bd9Sstevel@tonic-gate break;
6387c478bd9Sstevel@tonic-gate }
6397c478bd9Sstevel@tonic-gate case Wait: {
6407c478bd9Sstevel@tonic-gate FREE(ev->u.wait.this);
6417c478bd9Sstevel@tonic-gate break;
6427c478bd9Sstevel@tonic-gate }
6437c478bd9Sstevel@tonic-gate case Null: {
6447c478bd9Sstevel@tonic-gate /* No work. */
6457c478bd9Sstevel@tonic-gate break;
6467c478bd9Sstevel@tonic-gate }
6477c478bd9Sstevel@tonic-gate default: {
6487c478bd9Sstevel@tonic-gate abort();
6497c478bd9Sstevel@tonic-gate }
6507c478bd9Sstevel@tonic-gate }
6517c478bd9Sstevel@tonic-gate FREE(ev);
6527c478bd9Sstevel@tonic-gate }
6537c478bd9Sstevel@tonic-gate
6547c478bd9Sstevel@tonic-gate int
evMainLoop(evContext opaqueCtx)6557c478bd9Sstevel@tonic-gate evMainLoop(evContext opaqueCtx) {
6567c478bd9Sstevel@tonic-gate evEvent event;
6577c478bd9Sstevel@tonic-gate int x;
6587c478bd9Sstevel@tonic-gate
6597c478bd9Sstevel@tonic-gate while ((x = evGetNext(opaqueCtx, &event, EV_WAIT)) == 0)
6607c478bd9Sstevel@tonic-gate if ((x = evDispatch(opaqueCtx, event)) < 0)
6617c478bd9Sstevel@tonic-gate break;
6627c478bd9Sstevel@tonic-gate return (x);
6637c478bd9Sstevel@tonic-gate }
6647c478bd9Sstevel@tonic-gate
6657c478bd9Sstevel@tonic-gate int
evHighestFD(evContext opaqueCtx)6667c478bd9Sstevel@tonic-gate evHighestFD(evContext opaqueCtx) {
6677c478bd9Sstevel@tonic-gate evContext_p *ctx = opaqueCtx.opaque;
6687c478bd9Sstevel@tonic-gate
6697c478bd9Sstevel@tonic-gate return (ctx->highestFD);
6707c478bd9Sstevel@tonic-gate }
6717c478bd9Sstevel@tonic-gate
6727c478bd9Sstevel@tonic-gate void
evPrintf(const evContext_p * ctx,int level,const char * fmt,...)6737c478bd9Sstevel@tonic-gate evPrintf(const evContext_p *ctx, int level, const char *fmt, ...) {
6747c478bd9Sstevel@tonic-gate va_list ap;
6757c478bd9Sstevel@tonic-gate
6767c478bd9Sstevel@tonic-gate va_start(ap, fmt);
6777c478bd9Sstevel@tonic-gate if (ctx->output != NULL && ctx->debug >= level) {
6787c478bd9Sstevel@tonic-gate vfprintf(ctx->output, fmt, ap);
6797c478bd9Sstevel@tonic-gate fflush(ctx->output);
6807c478bd9Sstevel@tonic-gate }
6817c478bd9Sstevel@tonic-gate va_end(ap);
6827c478bd9Sstevel@tonic-gate }
6837c478bd9Sstevel@tonic-gate
684*9525b14bSRao Shoaib int
evSetOption(evContext * opaqueCtx,const char * option,int value)685*9525b14bSRao Shoaib evSetOption(evContext *opaqueCtx, const char *option, int value) {
686*9525b14bSRao Shoaib /* evContext_p *ctx = opaqueCtx->opaque; */
687*9525b14bSRao Shoaib
688*9525b14bSRao Shoaib UNUSED(opaqueCtx);
689*9525b14bSRao Shoaib UNUSED(value);
690*9525b14bSRao Shoaib #ifndef CLOCK_MONOTONIC
691*9525b14bSRao Shoaib UNUSED(option);
692*9525b14bSRao Shoaib #endif
693*9525b14bSRao Shoaib
694*9525b14bSRao Shoaib #ifdef CLOCK_MONOTONIC
695*9525b14bSRao Shoaib if (strcmp(option, "monotime") == 0) {
696*9525b14bSRao Shoaib if (opaqueCtx != NULL)
697*9525b14bSRao Shoaib errno = EINVAL;
698*9525b14bSRao Shoaib if (value == 0 || value == 1) {
699*9525b14bSRao Shoaib __evOptMonoTime = value;
700*9525b14bSRao Shoaib return (0);
701*9525b14bSRao Shoaib } else {
702*9525b14bSRao Shoaib errno = EINVAL;
703*9525b14bSRao Shoaib return (-1);
704*9525b14bSRao Shoaib }
705*9525b14bSRao Shoaib }
706*9525b14bSRao Shoaib #endif
707*9525b14bSRao Shoaib errno = ENOENT;
708*9525b14bSRao Shoaib return (-1);
709*9525b14bSRao Shoaib }
710*9525b14bSRao Shoaib
711*9525b14bSRao Shoaib int
evGetOption(evContext * opaqueCtx,const char * option,int * value)712*9525b14bSRao Shoaib evGetOption(evContext *opaqueCtx, const char *option, int *value) {
713*9525b14bSRao Shoaib /* evContext_p *ctx = opaqueCtx->opaque; */
714*9525b14bSRao Shoaib
715*9525b14bSRao Shoaib UNUSED(opaqueCtx);
716*9525b14bSRao Shoaib #ifndef CLOCK_MONOTONIC
717*9525b14bSRao Shoaib UNUSED(value);
718*9525b14bSRao Shoaib UNUSED(option);
719*9525b14bSRao Shoaib #endif
720*9525b14bSRao Shoaib
721*9525b14bSRao Shoaib #ifdef CLOCK_MONOTONIC
722*9525b14bSRao Shoaib if (strcmp(option, "monotime") == 0) {
723*9525b14bSRao Shoaib if (opaqueCtx != NULL)
724*9525b14bSRao Shoaib errno = EINVAL;
725*9525b14bSRao Shoaib *value = __evOptMonoTime;
726*9525b14bSRao Shoaib return (0);
727*9525b14bSRao Shoaib }
728*9525b14bSRao Shoaib #endif
729*9525b14bSRao Shoaib errno = ENOENT;
730*9525b14bSRao Shoaib return (-1);
731*9525b14bSRao Shoaib }
732*9525b14bSRao Shoaib
733*9525b14bSRao Shoaib #if defined(NEED_PSELECT) || defined(USE_POLL)
7347c478bd9Sstevel@tonic-gate /* XXX needs to move to the porting library. */
7357c478bd9Sstevel@tonic-gate static int
pselect(int nfds,void * rfds,void * wfds,void * efds,struct timespec * tsp,const sigset_t * sigmask)7367c478bd9Sstevel@tonic-gate pselect(int nfds, void *rfds, void *wfds, void *efds,
7377c478bd9Sstevel@tonic-gate struct timespec *tsp,
7387c478bd9Sstevel@tonic-gate const sigset_t *sigmask)
7397c478bd9Sstevel@tonic-gate {
7407c478bd9Sstevel@tonic-gate struct timeval tv, *tvp;
7417c478bd9Sstevel@tonic-gate sigset_t sigs;
7427c478bd9Sstevel@tonic-gate int n;
743*9525b14bSRao Shoaib #ifdef USE_POLL
7447c478bd9Sstevel@tonic-gate int polltimeout = INFTIM;
7457c478bd9Sstevel@tonic-gate evContext_p *ctx;
7467c478bd9Sstevel@tonic-gate struct pollfd *fds;
7477c478bd9Sstevel@tonic-gate nfds_t pnfds;
748*9525b14bSRao Shoaib
749*9525b14bSRao Shoaib UNUSED(nfds);
750*9525b14bSRao Shoaib #endif /* USE_POLL */
7517c478bd9Sstevel@tonic-gate
7527c478bd9Sstevel@tonic-gate if (tsp) {
7537c478bd9Sstevel@tonic-gate tvp = &tv;
7547c478bd9Sstevel@tonic-gate tv = evTimeVal(*tsp);
755*9525b14bSRao Shoaib #ifdef USE_POLL
7567c478bd9Sstevel@tonic-gate polltimeout = 1000 * tv.tv_sec + tv.tv_usec / 1000;
757*9525b14bSRao Shoaib #endif /* USE_POLL */
7587c478bd9Sstevel@tonic-gate } else
7597c478bd9Sstevel@tonic-gate tvp = NULL;
7607c478bd9Sstevel@tonic-gate if (sigmask)
7617c478bd9Sstevel@tonic-gate sigprocmask(SIG_SETMASK, sigmask, &sigs);
762*9525b14bSRao Shoaib #ifndef USE_POLL
763*9525b14bSRao Shoaib n = select(nfds, rfds, wfds, efds, tvp);
764*9525b14bSRao Shoaib #else
7657c478bd9Sstevel@tonic-gate /*
7667c478bd9Sstevel@tonic-gate * rfds, wfds, and efds should all be from the same evContext_p,
7677c478bd9Sstevel@tonic-gate * so any of them will do. If they're all NULL, the caller is
7687c478bd9Sstevel@tonic-gate * presumably calling us to block.
7697c478bd9Sstevel@tonic-gate */
770*9525b14bSRao Shoaib if (rfds != NULL)
7717c478bd9Sstevel@tonic-gate ctx = ((__evEmulMask *)rfds)->ctx;
772*9525b14bSRao Shoaib else if (wfds != NULL)
7737c478bd9Sstevel@tonic-gate ctx = ((__evEmulMask *)wfds)->ctx;
774*9525b14bSRao Shoaib else if (efds != NULL)
7757c478bd9Sstevel@tonic-gate ctx = ((__evEmulMask *)efds)->ctx;
7767c478bd9Sstevel@tonic-gate else
777*9525b14bSRao Shoaib ctx = NULL;
778*9525b14bSRao Shoaib if (ctx != NULL && ctx->fdMax != -1) {
7797c478bd9Sstevel@tonic-gate fds = &(ctx->pollfds[ctx->firstfd]);
7807c478bd9Sstevel@tonic-gate pnfds = ctx->fdMax - ctx->firstfd + 1;
7817c478bd9Sstevel@tonic-gate } else {
782*9525b14bSRao Shoaib fds = NULL;
7837c478bd9Sstevel@tonic-gate pnfds = 0;
7847c478bd9Sstevel@tonic-gate }
7857c478bd9Sstevel@tonic-gate n = poll(fds, pnfds, polltimeout);
7867c478bd9Sstevel@tonic-gate if (n > 0) {
7877c478bd9Sstevel@tonic-gate int i, e;
788*9525b14bSRao Shoaib
789*9525b14bSRao Shoaib INSIST(ctx != NULL);
7907c478bd9Sstevel@tonic-gate for (e = 0, i = ctx->firstfd; i <= ctx->fdMax; i++) {
7917c478bd9Sstevel@tonic-gate if (ctx->pollfds[i].fd < 0)
7927c478bd9Sstevel@tonic-gate continue;
7937c478bd9Sstevel@tonic-gate if (FD_ISSET(i, &ctx->rdLast))
7947c478bd9Sstevel@tonic-gate e++;
7957c478bd9Sstevel@tonic-gate if (FD_ISSET(i, &ctx->wrLast))
7967c478bd9Sstevel@tonic-gate e++;
7977c478bd9Sstevel@tonic-gate if (FD_ISSET(i, &ctx->exLast))
7987c478bd9Sstevel@tonic-gate e++;
7997c478bd9Sstevel@tonic-gate }
8007c478bd9Sstevel@tonic-gate n = e;
8017c478bd9Sstevel@tonic-gate }
802*9525b14bSRao Shoaib #endif /* USE_POLL */
8037c478bd9Sstevel@tonic-gate if (sigmask)
8047c478bd9Sstevel@tonic-gate sigprocmask(SIG_SETMASK, &sigs, NULL);
8057c478bd9Sstevel@tonic-gate if (tsp)
8067c478bd9Sstevel@tonic-gate *tsp = evTimeSpec(tv);
8077c478bd9Sstevel@tonic-gate return (n);
8087c478bd9Sstevel@tonic-gate }
8097c478bd9Sstevel@tonic-gate #endif
8107c478bd9Sstevel@tonic-gate
811*9525b14bSRao Shoaib #ifdef USE_POLL
812*9525b14bSRao Shoaib int
evPollfdRealloc(evContext_p * ctx,int pollfd_chunk_size,int fd)8137c478bd9Sstevel@tonic-gate evPollfdRealloc(evContext_p *ctx, int pollfd_chunk_size, int fd) {
8147c478bd9Sstevel@tonic-gate
815*9525b14bSRao Shoaib int i, maxnfds;
816*9525b14bSRao Shoaib void *pollfds, *fdTable;
8177c478bd9Sstevel@tonic-gate
818*9525b14bSRao Shoaib if (fd < ctx->maxnfds)
819*9525b14bSRao Shoaib return (0);
8207c478bd9Sstevel@tonic-gate
8217c478bd9Sstevel@tonic-gate /* Don't allow ridiculously small values for pollfd_chunk_size */
8227c478bd9Sstevel@tonic-gate if (pollfd_chunk_size < 20)
8237c478bd9Sstevel@tonic-gate pollfd_chunk_size = 20;
8247c478bd9Sstevel@tonic-gate
825*9525b14bSRao Shoaib maxnfds = (1 + (fd/pollfd_chunk_size)) * pollfd_chunk_size;
8267c478bd9Sstevel@tonic-gate
827*9525b14bSRao Shoaib pollfds = realloc(ctx->pollfds, maxnfds * sizeof(*ctx->pollfds));
828*9525b14bSRao Shoaib if (pollfds != NULL)
829*9525b14bSRao Shoaib ctx->pollfds = pollfds;
830*9525b14bSRao Shoaib fdTable = realloc(ctx->fdTable, maxnfds * sizeof(*ctx->fdTable));
831*9525b14bSRao Shoaib if (fdTable != NULL)
832*9525b14bSRao Shoaib ctx->fdTable = fdTable;
8337c478bd9Sstevel@tonic-gate
834*9525b14bSRao Shoaib if (pollfds == NULL || fdTable == NULL) {
835*9525b14bSRao Shoaib evPrintf(ctx, 2, "pollfd() realloc (%ld) failed\n",
836*9525b14bSRao Shoaib (long)maxnfds*sizeof(struct pollfd));
837*9525b14bSRao Shoaib return (-1);
8387c478bd9Sstevel@tonic-gate }
8397c478bd9Sstevel@tonic-gate
840*9525b14bSRao Shoaib for (i = ctx->maxnfds; i < maxnfds; i++) {
8417c478bd9Sstevel@tonic-gate ctx->pollfds[i].fd = -1;
8427c478bd9Sstevel@tonic-gate ctx->pollfds[i].events = 0;
8437c478bd9Sstevel@tonic-gate ctx->fdTable[i] = 0;
8447c478bd9Sstevel@tonic-gate }
8457c478bd9Sstevel@tonic-gate
846*9525b14bSRao Shoaib ctx->maxnfds = maxnfds;
8477c478bd9Sstevel@tonic-gate
848*9525b14bSRao Shoaib return (0);
8497c478bd9Sstevel@tonic-gate }
8507c478bd9Sstevel@tonic-gate
8517c478bd9Sstevel@tonic-gate /* Find the appropriate 'events' or 'revents' field in the pollfds array */
8527c478bd9Sstevel@tonic-gate short *
__fd_eventfield(int fd,__evEmulMask * maskp)8537c478bd9Sstevel@tonic-gate __fd_eventfield(int fd, __evEmulMask *maskp) {
8547c478bd9Sstevel@tonic-gate
8557c478bd9Sstevel@tonic-gate evContext_p *ctx = (evContext_p *)maskp->ctx;
8567c478bd9Sstevel@tonic-gate
8577c478bd9Sstevel@tonic-gate if (!maskp->result || maskp->type == EV_WASNONBLOCKING)
8587c478bd9Sstevel@tonic-gate return (&(ctx->pollfds[fd].events));
8597c478bd9Sstevel@tonic-gate else
8607c478bd9Sstevel@tonic-gate return (&(ctx->pollfds[fd].revents));
8617c478bd9Sstevel@tonic-gate }
8627c478bd9Sstevel@tonic-gate
8637c478bd9Sstevel@tonic-gate /* Translate to poll(2) event */
8647c478bd9Sstevel@tonic-gate short
__poll_event(__evEmulMask * maskp)8657c478bd9Sstevel@tonic-gate __poll_event(__evEmulMask *maskp) {
8667c478bd9Sstevel@tonic-gate
8677c478bd9Sstevel@tonic-gate switch ((maskp)->type) {
8687c478bd9Sstevel@tonic-gate case EV_READ:
8697c478bd9Sstevel@tonic-gate return (POLLRDNORM);
8707c478bd9Sstevel@tonic-gate case EV_WRITE:
8717c478bd9Sstevel@tonic-gate return (POLLWRNORM);
8727c478bd9Sstevel@tonic-gate case EV_EXCEPT:
8737c478bd9Sstevel@tonic-gate return (POLLRDBAND | POLLPRI | POLLWRBAND);
8747c478bd9Sstevel@tonic-gate case EV_WASNONBLOCKING:
8757c478bd9Sstevel@tonic-gate return (POLLHUP);
8767c478bd9Sstevel@tonic-gate default:
8777c478bd9Sstevel@tonic-gate return (0);
8787c478bd9Sstevel@tonic-gate }
8797c478bd9Sstevel@tonic-gate }
8807c478bd9Sstevel@tonic-gate
8817c478bd9Sstevel@tonic-gate /*
8827c478bd9Sstevel@tonic-gate * Clear the events corresponding to the specified mask. If this leaves
8837c478bd9Sstevel@tonic-gate * the events mask empty (apart from the POLLHUP bit), set the fd field
8847c478bd9Sstevel@tonic-gate * to -1 so that poll(2) will ignore this fd.
8857c478bd9Sstevel@tonic-gate */
8867c478bd9Sstevel@tonic-gate void
__fd_clr(int fd,__evEmulMask * maskp)8877c478bd9Sstevel@tonic-gate __fd_clr(int fd, __evEmulMask *maskp) {
8887c478bd9Sstevel@tonic-gate
8897c478bd9Sstevel@tonic-gate evContext_p *ctx = maskp->ctx;
8907c478bd9Sstevel@tonic-gate
8917c478bd9Sstevel@tonic-gate *__fd_eventfield(fd, maskp) &= ~__poll_event(maskp);
8927c478bd9Sstevel@tonic-gate if ((ctx->pollfds[fd].events & ~POLLHUP) == 0) {
8937c478bd9Sstevel@tonic-gate ctx->pollfds[fd].fd = -1;
894*9525b14bSRao Shoaib if (fd == ctx->fdMax)
895*9525b14bSRao Shoaib while (ctx->fdMax > ctx->firstfd &&
896*9525b14bSRao Shoaib ctx->pollfds[ctx->fdMax].fd < 0)
897*9525b14bSRao Shoaib ctx->fdMax--;
898*9525b14bSRao Shoaib if (fd == ctx->firstfd)
899*9525b14bSRao Shoaib while (ctx->firstfd <= ctx->fdMax &&
900*9525b14bSRao Shoaib ctx->pollfds[ctx->firstfd].fd < 0)
901*9525b14bSRao Shoaib ctx->firstfd++;
902*9525b14bSRao Shoaib /*
903*9525b14bSRao Shoaib * Do we have a empty set of descriptors?
904*9525b14bSRao Shoaib */
905*9525b14bSRao Shoaib if (ctx->firstfd > ctx->fdMax) {
906*9525b14bSRao Shoaib ctx->fdMax = -1;
907*9525b14bSRao Shoaib ctx->firstfd = 0;
908*9525b14bSRao Shoaib }
9097c478bd9Sstevel@tonic-gate }
9107c478bd9Sstevel@tonic-gate }
9117c478bd9Sstevel@tonic-gate
9127c478bd9Sstevel@tonic-gate /*
9137c478bd9Sstevel@tonic-gate * Set the events bit(s) corresponding to the specified mask. If the events
9147c478bd9Sstevel@tonic-gate * field has any other bits than POLLHUP set, also set the fd field so that
9157c478bd9Sstevel@tonic-gate * poll(2) will watch this fd.
9167c478bd9Sstevel@tonic-gate */
9177c478bd9Sstevel@tonic-gate void
__fd_set(int fd,__evEmulMask * maskp)9187c478bd9Sstevel@tonic-gate __fd_set(int fd, __evEmulMask *maskp) {
9197c478bd9Sstevel@tonic-gate
9207c478bd9Sstevel@tonic-gate evContext_p *ctx = maskp->ctx;
9217c478bd9Sstevel@tonic-gate
9227c478bd9Sstevel@tonic-gate *__fd_eventfield(fd, maskp) |= __poll_event(maskp);
9237c478bd9Sstevel@tonic-gate if ((ctx->pollfds[fd].events & ~POLLHUP) != 0) {
9247c478bd9Sstevel@tonic-gate ctx->pollfds[fd].fd = fd;
925*9525b14bSRao Shoaib if (fd < ctx->firstfd || ctx->fdMax == -1)
9267c478bd9Sstevel@tonic-gate ctx->firstfd = fd;
9277c478bd9Sstevel@tonic-gate if (fd > ctx->fdMax)
9287c478bd9Sstevel@tonic-gate ctx->fdMax = fd;
9297c478bd9Sstevel@tonic-gate }
9307c478bd9Sstevel@tonic-gate }
931*9525b14bSRao Shoaib #endif /* USE_POLL */
932*9525b14bSRao Shoaib
933*9525b14bSRao Shoaib /*! \file */
934