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