Annotation of embedaddon/thttpd/fdwatch.c, revision 1.1
1.1 ! misho 1: /* fdwatch.c - fd watcher routines, either select() or poll()
! 2: **
! 3: ** Copyright © 1999,2000 by Jef Poskanzer <jef@mail.acme.com>.
! 4: ** All rights reserved.
! 5: **
! 6: ** Redistribution and use in source and binary forms, with or without
! 7: ** modification, are permitted provided that the following conditions
! 8: ** are met:
! 9: ** 1. Redistributions of source code must retain the above copyright
! 10: ** notice, this list of conditions and the following disclaimer.
! 11: ** 2. Redistributions in binary form must reproduce the above copyright
! 12: ** notice, this list of conditions and the following disclaimer in the
! 13: ** documentation and/or other materials provided with the distribution.
! 14: **
! 15: ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
! 16: ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
! 17: ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
! 18: ** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
! 19: ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
! 20: ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
! 21: ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
! 22: ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
! 23: ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
! 24: ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
! 25: ** SUCH DAMAGE.
! 26: */
! 27:
! 28: #include <sys/types.h>
! 29: #include <stdlib.h>
! 30: #include <unistd.h>
! 31: #include <string.h>
! 32: #include <sys/time.h>
! 33: #include <sys/resource.h>
! 34: #include <syslog.h>
! 35: #include <fcntl.h>
! 36:
! 37: #ifndef MIN
! 38: #define MIN(a,b) ((a) < (b) ? (a) : (b))
! 39: #endif
! 40:
! 41: #ifdef HAVE_POLL_H
! 42: #include <poll.h>
! 43: #else /* HAVE_POLL_H */
! 44: #ifdef HAVE_SYS_POLL_H
! 45: #include <sys/poll.h>
! 46: #endif /* HAVE_SYS_POLL_H */
! 47: #endif /* HAVE_POLL_H */
! 48:
! 49: #ifdef HAVE_SYS_DEVPOLL_H
! 50: #include <sys/devpoll.h>
! 51: #ifndef HAVE_DEVPOLL
! 52: #define HAVE_DEVPOLL
! 53: #endif /* !HAVE_DEVPOLL */
! 54: #endif /* HAVE_SYS_DEVPOLL_H */
! 55:
! 56: #ifdef HAVE_SYS_EVENT_H
! 57: #include <sys/event.h>
! 58: #endif /* HAVE_SYS_EVENT_H */
! 59:
! 60: #include "fdwatch.h"
! 61:
! 62: #ifdef HAVE_SELECT
! 63: #ifndef FD_SET
! 64: #define NFDBITS 32
! 65: #define FD_SETSIZE 32
! 66: #define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
! 67: #define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
! 68: #define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
! 69: #define FD_ZERO(p) bzero((char*)(p), sizeof(*(p)))
! 70: #endif /* !FD_SET */
! 71: #endif /* HAVE_SELECT */
! 72:
! 73: static int nfiles;
! 74: static long nwatches;
! 75: static int* fd_rw;
! 76: static void** fd_data;
! 77: static int nreturned, next_ridx;
! 78:
! 79: #ifdef HAVE_KQUEUE
! 80:
! 81: #define WHICH "kevent"
! 82: #define INIT( nfiles ) kqueue_init( nfiles )
! 83: #define ADD_FD( fd, rw ) kqueue_add_fd( fd, rw )
! 84: #define DEL_FD( fd ) kqueue_del_fd( fd )
! 85: #define WATCH( timeout_msecs ) kqueue_watch( timeout_msecs )
! 86: #define CHECK_FD( fd ) kqueue_check_fd( fd )
! 87: #define GET_FD( ridx ) kqueue_get_fd( ridx )
! 88:
! 89: static int kqueue_init( int nfiles );
! 90: static void kqueue_add_fd( int fd, int rw );
! 91: static void kqueue_del_fd( int fd );
! 92: static int kqueue_watch( long timeout_msecs );
! 93: static int kqueue_check_fd( int fd );
! 94: static int kqueue_get_fd( int ridx );
! 95:
! 96: #else /* HAVE_KQUEUE */
! 97: # ifdef HAVE_DEVPOLL
! 98:
! 99: #define WHICH "devpoll"
! 100: #define INIT( nfiles ) devpoll_init( nfiles )
! 101: #define ADD_FD( fd, rw ) devpoll_add_fd( fd, rw )
! 102: #define DEL_FD( fd ) devpoll_del_fd( fd )
! 103: #define WATCH( timeout_msecs ) devpoll_watch( timeout_msecs )
! 104: #define CHECK_FD( fd ) devpoll_check_fd( fd )
! 105: #define GET_FD( ridx ) devpoll_get_fd( ridx )
! 106:
! 107: static int devpoll_init( int nfiles );
! 108: static void devpoll_add_fd( int fd, int rw );
! 109: static void devpoll_del_fd( int fd );
! 110: static int devpoll_watch( long timeout_msecs );
! 111: static int devpoll_check_fd( int fd );
! 112: static int devpoll_get_fd( int ridx );
! 113:
! 114: # else /* HAVE_DEVPOLL */
! 115: # ifdef HAVE_POLL
! 116:
! 117: #define WHICH "poll"
! 118: #define INIT( nfiles ) poll_init( nfiles )
! 119: #define ADD_FD( fd, rw ) poll_add_fd( fd, rw )
! 120: #define DEL_FD( fd ) poll_del_fd( fd )
! 121: #define WATCH( timeout_msecs ) poll_watch( timeout_msecs )
! 122: #define CHECK_FD( fd ) poll_check_fd( fd )
! 123: #define GET_FD( ridx ) poll_get_fd( ridx )
! 124:
! 125: static int poll_init( int nfiles );
! 126: static void poll_add_fd( int fd, int rw );
! 127: static void poll_del_fd( int fd );
! 128: static int poll_watch( long timeout_msecs );
! 129: static int poll_check_fd( int fd );
! 130: static int poll_get_fd( int ridx );
! 131:
! 132: # else /* HAVE_POLL */
! 133: # ifdef HAVE_SELECT
! 134:
! 135: #define WHICH "select"
! 136: #define INIT( nfiles ) select_init( nfiles )
! 137: #define ADD_FD( fd, rw ) select_add_fd( fd, rw )
! 138: #define DEL_FD( fd ) select_del_fd( fd )
! 139: #define WATCH( timeout_msecs ) select_watch( timeout_msecs )
! 140: #define CHECK_FD( fd ) select_check_fd( fd )
! 141: #define GET_FD( ridx ) select_get_fd( ridx )
! 142:
! 143: static int select_init( int nfiles );
! 144: static void select_add_fd( int fd, int rw );
! 145: static void select_del_fd( int fd );
! 146: static int select_watch( long timeout_msecs );
! 147: static int select_check_fd( int fd );
! 148: static int select_get_fd( int ridx );
! 149:
! 150: # endif /* HAVE_SELECT */
! 151: # endif /* HAVE_POLL */
! 152: # endif /* HAVE_DEVPOLL */
! 153: #endif /* HAVE_KQUEUE */
! 154:
! 155:
! 156: /* Routines. */
! 157:
! 158: /* Figure out how many file descriptors the system allows, and
! 159: ** initialize the fdwatch data structures. Returns -1 on failure.
! 160: */
! 161: int
! 162: fdwatch_get_nfiles( void )
! 163: {
! 164: int i;
! 165: #ifdef RLIMIT_NOFILE
! 166: struct rlimit rl;
! 167: #endif /* RLIMIT_NOFILE */
! 168:
! 169: /* Figure out how many fd's we can have. */
! 170: nfiles = getdtablesize();
! 171: #ifdef RLIMIT_NOFILE
! 172: /* If we have getrlimit(), use that, and attempt to raise the limit. */
! 173: if ( getrlimit( RLIMIT_NOFILE, &rl ) == 0 )
! 174: {
! 175: nfiles = rl.rlim_cur;
! 176: if ( rl.rlim_max == RLIM_INFINITY )
! 177: rl.rlim_cur = 8192; /* arbitrary */
! 178: else if ( rl.rlim_max > rl.rlim_cur )
! 179: rl.rlim_cur = rl.rlim_max;
! 180: if ( setrlimit( RLIMIT_NOFILE, &rl ) == 0 )
! 181: nfiles = rl.rlim_cur;
! 182: }
! 183: #endif /* RLIMIT_NOFILE */
! 184:
! 185: #if defined(HAVE_SELECT) && ! ( defined(HAVE_POLL) || defined(HAVE_DEVPOLL) || defined(HAVE_KQUEUE) )
! 186: /* If we use select(), then we must limit ourselves to FD_SETSIZE. */
! 187: nfiles = MIN( nfiles, FD_SETSIZE );
! 188: #endif /* HAVE_SELECT && ! ( HAVE_POLL || HAVE_DEVPOLL || HAVE_KQUEUE ) */
! 189:
! 190: /* Initialize the fdwatch data structures. */
! 191: nwatches = 0;
! 192: fd_rw = (int*) malloc( sizeof(int) * nfiles );
! 193: fd_data = (void**) malloc( sizeof(void*) * nfiles );
! 194: if ( fd_rw == (int*) 0 || fd_data == (void**) 0 )
! 195: return -1;
! 196: for ( i = 0; i < nfiles; ++i )
! 197: fd_rw[i] = -1;
! 198: if ( INIT( nfiles ) == -1 )
! 199: return -1;
! 200:
! 201: return nfiles;
! 202: }
! 203:
! 204:
! 205: /* Add a descriptor to the watch list. rw is either FDW_READ or FDW_WRITE. */
! 206: void
! 207: fdwatch_add_fd( int fd, void* client_data, int rw )
! 208: {
! 209: if ( fd < 0 || fd >= nfiles || fd_rw[fd] != -1 )
! 210: {
! 211: syslog( LOG_ERR, "bad fd (%d) passed to fdwatch_add_fd!", fd );
! 212: return;
! 213: }
! 214: ADD_FD( fd, rw );
! 215: fd_rw[fd] = rw;
! 216: fd_data[fd] = client_data;
! 217: }
! 218:
! 219:
! 220: /* Remove a descriptor from the watch list. */
! 221: void
! 222: fdwatch_del_fd( int fd )
! 223: {
! 224: if ( fd < 0 || fd >= nfiles || fd_rw[fd] == -1 )
! 225: {
! 226: syslog( LOG_ERR, "bad fd (%d) passed to fdwatch_del_fd!", fd );
! 227: return;
! 228: }
! 229: DEL_FD( fd );
! 230: fd_rw[fd] = -1;
! 231: fd_data[fd] = (void*) 0;
! 232: }
! 233:
! 234: /* Do the watch. Return value is the number of descriptors that are ready,
! 235: ** or 0 if the timeout expired, or -1 on errors. A timeout of INFTIM means
! 236: ** wait indefinitely.
! 237: */
! 238: int
! 239: fdwatch( long timeout_msecs )
! 240: {
! 241: ++nwatches;
! 242: nreturned = WATCH( timeout_msecs );
! 243: next_ridx = 0;
! 244: return nreturned;
! 245: }
! 246:
! 247:
! 248: /* Check if a descriptor was ready. */
! 249: int
! 250: fdwatch_check_fd( int fd )
! 251: {
! 252: if ( fd < 0 || fd >= nfiles || fd_rw[fd] == -1 )
! 253: {
! 254: syslog( LOG_ERR, "bad fd (%d) passed to fdwatch_check_fd!", fd );
! 255: return 0;
! 256: }
! 257: return CHECK_FD( fd );
! 258: }
! 259:
! 260:
! 261: void*
! 262: fdwatch_get_next_client_data( void )
! 263: {
! 264: int fd;
! 265:
! 266: if ( next_ridx >= nreturned )
! 267: return (void*) -1;
! 268: fd = GET_FD( next_ridx++ );
! 269: if ( fd < 0 || fd >= nfiles )
! 270: return (void*) 0;
! 271: return fd_data[fd];
! 272: }
! 273:
! 274:
! 275: /* Generate debugging statistics syslog message. */
! 276: void
! 277: fdwatch_logstats( long secs )
! 278: {
! 279: if ( secs > 0 )
! 280: syslog(
! 281: LOG_INFO, " fdwatch - %ld %ss (%g/sec)",
! 282: nwatches, WHICH, (float) nwatches / secs );
! 283: nwatches = 0;
! 284: }
! 285:
! 286:
! 287: #ifdef HAVE_KQUEUE
! 288:
! 289: static int maxkqevents;
! 290: static struct kevent* kqevents;
! 291: static int nkqevents;
! 292: static struct kevent* kqrevents;
! 293: static int* kqrfdidx;
! 294: static int kq;
! 295:
! 296:
! 297: static int
! 298: kqueue_init( int nfiles )
! 299: {
! 300: kq = kqueue();
! 301: if ( kq == -1 )
! 302: return -1;
! 303: maxkqevents = nfiles * 2;
! 304: kqevents = (struct kevent*) malloc( sizeof(struct kevent) * maxkqevents );
! 305: kqrevents = (struct kevent*) malloc( sizeof(struct kevent) * nfiles );
! 306: kqrfdidx = (int*) malloc( sizeof(int) * nfiles );
! 307: if ( kqevents == (struct kevent*) 0 || kqrevents == (struct kevent*) 0 ||
! 308: kqrfdidx == (int*) 0 )
! 309: return -1;
! 310: (void) memset( kqevents, 0, sizeof(struct kevent) * maxkqevents );
! 311: (void) memset( kqrfdidx, 0, sizeof(int) * nfiles );
! 312: return 0;
! 313: }
! 314:
! 315:
! 316: static void
! 317: kqueue_add_fd( int fd, int rw )
! 318: {
! 319: if ( nkqevents >= maxkqevents )
! 320: {
! 321: syslog( LOG_ERR, "too many kqevents in kqueue_add_fd!" );
! 322: return;
! 323: }
! 324: kqevents[nkqevents].ident = fd;
! 325: kqevents[nkqevents].flags = EV_ADD;
! 326: switch ( rw )
! 327: {
! 328: case FDW_READ: kqevents[nkqevents].filter = EVFILT_READ; break;
! 329: case FDW_WRITE: kqevents[nkqevents].filter = EVFILT_WRITE; break;
! 330: default: break;
! 331: }
! 332: ++nkqevents;
! 333: }
! 334:
! 335:
! 336: static void
! 337: kqueue_del_fd( int fd )
! 338: {
! 339: if ( nkqevents >= maxkqevents )
! 340: {
! 341: syslog( LOG_ERR, "too many kqevents in kqueue_del_fd!" );
! 342: return;
! 343: }
! 344: kqevents[nkqevents].ident = fd;
! 345: kqevents[nkqevents].flags = EV_DELETE;
! 346: switch ( fd_rw[fd] )
! 347: {
! 348: case FDW_READ: kqevents[nkqevents].filter = EVFILT_READ; break;
! 349: case FDW_WRITE: kqevents[nkqevents].filter = EVFILT_WRITE; break;
! 350: }
! 351: ++nkqevents;
! 352: }
! 353:
! 354:
! 355: static int
! 356: kqueue_watch( long timeout_msecs )
! 357: {
! 358: int i, r;
! 359:
! 360: if ( timeout_msecs == INFTIM )
! 361: r = kevent(
! 362: kq, kqevents, nkqevents, kqrevents, nfiles, (struct timespec*) 0 );
! 363: else
! 364: {
! 365: struct timespec ts;
! 366: ts.tv_sec = timeout_msecs / 1000L;
! 367: ts.tv_nsec = ( timeout_msecs % 1000L ) * 1000000L;
! 368: r = kevent( kq, kqevents, nkqevents, kqrevents, nfiles, &ts );
! 369: }
! 370: nkqevents = 0;
! 371: if ( r == -1 )
! 372: return -1;
! 373:
! 374: for ( i = 0; i < r; ++i )
! 375: kqrfdidx[kqrevents[i].ident] = i;
! 376:
! 377: return r;
! 378: }
! 379:
! 380:
! 381: static int
! 382: kqueue_check_fd( int fd )
! 383: {
! 384: int ridx = kqrfdidx[fd];
! 385:
! 386: if ( ridx < 0 || ridx >= nfiles )
! 387: {
! 388: syslog( LOG_ERR, "bad ridx (%d) in kqueue_check_fd!", ridx );
! 389: return 0;
! 390: }
! 391: if ( ridx >= nreturned )
! 392: return 0;
! 393: if ( kqrevents[ridx].ident != fd )
! 394: return 0;
! 395: if ( kqrevents[ridx].flags & EV_ERROR )
! 396: return 0;
! 397: switch ( fd_rw[fd] )
! 398: {
! 399: case FDW_READ: return kqrevents[ridx].filter == EVFILT_READ;
! 400: case FDW_WRITE: return kqrevents[ridx].filter == EVFILT_WRITE;
! 401: default: return 0;
! 402: }
! 403: }
! 404:
! 405:
! 406: static int
! 407: kqueue_get_fd( int ridx )
! 408: {
! 409: if ( ridx < 0 || ridx >= nfiles )
! 410: {
! 411: syslog( LOG_ERR, "bad ridx (%d) in kqueue_get_fd!", ridx );
! 412: return -1;
! 413: }
! 414: return kqrevents[ridx].ident;
! 415: }
! 416:
! 417: #else /* HAVE_KQUEUE */
! 418:
! 419:
! 420: # ifdef HAVE_DEVPOLL
! 421:
! 422: static int maxdpevents;
! 423: static struct pollfd* dpevents;
! 424: static int ndpevents;
! 425: static struct pollfd* dprevents;
! 426: static int* dp_rfdidx;
! 427: static int dp;
! 428:
! 429:
! 430: static int
! 431: devpoll_init( int nfiles )
! 432: {
! 433: dp = open( "/dev/poll", O_RDWR );
! 434: if ( dp == -1 )
! 435: return -1;
! 436: (void) fcntl( dp, F_SETFD, 1 );
! 437: maxdpevents = nfiles * 2;
! 438: dpevents = (struct pollfd*) malloc( sizeof(struct pollfd) * maxdpevents );
! 439: dprevents = (struct pollfd*) malloc( sizeof(struct pollfd) * nfiles );
! 440: dp_rfdidx = (int*) malloc( sizeof(int) * nfiles );
! 441: if ( dpevents == (struct pollfd*) 0 || dprevents == (struct pollfd*) 0 ||
! 442: dp_rfdidx == (int*) 0 )
! 443: return -1;
! 444: (void) memset( dp_rfdidx, 0, sizeof(int) * nfiles );
! 445: return 0;
! 446: }
! 447:
! 448:
! 449: static void
! 450: devpoll_add_fd( int fd, int rw )
! 451: {
! 452: if ( ndpevents >= maxdpevents )
! 453: {
! 454: syslog( LOG_ERR, "too many fds in devpoll_add_fd!" );
! 455: return;
! 456: }
! 457: dpevents[ndpevents].fd = fd;
! 458: switch ( rw )
! 459: {
! 460: case FDW_READ: dpevents[ndpevents].events = POLLIN; break;
! 461: case FDW_WRITE: dpevents[ndpevents].events = POLLOUT; break;
! 462: default: break;
! 463: }
! 464: ++ndpevents;
! 465: }
! 466:
! 467:
! 468: static void
! 469: devpoll_del_fd( int fd )
! 470: {
! 471: if ( ndpevents >= maxdpevents )
! 472: {
! 473: syslog( LOG_ERR, "too many fds in devpoll_del_fd!" );
! 474: return;
! 475: }
! 476: dpevents[ndpevents].fd = fd;
! 477: dpevents[ndpevents].events = POLLREMOVE;
! 478: ++ndpevents;
! 479: }
! 480:
! 481:
! 482: static int
! 483: devpoll_watch( long timeout_msecs )
! 484: {
! 485: int i, r;
! 486: struct dvpoll dvp;
! 487:
! 488: r = sizeof(struct pollfd) * ndpevents;
! 489: if ( r > 0 && write( dp, dpevents, r ) != r )
! 490: return -1;
! 491:
! 492: ndpevents = 0;
! 493: dvp.dp_fds = dprevents;
! 494: dvp.dp_nfds = nfiles;
! 495: dvp.dp_timeout = (int) timeout_msecs;
! 496:
! 497: r = ioctl( dp, DP_POLL, &dvp );
! 498: if ( r == -1 )
! 499: return -1;
! 500:
! 501: for ( i = 0; i < r; ++i )
! 502: dp_rfdidx[dprevents[i].fd] = i;
! 503:
! 504: return r;
! 505: }
! 506:
! 507:
! 508: static int
! 509: devpoll_check_fd( int fd )
! 510: {
! 511: int ridx = dp_rfdidx[fd];
! 512:
! 513: if ( ridx < 0 || ridx >= nfiles )
! 514: {
! 515: syslog( LOG_ERR, "bad ridx (%d) in devpoll_check_fd!", ridx );
! 516: return 0;
! 517: }
! 518: if ( ridx >= nreturned )
! 519: return 0;
! 520: if ( dprevents[ridx].fd != fd )
! 521: return 0;
! 522: if ( dprevents[ridx].revents & POLLERR )
! 523: return 0;
! 524: switch ( fd_rw[fd] )
! 525: {
! 526: case FDW_READ: return dprevents[ridx].revents & ( POLLIN | POLLHUP | POLLNVAL );
! 527: case FDW_WRITE: return dprevents[ridx].revents & ( POLLOUT | POLLHUP | POLLNVAL );
! 528: default: return 0;
! 529: }
! 530: }
! 531:
! 532:
! 533: static int
! 534: devpoll_get_fd( int ridx )
! 535: {
! 536: if ( ridx < 0 || ridx >= nfiles )
! 537: {
! 538: syslog( LOG_ERR, "bad ridx (%d) in devpoll_get_fd!", ridx );
! 539: return -1;
! 540: }
! 541: return dprevents[ridx].fd;
! 542: }
! 543:
! 544:
! 545: # else /* HAVE_DEVPOLL */
! 546:
! 547:
! 548: # ifdef HAVE_POLL
! 549:
! 550: static struct pollfd* pollfds;
! 551: static int npoll_fds;
! 552: static int* poll_fdidx;
! 553: static int* poll_rfdidx;
! 554:
! 555:
! 556: static int
! 557: poll_init( int nfiles )
! 558: {
! 559: int i;
! 560:
! 561: pollfds = (struct pollfd*) malloc( sizeof(struct pollfd) * nfiles );
! 562: poll_fdidx = (int*) malloc( sizeof(int) * nfiles );
! 563: poll_rfdidx = (int*) malloc( sizeof(int) * nfiles );
! 564: if ( pollfds == (struct pollfd*) 0 || poll_fdidx == (int*) 0 ||
! 565: poll_rfdidx == (int*) 0 )
! 566: return -1;
! 567: for ( i = 0; i < nfiles; ++i )
! 568: pollfds[i].fd = poll_fdidx[i] = -1;
! 569: return 0;
! 570: }
! 571:
! 572:
! 573: static void
! 574: poll_add_fd( int fd, int rw )
! 575: {
! 576: if ( npoll_fds >= nfiles )
! 577: {
! 578: syslog( LOG_ERR, "too many fds in poll_add_fd!" );
! 579: return;
! 580: }
! 581: pollfds[npoll_fds].fd = fd;
! 582: switch ( rw )
! 583: {
! 584: case FDW_READ: pollfds[npoll_fds].events = POLLIN; break;
! 585: case FDW_WRITE: pollfds[npoll_fds].events = POLLOUT; break;
! 586: default: break;
! 587: }
! 588: poll_fdidx[fd] = npoll_fds;
! 589: ++npoll_fds;
! 590: }
! 591:
! 592:
! 593: static void
! 594: poll_del_fd( int fd )
! 595: {
! 596: int idx = poll_fdidx[fd];
! 597:
! 598: if ( idx < 0 || idx >= nfiles )
! 599: {
! 600: syslog( LOG_ERR, "bad idx (%d) in poll_del_fd!", idx );
! 601: return;
! 602: }
! 603: --npoll_fds;
! 604: pollfds[idx] = pollfds[npoll_fds];
! 605: poll_fdidx[pollfds[idx].fd] = idx;
! 606: pollfds[npoll_fds].fd = -1;
! 607: poll_fdidx[fd] = -1;
! 608: }
! 609:
! 610:
! 611: static int
! 612: poll_watch( long timeout_msecs )
! 613: {
! 614: int r, ridx, i;
! 615:
! 616: r = poll( pollfds, npoll_fds, (int) timeout_msecs );
! 617: if ( r <= 0 )
! 618: return r;
! 619:
! 620: ridx = 0;
! 621: for ( i = 0; i < npoll_fds; ++i )
! 622: if ( pollfds[i].revents &
! 623: ( POLLIN | POLLOUT | POLLERR | POLLHUP | POLLNVAL ) )
! 624: {
! 625: poll_rfdidx[ridx++] = pollfds[i].fd;
! 626: if ( ridx == r )
! 627: break;
! 628: }
! 629:
! 630: return ridx; /* should be equal to r */
! 631: }
! 632:
! 633:
! 634: static int
! 635: poll_check_fd( int fd )
! 636: {
! 637: int fdidx = poll_fdidx[fd];
! 638:
! 639: if ( fdidx < 0 || fdidx >= nfiles )
! 640: {
! 641: syslog( LOG_ERR, "bad fdidx (%d) in poll_check_fd!", fdidx );
! 642: return 0;
! 643: }
! 644: if ( pollfds[fdidx].revents & POLLERR )
! 645: return 0;
! 646: switch ( fd_rw[fd] )
! 647: {
! 648: case FDW_READ: return pollfds[fdidx].revents & ( POLLIN | POLLHUP | POLLNVAL );
! 649: case FDW_WRITE: return pollfds[fdidx].revents & ( POLLOUT | POLLHUP | POLLNVAL );
! 650: default: return 0;
! 651: }
! 652: }
! 653:
! 654:
! 655: static int
! 656: poll_get_fd( int ridx )
! 657: {
! 658: if ( ridx < 0 || ridx >= nfiles )
! 659: {
! 660: syslog( LOG_ERR, "bad ridx (%d) in poll_get_fd!", ridx );
! 661: return -1;
! 662: }
! 663: return poll_rfdidx[ridx];
! 664: }
! 665:
! 666: # else /* HAVE_POLL */
! 667:
! 668:
! 669: # ifdef HAVE_SELECT
! 670:
! 671: static fd_set master_rfdset;
! 672: static fd_set master_wfdset;
! 673: static fd_set working_rfdset;
! 674: static fd_set working_wfdset;
! 675: static int* select_fds;
! 676: static int* select_fdidx;
! 677: static int* select_rfdidx;
! 678: static int nselect_fds;
! 679: static int maxfd;
! 680: static int maxfd_changed;
! 681:
! 682:
! 683: static int
! 684: select_init( int nfiles )
! 685: {
! 686: int i;
! 687:
! 688: FD_ZERO( &master_rfdset );
! 689: FD_ZERO( &master_wfdset );
! 690: select_fds = (int*) malloc( sizeof(int) * nfiles );
! 691: select_fdidx = (int*) malloc( sizeof(int) * nfiles );
! 692: select_rfdidx = (int*) malloc( sizeof(int) * nfiles );
! 693: if ( select_fds == (int*) 0 || select_fdidx == (int*) 0 ||
! 694: select_rfdidx == (int*) 0 )
! 695: return -1;
! 696: nselect_fds = 0;
! 697: maxfd = -1;
! 698: maxfd_changed = 0;
! 699: for ( i = 0; i < nfiles; ++i )
! 700: select_fds[i] = select_fdidx[i] = -1;
! 701: return 0;
! 702: }
! 703:
! 704:
! 705: static void
! 706: select_add_fd( int fd, int rw )
! 707: {
! 708: if ( nselect_fds >= nfiles )
! 709: {
! 710: syslog( LOG_ERR, "too many fds in select_add_fd!" );
! 711: return;
! 712: }
! 713: select_fds[nselect_fds] = fd;
! 714: switch ( rw )
! 715: {
! 716: case FDW_READ: FD_SET( fd, &master_rfdset ); break;
! 717: case FDW_WRITE: FD_SET( fd, &master_wfdset ); break;
! 718: default: break;
! 719: }
! 720: if ( fd > maxfd )
! 721: maxfd = fd;
! 722: select_fdidx[fd] = nselect_fds;
! 723: ++nselect_fds;
! 724: }
! 725:
! 726:
! 727: static void
! 728: select_del_fd( int fd )
! 729: {
! 730: int idx = select_fdidx[fd];
! 731:
! 732: if ( idx < 0 || idx >= nfiles )
! 733: {
! 734: syslog( LOG_ERR, "bad idx (%d) in select_del_fd!", idx );
! 735: return;
! 736: }
! 737:
! 738: --nselect_fds;
! 739: select_fds[idx] = select_fds[nselect_fds];
! 740: select_fdidx[select_fds[idx]] = idx;
! 741: select_fds[nselect_fds] = -1;
! 742: select_fdidx[fd] = -1;
! 743:
! 744: FD_CLR( fd, &master_rfdset );
! 745: FD_CLR( fd, &master_wfdset );
! 746:
! 747: if ( fd >= maxfd )
! 748: maxfd_changed = 1;
! 749: }
! 750:
! 751:
! 752: static int
! 753: select_get_maxfd( void )
! 754: {
! 755: if ( maxfd_changed )
! 756: {
! 757: int i;
! 758: maxfd = -1;
! 759: for ( i = 0; i < nselect_fds; ++i )
! 760: if ( select_fds[i] > maxfd )
! 761: maxfd = select_fds[i];
! 762: maxfd_changed = 0;
! 763: }
! 764: return maxfd;
! 765: }
! 766:
! 767:
! 768: static int
! 769: select_watch( long timeout_msecs )
! 770: {
! 771: int mfd;
! 772: int r, idx, ridx;
! 773:
! 774: working_rfdset = master_rfdset;
! 775: working_wfdset = master_wfdset;
! 776: mfd = select_get_maxfd();
! 777: if ( timeout_msecs == INFTIM )
! 778: r = select(
! 779: mfd + 1, &working_rfdset, &working_wfdset, (fd_set*) 0,
! 780: (struct timeval*) 0 );
! 781: else
! 782: {
! 783: struct timeval timeout;
! 784: timeout.tv_sec = timeout_msecs / 1000L;
! 785: timeout.tv_usec = ( timeout_msecs % 1000L ) * 1000L;
! 786: r = select(
! 787: mfd + 1, &working_rfdset, &working_wfdset, (fd_set*) 0, &timeout );
! 788: }
! 789: if ( r <= 0 )
! 790: return r;
! 791:
! 792: ridx = 0;
! 793: for ( idx = 0; idx < nselect_fds; ++idx )
! 794: if ( select_check_fd( select_fds[idx] ) )
! 795: {
! 796: select_rfdidx[ridx++] = select_fds[idx];
! 797: if ( ridx == r )
! 798: break;
! 799: }
! 800:
! 801: return ridx; /* should be equal to r */
! 802: }
! 803:
! 804:
! 805: static int
! 806: select_check_fd( int fd )
! 807: {
! 808: switch ( fd_rw[fd] )
! 809: {
! 810: case FDW_READ: return FD_ISSET( fd, &working_rfdset );
! 811: case FDW_WRITE: return FD_ISSET( fd, &working_wfdset );
! 812: default: return 0;
! 813: }
! 814: }
! 815:
! 816:
! 817: static int
! 818: select_get_fd( int ridx )
! 819: {
! 820: if ( ridx < 0 || ridx >= nfiles )
! 821: {
! 822: syslog( LOG_ERR, "bad ridx (%d) in select_get_fd!", ridx );
! 823: return -1;
! 824: }
! 825: return select_rfdidx[ridx];
! 826: }
! 827:
! 828: # endif /* HAVE_SELECT */
! 829:
! 830: # endif /* HAVE_POLL */
! 831:
! 832: # endif /* HAVE_DEVPOLL */
! 833:
! 834: #endif /* HAVE_KQUEUE */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>