/* * FD polling functions for generic poll() * * Copyright 2000-2007 Willy Tarreau * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. * */ #include #include #include #include #include #include #include #include #include #include #include static fd_set *StaticReadEvent, *StaticWriteEvent; /* private data */ static struct pollfd *poll_events = NULL; /* * Benchmarks performed on a Pentium-M notebook show that using functions * instead of the usual macros improve the FD_* performance by about 80%, * and that marking them regparm(2) adds another 20%. */ REGPRM2 static int __fd_isset(const int fd, const int dir) { fd_set *ev; if (dir == DIR_RD) ev = StaticReadEvent; else ev = StaticWriteEvent; return FD_ISSET(fd, ev); } REGPRM2 static void __fd_set(const int fd, const int dir) { fd_set *ev; if (dir == DIR_RD) ev = StaticReadEvent; else ev = StaticWriteEvent; FD_SET(fd, ev); } REGPRM2 static void __fd_clr(const int fd, const int dir) { fd_set *ev; if (dir == DIR_RD) ev = StaticReadEvent; else ev = StaticWriteEvent; FD_CLR(fd, ev); } REGPRM2 static int __fd_cond_s(const int fd, const int dir) { int ret; fd_set *ev; if (dir == DIR_RD) ev = StaticReadEvent; else ev = StaticWriteEvent; ret = !FD_ISSET(fd, ev); if (ret) FD_SET(fd, ev); return ret; } REGPRM2 static int __fd_cond_c(const int fd, const int dir) { int ret; fd_set *ev; if (dir == DIR_RD) ev = StaticReadEvent; else ev = StaticWriteEvent; ret = FD_ISSET(fd, ev); if (ret) FD_CLR(fd, ev); return ret; } REGPRM1 static void __fd_rem(const int fd) { FD_CLR(fd, StaticReadEvent); FD_CLR(fd, StaticWriteEvent); } /* * Initialization of the poll() poller. * Returns 0 in case of failure, non-zero in case of success. If it fails, it * disables the poller by setting its pref to 0. */ REGPRM1 static int poll_init(struct poller *p) { __label__ fail_swevt, fail_srevt, fail_pe; int fd_set_bytes; p->private = NULL; fd_set_bytes = sizeof(fd_set) * (global.maxsock + FD_SETSIZE - 1) / FD_SETSIZE; poll_events = (struct pollfd*) calloc(1, sizeof(struct pollfd) * global.maxsock); if (poll_events == NULL) goto fail_pe; if ((StaticReadEvent = (fd_set *)calloc(1, fd_set_bytes)) == NULL) goto fail_srevt; if ((StaticWriteEvent = (fd_set *)calloc(1, fd_set_bytes)) == NULL) goto fail_swevt; return 1; fail_swevt: free(StaticReadEvent); fail_srevt: free(poll_events); fail_pe: p->pref = 0; return 0; } /* * Termination of the poll() poller. * Memory is released and the poller is marked as unselectable. */ REGPRM1 static void poll_term(struct poller *p) { if (StaticWriteEvent) free(StaticWriteEvent); if (StaticReadEvent) free(StaticReadEvent); if (poll_events) free(poll_events); p->private = NULL; p->pref = 0; } /* * Poll() poller */ REGPRM2 static void poll_poll(struct poller *p, int wait_time) { int status; int fd, nbfd; int fds, count; int sr, sw; unsigned rn, wn; /* read new, write new */ nbfd = 0; for (fds = 0; (fds << INTBITS) < maxfd; fds++) { rn = ((int*)StaticReadEvent)[fds]; wn = ((int*)StaticWriteEvent)[fds]; if ((rn|wn)) { for (count = 0, fd = fds << INTBITS; count < (1<> count) & 1; sw = (wn >> count) & 1; #else sr = FD_ISSET(fd&((1< 0 && count < nbfd; count++) { fd = poll_events[count].fd; if (!(poll_events[count].revents & ( POLLOUT | POLLIN | POLLERR | POLLHUP ))) continue; /* ok, we found one active fd */ status--; if (FD_ISSET(fd, StaticReadEvent)) { if (fdtab[fd].state == FD_STCLOSE) continue; if (poll_events[count].revents & ( POLLIN | POLLERR | POLLHUP )) fdtab[fd].cb[DIR_RD].f(fd); } if (FD_ISSET(fd, StaticWriteEvent)) { if (fdtab[fd].state == FD_STCLOSE) continue; if (poll_events[count].revents & ( POLLOUT | POLLERR | POLLHUP )) fdtab[fd].cb[DIR_WR].f(fd); } } } /* * The only exported function. Returns 1. */ int poll_register(struct poller *p) { p->name = "poll"; p->pref = 200; p->private = NULL; p->init = poll_init; p->term = poll_term; p->poll = poll_poll; p->isset = __fd_isset; p->set = __fd_set; p->clr = __fd_clr; p->clo = p->rem = __fd_rem; p->cond_s = __fd_cond_s; p->cond_c = __fd_cond_c; return 1; } /* * Local variables: * c-indent-level: 8 * c-basic-offset: 8 * End: */