diff options
Diffstat (limited to 'contrib/bind9/lib/bind/isc/eventlib.c')
-rw-r--r-- | contrib/bind9/lib/bind/isc/eventlib.c | 933 |
1 files changed, 0 insertions, 933 deletions
diff --git a/contrib/bind9/lib/bind/isc/eventlib.c b/contrib/bind9/lib/bind/isc/eventlib.c deleted file mode 100644 index 20624d0..0000000 --- a/contrib/bind9/lib/bind/isc/eventlib.c +++ /dev/null @@ -1,933 +0,0 @@ -/* - * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") - * Copyright (c) 1995-1999 by Internet Software Consortium - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT - * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -/* eventlib.c - implement glue for the eventlib - * vix 09sep95 [initial] - */ - -#if !defined(LINT) && !defined(CODECENTER) -static const char rcsid[] = "$Id: eventlib.c,v 1.5.18.5 2006/03/10 00:20:08 marka Exp $"; -#endif - -#include "port_before.h" -#include "fd_setsize.h" - -#include <sys/types.h> -#include <sys/time.h> -#include <sys/stat.h> -#ifdef SOLARIS2 -#include <limits.h> -#endif /* SOLARIS2 */ - -#include <errno.h> -#include <signal.h> -#include <stdarg.h> -#include <stdlib.h> -#include <unistd.h> - -#include <isc/eventlib.h> -#include <isc/assertions.h> -#include "eventlib_p.h" - -#include "port_after.h" - -int __evOptMonoTime; - -#ifdef USE_POLL -#define pselect Pselect -#endif /* USE_POLL */ - -/* Forward. */ - -#if defined(NEED_PSELECT) || defined(USE_POLL) -static int pselect(int, void *, void *, void *, - struct timespec *, - const sigset_t *); -#endif - -int __evOptMonoTime; - -/* Public. */ - -int -evCreate(evContext *opaqueCtx) { - evContext_p *ctx; - - /* Make sure the memory heap is initialized. */ - if (meminit(0, 0) < 0 && errno != EEXIST) - return (-1); - - OKNEW(ctx); - - /* Global. */ - ctx->cur = NULL; - - /* Debugging. */ - ctx->debug = 0; - ctx->output = NULL; - - /* Connections. */ - ctx->conns = NULL; - INIT_LIST(ctx->accepts); - - /* Files. */ - ctx->files = NULL; -#ifdef USE_POLL - ctx->pollfds = NULL; - ctx->maxnfds = 0; - ctx->firstfd = 0; - emulMaskInit(ctx, rdLast, EV_READ, 1); - emulMaskInit(ctx, rdNext, EV_READ, 0); - emulMaskInit(ctx, wrLast, EV_WRITE, 1); - emulMaskInit(ctx, wrNext, EV_WRITE, 0); - emulMaskInit(ctx, exLast, EV_EXCEPT, 1); - emulMaskInit(ctx, exNext, EV_EXCEPT, 0); - emulMaskInit(ctx, nonblockBefore, EV_WASNONBLOCKING, 0); -#endif /* USE_POLL */ - FD_ZERO(&ctx->rdNext); - FD_ZERO(&ctx->wrNext); - FD_ZERO(&ctx->exNext); - FD_ZERO(&ctx->nonblockBefore); - ctx->fdMax = -1; - ctx->fdNext = NULL; - ctx->fdCount = 0; /*%< Invalidate {rd,wr,ex}Last. */ -#ifndef USE_POLL - ctx->highestFD = FD_SETSIZE - 1; - memset(ctx->fdTable, 0, sizeof ctx->fdTable); -#else - ctx->highestFD = INT_MAX / sizeof(struct pollfd); - ctx->fdTable = NULL; -#endif /* USE_POLL */ -#ifdef EVENTLIB_TIME_CHECKS - ctx->lastFdCount = 0; -#endif - - /* Streams. */ - ctx->streams = NULL; - ctx->strDone = NULL; - ctx->strLast = NULL; - - /* Timers. */ - ctx->lastEventTime = evNowTime(); -#ifdef EVENTLIB_TIME_CHECKS - ctx->lastSelectTime = ctx->lastEventTime; -#endif - ctx->timers = evCreateTimers(ctx); - if (ctx->timers == NULL) - return (-1); - - /* Waits. */ - ctx->waitLists = NULL; - ctx->waitDone.first = ctx->waitDone.last = NULL; - ctx->waitDone.prev = ctx->waitDone.next = NULL; - - opaqueCtx->opaque = ctx; - return (0); -} - -void -evSetDebug(evContext opaqueCtx, int level, FILE *output) { - evContext_p *ctx = opaqueCtx.opaque; - - ctx->debug = level; - ctx->output = output; -} - -int -evDestroy(evContext opaqueCtx) { - evContext_p *ctx = opaqueCtx.opaque; - int revs = 424242; /*%< Doug Adams. */ - evWaitList *this_wl, *next_wl; - evWait *this_wait, *next_wait; - - /* Connections. */ - while (revs-- > 0 && ctx->conns != NULL) { - evConnID id; - - id.opaque = ctx->conns; - (void) evCancelConn(opaqueCtx, id); - } - INSIST(revs >= 0); - - /* Streams. */ - while (revs-- > 0 && ctx->streams != NULL) { - evStreamID id; - - id.opaque = ctx->streams; - (void) evCancelRW(opaqueCtx, id); - } - - /* Files. */ - while (revs-- > 0 && ctx->files != NULL) { - evFileID id; - - id.opaque = ctx->files; - (void) evDeselectFD(opaqueCtx, id); - } - INSIST(revs >= 0); - - /* Timers. */ - evDestroyTimers(ctx); - - /* Waits. */ - for (this_wl = ctx->waitLists; - revs-- > 0 && this_wl != NULL; - this_wl = next_wl) { - next_wl = this_wl->next; - for (this_wait = this_wl->first; - revs-- > 0 && this_wait != NULL; - this_wait = next_wait) { - next_wait = this_wait->next; - FREE(this_wait); - } - FREE(this_wl); - } - for (this_wait = ctx->waitDone.first; - revs-- > 0 && this_wait != NULL; - this_wait = next_wait) { - next_wait = this_wait->next; - FREE(this_wait); - } - - FREE(ctx); - return (0); -} - -int -evGetNext(evContext opaqueCtx, evEvent *opaqueEv, int options) { - evContext_p *ctx = opaqueCtx.opaque; - struct timespec nextTime; - evTimer *nextTimer; - evEvent_p *new; - int x, pselect_errno, timerPast; -#ifdef EVENTLIB_TIME_CHECKS - struct timespec interval; -#endif - - /* Ensure that exactly one of EV_POLL or EV_WAIT was specified. */ - x = ((options & EV_POLL) != 0) + ((options & EV_WAIT) != 0); - if (x != 1) - EV_ERR(EINVAL); - - /* Get the time of day. We'll do this again after select() blocks. */ - ctx->lastEventTime = evNowTime(); - - again: - /* Finished accept()'s do not require a select(). */ - if (!EMPTY(ctx->accepts)) { - OKNEW(new); - new->type = Accept; - new->u.accept.this = HEAD(ctx->accepts); - UNLINK(ctx->accepts, HEAD(ctx->accepts), link); - opaqueEv->opaque = new; - return (0); - } - - /* Stream IO does not require a select(). */ - if (ctx->strDone != NULL) { - OKNEW(new); - new->type = Stream; - new->u.stream.this = ctx->strDone; - ctx->strDone = ctx->strDone->nextDone; - if (ctx->strDone == NULL) - ctx->strLast = NULL; - opaqueEv->opaque = new; - return (0); - } - - /* Waits do not require a select(). */ - if (ctx->waitDone.first != NULL) { - OKNEW(new); - new->type = Wait; - new->u.wait.this = ctx->waitDone.first; - ctx->waitDone.first = ctx->waitDone.first->next; - if (ctx->waitDone.first == NULL) - ctx->waitDone.last = NULL; - opaqueEv->opaque = new; - return (0); - } - - /* Get the status and content of the next timer. */ - if ((nextTimer = heap_element(ctx->timers, 1)) != NULL) { - nextTime = nextTimer->due; - timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0); - } else - timerPast = 0; /*%< Make gcc happy. */ - evPrintf(ctx, 9, "evGetNext: fdCount %d\n", ctx->fdCount); - if (ctx->fdCount == 0) { - static const struct timespec NoTime = {0, 0L}; - enum { JustPoll, Block, Timer } m; - struct timespec t, *tp; - - /* Are there any events at all? */ - if ((options & EV_WAIT) != 0 && !nextTimer && ctx->fdMax == -1) - EV_ERR(ENOENT); - - /* Figure out what select()'s timeout parameter should be. */ - if ((options & EV_POLL) != 0) { - m = JustPoll; - t = NoTime; - tp = &t; - } else if (nextTimer == NULL) { - m = Block; - /* ``t'' unused. */ - tp = NULL; - } else if (timerPast) { - m = JustPoll; - t = NoTime; - tp = &t; - } else { - m = Timer; - /* ``t'' filled in later. */ - tp = &t; - } -#ifdef EVENTLIB_TIME_CHECKS - if (ctx->debug > 0) { - interval = evSubTime(ctx->lastEventTime, - ctx->lastSelectTime); - if (interval.tv_sec > 0 || interval.tv_nsec > 0) - evPrintf(ctx, 1, - "time between pselect() %u.%09u count %d\n", - interval.tv_sec, interval.tv_nsec, - ctx->lastFdCount); - } -#endif - do { -#ifndef USE_POLL - /* XXX need to copy only the bits we are using. */ - ctx->rdLast = ctx->rdNext; - ctx->wrLast = ctx->wrNext; - ctx->exLast = ctx->exNext; -#else - /* - * The pollfd structure uses separate fields for - * the input and output events (corresponding to - * the ??Next and ??Last fd sets), so there's no - * need to copy one to the other. - */ -#endif /* USE_POLL */ - if (m == Timer) { - INSIST(tp == &t); - t = evSubTime(nextTime, ctx->lastEventTime); - } - - /* XXX should predict system's earliness and adjust. */ - x = pselect(ctx->fdMax+1, - &ctx->rdLast, &ctx->wrLast, &ctx->exLast, - tp, NULL); - pselect_errno = errno; - -#ifndef USE_POLL - evPrintf(ctx, 4, "select() returns %d (err: %s)\n", - x, (x == -1) ? strerror(errno) : "none"); -#else - evPrintf(ctx, 4, "poll() returns %d (err: %s)\n", - x, (x == -1) ? strerror(errno) : "none"); -#endif /* USE_POLL */ - /* Anything but a poll can change the time. */ - if (m != JustPoll) - ctx->lastEventTime = evNowTime(); - - /* Select() likes to finish about 10ms early. */ - } while (x == 0 && m == Timer && - evCmpTime(ctx->lastEventTime, nextTime) < 0); -#ifdef EVENTLIB_TIME_CHECKS - ctx->lastSelectTime = ctx->lastEventTime; -#endif - if (x < 0) { - if (pselect_errno == EINTR) { - if ((options & EV_NULL) != 0) - goto again; - OKNEW(new); - new->type = Null; - /* No data. */ - opaqueEv->opaque = new; - return (0); - } - if (pselect_errno == EBADF) { - for (x = 0; x <= ctx->fdMax; x++) { - struct stat sb; - - if (FD_ISSET(x, &ctx->rdNext) == 0 && - FD_ISSET(x, &ctx->wrNext) == 0 && - FD_ISSET(x, &ctx->exNext) == 0) - continue; - if (fstat(x, &sb) == -1 && - errno == EBADF) - evPrintf(ctx, 1, "EBADF: %d\n", - x); - } - abort(); - } - EV_ERR(pselect_errno); - } - if (x == 0 && (nextTimer == NULL || !timerPast) && - (options & EV_POLL)) - EV_ERR(EWOULDBLOCK); - ctx->fdCount = x; -#ifdef EVENTLIB_TIME_CHECKS - ctx->lastFdCount = x; -#endif - } - INSIST(nextTimer || ctx->fdCount); - - /* Timers go first since we'd like them to be accurate. */ - if (nextTimer && !timerPast) { - /* Has anything happened since we blocked? */ - timerPast = (evCmpTime(nextTime, ctx->lastEventTime) <= 0); - } - if (nextTimer && timerPast) { - OKNEW(new); - new->type = Timer; - new->u.timer.this = nextTimer; - opaqueEv->opaque = new; - return (0); - } - - /* No timers, so there should be a ready file descriptor. */ - x = 0; - while (ctx->fdCount > 0) { - evFile *fid; - int fd, eventmask; - - if (ctx->fdNext == NULL) { - if (++x == 2) { - /* - * Hitting the end twice means that the last - * select() found some FD's which have since - * been deselected. - * - * On some systems, the count returned by - * selects is the total number of bits in - * all masks that are set, and on others it's - * the number of fd's that have some bit set, - * and on others, it's just broken. We - * always assume that it's the number of - * bits set in all masks, because that's what - * the man page says it should do, and - * the worst that can happen is we do an - * extra select(). - */ - ctx->fdCount = 0; - break; - } - ctx->fdNext = ctx->files; - } - fid = ctx->fdNext; - ctx->fdNext = fid->next; - - fd = fid->fd; - eventmask = 0; - if (FD_ISSET(fd, &ctx->rdLast)) - eventmask |= EV_READ; - if (FD_ISSET(fd, &ctx->wrLast)) - eventmask |= EV_WRITE; - if (FD_ISSET(fd, &ctx->exLast)) - eventmask |= EV_EXCEPT; - eventmask &= fid->eventmask; - if (eventmask != 0) { - if ((eventmask & EV_READ) != 0) { - FD_CLR(fd, &ctx->rdLast); - ctx->fdCount--; - } - if ((eventmask & EV_WRITE) != 0) { - FD_CLR(fd, &ctx->wrLast); - ctx->fdCount--; - } - if ((eventmask & EV_EXCEPT) != 0) { - FD_CLR(fd, &ctx->exLast); - ctx->fdCount--; - } - OKNEW(new); - new->type = File; - new->u.file.this = fid; - new->u.file.eventmask = eventmask; - opaqueEv->opaque = new; - return (0); - } - } - if (ctx->fdCount < 0) { - /* - * select()'s count is off on a number of systems, and - * can result in fdCount < 0. - */ - evPrintf(ctx, 4, "fdCount < 0 (%d)\n", ctx->fdCount); - ctx->fdCount = 0; - } - - /* We get here if the caller deselect()'s an FD. Gag me with a goto. */ - goto again; -} - -int -evDispatch(evContext opaqueCtx, evEvent opaqueEv) { - evContext_p *ctx = opaqueCtx.opaque; - evEvent_p *ev = opaqueEv.opaque; -#ifdef EVENTLIB_TIME_CHECKS - void *func; - struct timespec start_time; - struct timespec interval; -#endif - -#ifdef EVENTLIB_TIME_CHECKS - if (ctx->debug > 0) - start_time = evNowTime(); -#endif - ctx->cur = ev; - switch (ev->type) { - case Accept: { - evAccept *this = ev->u.accept.this; - - evPrintf(ctx, 5, - "Dispatch.Accept: fd %d -> %d, func %p, uap %p\n", - this->conn->fd, this->fd, - this->conn->func, this->conn->uap); - errno = this->ioErrno; - (this->conn->func)(opaqueCtx, this->conn->uap, this->fd, - &this->la, this->lalen, - &this->ra, this->ralen); -#ifdef EVENTLIB_TIME_CHECKS - func = this->conn->func; -#endif - break; - } - case File: { - evFile *this = ev->u.file.this; - int eventmask = ev->u.file.eventmask; - - evPrintf(ctx, 5, - "Dispatch.File: fd %d, mask 0x%x, func %p, uap %p\n", - this->fd, this->eventmask, this->func, this->uap); - (this->func)(opaqueCtx, this->uap, this->fd, eventmask); -#ifdef EVENTLIB_TIME_CHECKS - func = this->func; -#endif - break; - } - case Stream: { - evStream *this = ev->u.stream.this; - - evPrintf(ctx, 5, - "Dispatch.Stream: fd %d, func %p, uap %p\n", - this->fd, this->func, this->uap); - errno = this->ioErrno; - (this->func)(opaqueCtx, this->uap, this->fd, this->ioDone); -#ifdef EVENTLIB_TIME_CHECKS - func = this->func; -#endif - break; - } - case Timer: { - evTimer *this = ev->u.timer.this; - - evPrintf(ctx, 5, "Dispatch.Timer: func %p, uap %p\n", - this->func, this->uap); - (this->func)(opaqueCtx, this->uap, this->due, this->inter); -#ifdef EVENTLIB_TIME_CHECKS - func = this->func; -#endif - break; - } - case Wait: { - evWait *this = ev->u.wait.this; - - evPrintf(ctx, 5, - "Dispatch.Wait: tag %p, func %p, uap %p\n", - this->tag, this->func, this->uap); - (this->func)(opaqueCtx, this->uap, this->tag); -#ifdef EVENTLIB_TIME_CHECKS - func = this->func; -#endif - break; - } - case Null: { - /* No work. */ -#ifdef EVENTLIB_TIME_CHECKS - func = NULL; -#endif - break; - } - default: { - abort(); - } - } -#ifdef EVENTLIB_TIME_CHECKS - if (ctx->debug > 0) { - interval = evSubTime(evNowTime(), start_time); - /* - * Complain if it took longer than 50 milliseconds. - * - * We call getuid() to make an easy to find mark in a kernel - * trace. - */ - if (interval.tv_sec > 0 || interval.tv_nsec > 50000000) - evPrintf(ctx, 1, - "dispatch interval %u.%09u uid %d type %d func %p\n", - interval.tv_sec, interval.tv_nsec, - getuid(), ev->type, func); - } -#endif - ctx->cur = NULL; - evDrop(opaqueCtx, opaqueEv); - return (0); -} - -void -evDrop(evContext opaqueCtx, evEvent opaqueEv) { - evContext_p *ctx = opaqueCtx.opaque; - evEvent_p *ev = opaqueEv.opaque; - - switch (ev->type) { - case Accept: { - FREE(ev->u.accept.this); - break; - } - case File: { - /* No work. */ - break; - } - case Stream: { - evStreamID id; - - id.opaque = ev->u.stream.this; - (void) evCancelRW(opaqueCtx, id); - break; - } - case Timer: { - evTimer *this = ev->u.timer.this; - evTimerID opaque; - - /* Check to see whether the user func cleared the timer. */ - if (heap_element(ctx->timers, this->index) != this) { - evPrintf(ctx, 5, "Dispatch.Timer: timer rm'd?\n"); - break; - } - /* - * Timer is still there. Delete it if it has expired, - * otherwise set it according to its next interval. - */ - if (this->inter.tv_sec == (time_t)0 && - this->inter.tv_nsec == 0L) { - opaque.opaque = this; - (void) evClearTimer(opaqueCtx, opaque); - } else { - opaque.opaque = this; - (void) evResetTimer(opaqueCtx, opaque, this->func, - this->uap, - evAddTime((this->mode & EV_TMR_RATE) ? - this->due : - ctx->lastEventTime, - this->inter), - this->inter); - } - break; - } - case Wait: { - FREE(ev->u.wait.this); - break; - } - case Null: { - /* No work. */ - break; - } - default: { - abort(); - } - } - FREE(ev); -} - -int -evMainLoop(evContext opaqueCtx) { - evEvent event; - int x; - - while ((x = evGetNext(opaqueCtx, &event, EV_WAIT)) == 0) - if ((x = evDispatch(opaqueCtx, event)) < 0) - break; - return (x); -} - -int -evHighestFD(evContext opaqueCtx) { - evContext_p *ctx = opaqueCtx.opaque; - - return (ctx->highestFD); -} - -void -evPrintf(const evContext_p *ctx, int level, const char *fmt, ...) { - va_list ap; - - va_start(ap, fmt); - if (ctx->output != NULL && ctx->debug >= level) { - vfprintf(ctx->output, fmt, ap); - fflush(ctx->output); - } - va_end(ap); -} - -int -evSetOption(evContext *opaqueCtx, const char *option, int value) { - /* evContext_p *ctx = opaqueCtx->opaque; */ - - UNUSED(opaqueCtx); - UNUSED(value); -#ifndef CLOCK_MONOTONIC - UNUSED(option); -#endif - -#ifdef CLOCK_MONOTONIC - if (strcmp(option, "monotime") == 0) { - if (opaqueCtx != NULL) - errno = EINVAL; - if (value == 0 || value == 1) { - __evOptMonoTime = value; - return (0); - } else { - errno = EINVAL; - return (-1); - } - } -#endif - errno = ENOENT; - return (-1); -} - -int -evGetOption(evContext *opaqueCtx, const char *option, int *value) { - /* evContext_p *ctx = opaqueCtx->opaque; */ - - UNUSED(opaqueCtx); -#ifndef CLOCK_MONOTONIC - UNUSED(value); - UNUSED(option); -#endif - -#ifdef CLOCK_MONOTONIC - if (strcmp(option, "monotime") == 0) { - if (opaqueCtx != NULL) - errno = EINVAL; - *value = __evOptMonoTime; - return (0); - } -#endif - errno = ENOENT; - return (-1); -} - -#if defined(NEED_PSELECT) || defined(USE_POLL) -/* XXX needs to move to the porting library. */ -static int -pselect(int nfds, void *rfds, void *wfds, void *efds, - struct timespec *tsp, - const sigset_t *sigmask) -{ - struct timeval tv, *tvp; - sigset_t sigs; - int n; -#ifdef USE_POLL - int polltimeout = INFTIM; - evContext_p *ctx; - struct pollfd *fds; - nfds_t pnfds; - - UNUSED(nfds); -#endif /* USE_POLL */ - - if (tsp) { - tvp = &tv; - tv = evTimeVal(*tsp); -#ifdef USE_POLL - polltimeout = 1000 * tv.tv_sec + tv.tv_usec / 1000; -#endif /* USE_POLL */ - } else - tvp = NULL; - if (sigmask) - sigprocmask(SIG_SETMASK, sigmask, &sigs); -#ifndef USE_POLL - n = select(nfds, rfds, wfds, efds, tvp); -#else - /* - * rfds, wfds, and efds should all be from the same evContext_p, - * so any of them will do. If they're all NULL, the caller is - * presumably calling us to block. - */ - if (rfds != NULL) - ctx = ((__evEmulMask *)rfds)->ctx; - else if (wfds != NULL) - ctx = ((__evEmulMask *)wfds)->ctx; - else if (efds != NULL) - ctx = ((__evEmulMask *)efds)->ctx; - else - ctx = NULL; - if (ctx != NULL && ctx->fdMax != -1) { - fds = &(ctx->pollfds[ctx->firstfd]); - pnfds = ctx->fdMax - ctx->firstfd + 1; - } else { - fds = NULL; - pnfds = 0; - } - n = poll(fds, pnfds, polltimeout); - if (n > 0) { - int i, e; - - INSIST(ctx != NULL); - for (e = 0, i = ctx->firstfd; i <= ctx->fdMax; i++) { - if (ctx->pollfds[i].fd < 0) - continue; - if (FD_ISSET(i, &ctx->rdLast)) - e++; - if (FD_ISSET(i, &ctx->wrLast)) - e++; - if (FD_ISSET(i, &ctx->exLast)) - e++; - } - n = e; - } -#endif /* USE_POLL */ - if (sigmask) - sigprocmask(SIG_SETMASK, &sigs, NULL); - if (tsp) - *tsp = evTimeSpec(tv); - return (n); -} -#endif - -#ifdef USE_POLL -int -evPollfdRealloc(evContext_p *ctx, int pollfd_chunk_size, int fd) { - - int i, maxnfds; - void *pollfds, *fdTable; - - if (fd < ctx->maxnfds) - return (0); - - /* Don't allow ridiculously small values for pollfd_chunk_size */ - if (pollfd_chunk_size < 20) - pollfd_chunk_size = 20; - - maxnfds = (1 + (fd/pollfd_chunk_size)) * pollfd_chunk_size; - - pollfds = realloc(ctx->pollfds, maxnfds * sizeof(*ctx->pollfds)); - if (pollfds != NULL) - ctx->pollfds = pollfds; - fdTable = realloc(ctx->fdTable, maxnfds * sizeof(*ctx->fdTable)); - if (fdTable != NULL) - ctx->fdTable = fdTable; - - if (pollfds == NULL || fdTable == NULL) { - evPrintf(ctx, 2, "pollfd() realloc (%ld) failed\n", - (long)maxnfds*sizeof(struct pollfd)); - return (-1); - } - - for (i = ctx->maxnfds; i < maxnfds; i++) { - ctx->pollfds[i].fd = -1; - ctx->pollfds[i].events = 0; - ctx->fdTable[i] = 0; - } - - ctx->maxnfds = maxnfds; - - return (0); -} - -/* Find the appropriate 'events' or 'revents' field in the pollfds array */ -short * -__fd_eventfield(int fd, __evEmulMask *maskp) { - - evContext_p *ctx = (evContext_p *)maskp->ctx; - - if (!maskp->result || maskp->type == EV_WASNONBLOCKING) - return (&(ctx->pollfds[fd].events)); - else - return (&(ctx->pollfds[fd].revents)); -} - -/* Translate to poll(2) event */ -short -__poll_event(__evEmulMask *maskp) { - - switch ((maskp)->type) { - case EV_READ: - return (POLLRDNORM); - case EV_WRITE: - return (POLLWRNORM); - case EV_EXCEPT: - return (POLLRDBAND | POLLPRI | POLLWRBAND); - case EV_WASNONBLOCKING: - return (POLLHUP); - default: - return (0); - } -} - -/* - * Clear the events corresponding to the specified mask. If this leaves - * the events mask empty (apart from the POLLHUP bit), set the fd field - * to -1 so that poll(2) will ignore this fd. - */ -void -__fd_clr(int fd, __evEmulMask *maskp) { - - evContext_p *ctx = maskp->ctx; - - *__fd_eventfield(fd, maskp) &= ~__poll_event(maskp); - if ((ctx->pollfds[fd].events & ~POLLHUP) == 0) { - ctx->pollfds[fd].fd = -1; - if (fd == ctx->fdMax) - while (ctx->fdMax > ctx->firstfd && - ctx->pollfds[ctx->fdMax].fd < 0) - ctx->fdMax--; - if (fd == ctx->firstfd) - while (ctx->firstfd <= ctx->fdMax && - ctx->pollfds[ctx->firstfd].fd < 0) - ctx->firstfd++; - /* - * Do we have a empty set of descriptors? - */ - if (ctx->firstfd > ctx->fdMax) { - ctx->fdMax = -1; - ctx->firstfd = 0; - } - } -} - -/* - * Set the events bit(s) corresponding to the specified mask. If the events - * field has any other bits than POLLHUP set, also set the fd field so that - * poll(2) will watch this fd. - */ -void -__fd_set(int fd, __evEmulMask *maskp) { - - evContext_p *ctx = maskp->ctx; - - *__fd_eventfield(fd, maskp) |= __poll_event(maskp); - if ((ctx->pollfds[fd].events & ~POLLHUP) != 0) { - ctx->pollfds[fd].fd = fd; - if (fd < ctx->firstfd || ctx->fdMax == -1) - ctx->firstfd = fd; - if (fd > ctx->fdMax) - ctx->fdMax = fd; - } -} -#endif /* USE_POLL */ - -/*! \file */ |