/* * comm_setselect * * This is a needed exported function which will be called to register * and deregister interest in a pending IO state for a given FD. */ void comm_setselect(int fd, fdlist_t list, unsigned int type, PF *handler, void *client_data, time_t timeout) { fde_t *F = &fd_table[fd]; assert(fd >= 0); assert(F->flags.open); if (type & COMM_SELECT_READ) { F->read_handler = handler; F->read_data = client_data; poll_update_pollfds(fd, POLLIN, handler); } if (type & COMM_SELECT_WRITE) { F->write_handler = handler; F->write_data = client_data; poll_update_pollfds(fd, POLLOUT, handler); } if (timeout) F->timeout = CurrentTime + (timeout / 1000); }
/* void comm_select_fdlist(unsigned long delay) * Input: The maximum time to delay. * Output: None * Side-effects: Deregisters future interest in IO and calls the handlers * if an event occurs for an FD. * Comments: Check all connections for new connections and input data * that is to be processed. Also check for connections with data queued * and whether we can write it out. * Called to do the new-style IO, courtesy of of squid (like most of this * new IO code). This routine handles the stuff we've hidden in * comm_setselect and fd_table[] and calls callbacks for IO ready * events. */ void comm_select(unsigned long delay) { int num, fd, ci, revents; PF *hdl; fde_t *F; /* XXX kill that +1 later ! -- adrian */ while ((num = poll(pollfd_list.pollfds, pollfd_list.maxindex + 1, delay)) < 0 && ignoreErrno(errno)) ; set_time(); if (num == 0) return; /* XXX we *could* optimise by falling out after doing num fds ... * Currently it'd be hard to do, because pollfd_list can be changed * within this loop (by I/O handlers) --adx */ for (ci = 0; ci < pollfd_list.maxindex + 1; ci++) { if (((revents = pollfd_list.pollfds[ci].revents) == 0) || (pollfd_list.pollfds[ci].fd) == -1) continue; fd = pollfd_list.pollfds[ci].fd; F = &fd_table[fd]; if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { hdl = F->read_handler; F->read_handler = NULL; poll_update_pollfds(fd, POLLRDNORM, NULL); if (hdl) hdl(fd, F->read_data); } if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { hdl = F->write_handler; F->write_handler = NULL; poll_update_pollfds(fd, POLLWRNORM, NULL); if (hdl) hdl(fd, F->write_data); } } }
/* * comm_setselect * * This is a needed exported function which will be called to register * and deregister interest in a pending IO state for a given FD. */ void comm_setselect(int fd, fdlist_t list, unsigned int type, PF * handler, void *client_data) { fde_t *F = &fd_table[fd]; s_assert(fd >= 0); s_assert(F->flags.open); if(type & COMM_SELECT_READ) { F->read_handler = handler; F->read_data = client_data; poll_update_pollfds(fd, POLLRDNORM, handler); } if(type & COMM_SELECT_WRITE) { F->write_handler = handler; F->write_data = client_data; poll_update_pollfds(fd, POLLWRNORM, handler); } }
/* int comm_select(unsigned long delay) * Input: The maximum time to delay. * Output: Returns -1 on error, 0 on success. * Side-effects: Deregisters future interest in IO and calls the handlers * if an event occurs for an FD. * Comments: Check all connections for new connections and input data * that is to be processed. Also check for connections with data queued * and whether we can write it out. * Called to do the new-style IO, courtesy of of squid (like most of this * new IO code). This routine handles the stuff we've hidden in * comm_setselect and fd_table[] and calls callbacks for IO ready * events. */ int comm_select(unsigned long delay) { int num = 0; int revents = 0; int sig; int fd; int ci; PF *hdl; fde_t *F; struct siginfo si; struct timespec timeout; timeout.tv_sec = 0; timeout.tv_nsec = 1000000 * delay; for (;;) { if (!sigio_is_screwed) { if ((sig = sigtimedwait(&our_sigset, &si, &timeout)) > 0) { if (sig == SIGIO) { ilog(L_WARN, "Kernel RT Signal queue overflowed. Is /proc/sys/kernel/rtsig-max too small?"); sigio_is_screwed = 1; break; } fd = si.si_fd; pollfd_list.pollfds[fd].revents |= si.si_band; revents = pollfd_list.pollfds[fd].revents; num++; F = &fd_table[fd]; set_time(); if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { callbacks_called++; hdl = F->read_handler; F->read_handler = NULL; poll_update_pollfds(fd, POLLIN, NULL); if (hdl) hdl(fd, F->read_data); } if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { callbacks_called++; hdl = F->write_handler; F->write_handler = NULL; poll_update_pollfds(fd, POLLOUT, NULL); if (hdl) hdl(fd, F->write_data); } } else break; } else break; } if (!sigio_is_screwed) /* We don't need to proceed */ { set_time(); return 0; } for (;;) { if (sigio_is_screwed) { signal(sigio_signal, SIG_IGN); signal(sigio_signal, SIG_DFL); sigio_is_screwed = 0; } num = poll(pollfd_list.pollfds, pollfd_list.maxindex + 1, 0); if (num >= 0) break; if (ignoreErrno(errno)) continue; /* error! */ set_time(); return -1; /* NOTREACHED */ } /* update current time again, eww.. */ set_time(); if (num == 0) return 0; /* XXX we *could* optimise by falling out after doing num fds ... */ for (ci = 0; ci < pollfd_list.maxindex + 1; ci++) { if (((revents = pollfd_list.pollfds[ci].revents) == 0) || (pollfd_list.pollfds[ci].fd) == -1) continue; fd = pollfd_list.pollfds[ci].fd; F = &fd_table[fd]; if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { callbacks_called++; hdl = F->read_handler; F->read_handler = NULL; poll_update_pollfds(fd, POLLIN, NULL); if (hdl) hdl(fd, F->read_data); } if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { callbacks_called++; hdl = F->write_handler; F->write_handler = NULL; poll_update_pollfds(fd, POLLOUT, NULL); if (hdl) hdl(fd, F->write_data); } } mask_our_signal(sigio_signal); return 0; }
/* void comm_select(unsigned long delay) * Input: The maximum time to delay. * Output: None * Side-effects: Deregisters future interest in IO and calls the handlers * if an event occurs for an FD. * Comments: Check all connections for new connections and input data * that is to be processed. Also check for connections with data queued * and whether we can write it out. * Called to do the new-style IO, courtesy of squid (like most of this * new IO code). This routine handles the stuff we've hidden in * comm_setselect and fd_table[] and calls callbacks for IO ready * events. */ void comm_select(unsigned long delay) { int revents = 0, sig, fd; PF *hdl; fde_t *F; struct siginfo si; struct timespec timeout; timeout.tv_sec = 0; timeout.tv_nsec = 1000000 * delay; sig = sigtimedwait(&our_sigset, &si, &timeout); set_time(); if (sig != SIGIO) { if (sig > 0) { fd = si.si_fd; pollfd_list.pollfds[fd].revents |= si.si_band; revents = pollfd_list.pollfds[fd].revents; F = &fd_table[fd]; if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { hdl = F->read_handler; F->read_handler = NULL; poll_update_pollfds(fd, POLLIN, NULL); if (hdl) hdl(fd, F->read_data); } if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { hdl = F->write_handler; F->write_handler = NULL; poll_update_pollfds(fd, POLLOUT, NULL); if (hdl) hdl(fd, F->write_data); } } return; } /* RT signal queue overflowed.. */ if (CurrentTime - last_rtsigqo_warning >= 30) { ilog(L_WARN, "Kernel RT Signal queue overflowed. " "Is /proc/sys/kernel/rtsig-max too small?"); last_rtsigqo_warning = CurrentTime; } signal(SIGIO_SIGNAL, SIG_IGN); signal(SIGIO_SIGNAL, SIG_DFL); /* ..try polling instead */ { int num, ci; while ((num = poll(pollfd_list.pollfds, pollfd_list.maxindex + 1, 0)) < 0 && ignoreErrno(errno)) ; /* update current time again, eww.. */ set_time(); if (num > 0) { /* XXX we *could* optimise by falling out after doing num fds ... */ for (ci = 0; ci < pollfd_list.maxindex + 1; ci++) { if (((revents = pollfd_list.pollfds[ci].revents) == 0) || (pollfd_list.pollfds[ci].fd) == -1) continue; fd = pollfd_list.pollfds[ci].fd; F = &fd_table[fd]; if (revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { hdl = F->read_handler; F->read_handler = NULL; poll_update_pollfds(fd, POLLIN, NULL); if (hdl) hdl(fd, F->read_data); } if (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { hdl = F->write_handler; F->write_handler = NULL; poll_update_pollfds(fd, POLLOUT, NULL); if (hdl) hdl(fd, F->write_data); } } } } mask_our_signal(SIGIO_SIGNAL); }
/* int comm_select_fdlist(unsigned long delay) * Input: The maximum time to delay. * Output: Returns -1 on error, 0 on success. * Side-effects: Deregisters future interest in IO and calls the handlers * if an event occurs for an FD. * Comments: Check all connections for new connections and input data * that is to be processed. Also check for connections with data queued * and whether we can write it out. * Called to do the new-style IO, courtesy of squid (like most of this * new IO code). This routine handles the stuff we've hidden in * comm_setselect and fd_table[] and calls callbacks for IO ready * events. */ int comm_select(unsigned long delay) { int num; int fd; int ci; unsigned long ndelay; PF *hdl; if(last_count > 0) { empty_count = 0; ndelay = 0; } else { ndelay = ++empty_count * 15000 ; if(ndelay > delay * 1000) ndelay = delay * 1000; } for (;;) { /* XXX kill that +1 later ! -- adrian */ if(ndelay > 0) irc_sleep(ndelay); last_count = num = poll(pollfd_list.pollfds, pollfd_list.maxindex + 1, 0); if(num >= 0) break; if(ignoreErrno(errno)) continue; /* error! */ set_time(); return -1; /* NOTREACHED */ } /* update current time again, eww.. */ set_time(); if(num == 0) return 0; /* XXX we *could* optimise by falling out after doing num fds ... */ for (ci = 0; ci < pollfd_list.maxindex + 1; ci++) { fde_t *F; int revents; if(((revents = pollfd_list.pollfds[ci].revents) == 0) || (pollfd_list.pollfds[ci].fd) == -1) continue; fd = pollfd_list.pollfds[ci].fd; F = &fd_table[fd]; if(revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { hdl = F->read_handler; F->read_handler = NULL; poll_update_pollfds(fd, POLLRDNORM, NULL); if(hdl) hdl(fd, F->read_data); } if(revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { hdl = F->write_handler; F->write_handler = NULL; poll_update_pollfds(fd, POLLWRNORM, NULL); if(hdl) hdl(fd, F->write_data); } } return 0; }