static void rb_read_timerfd(rb_fde_t *F, void *data) { struct ev_entry *event = (struct ev_entry *)data; int retlen; uint64_t count; if(event == NULL) { rb_close(F); return; } retlen = rb_read(F, &count, sizeof(count)); if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno))) { rb_close(F); rb_lib_log("rb_read_timerfd: timerfd[%s] closed on error: %s", event->name, strerror(errno)); return; } rb_setselect(F, RB_SELECT_READ, rb_read_timerfd, event); rb_run_event(event); }
int rb_select_ports(long delay) { int i, fd; unsigned int nget = 1; struct timespec poll_time; struct timespec *p = NULL; struct ev_entry *ev; if(delay >= 0) { poll_time.tv_sec = delay / 1000; poll_time.tv_nsec = (delay % 1000) * 1000000; p = &poll_time; } i = port_getn(pe, pelst, pemax, &nget, p); rb_set_time(); if(i == -1) return RB_OK; for(i = 0; (unsigned)i < nget; i++) { if(pelst[i].portev_source == PORT_SOURCE_FD) { fd = pelst[i].portev_object; PF *hdl = NULL; rb_fde_t *F = pelst[i].portev_user; if((pelst[i].portev_events & (POLLIN | POLLHUP | POLLERR)) && (hdl = F->read_handler)) { F->read_handler = NULL; hdl(F, F->read_data); } if((pelst[i].portev_events & (POLLOUT | POLLHUP | POLLERR)) && (hdl = F->write_handler)) { F->write_handler = NULL; hdl(F, F->write_data); } } else if(pelst[i].portev_source == PORT_SOURCE_TIMER) { ev = (struct ev_entry *)pelst[i].portev_user; rb_run_event(ev); } } return RB_OK; }
static void signalfd_handler(rb_fde_t *F, void *data) { static struct our_signalfd_siginfo fdsig[SIGFDIOV_COUNT]; static struct iovec iov[SIGFDIOV_COUNT]; struct ev_entry *ev; int ret, x; for(x = 0; x < SIGFDIOV_COUNT; x++) { iov[x].iov_base = &fdsig[x]; iov[x].iov_len = sizeof(struct our_signalfd_siginfo); } while(1) { ret = readv(rb_get_fd(F), iov, SIGFDIOV_COUNT); if(ret == 0 || (ret < 0 && !rb_ignore_errno(errno))) { rb_close(F); rb_epoll_init_event(); return; } if(ret < 0) { rb_setselect(F, RB_SELECT_READ, signalfd_handler, NULL); return; } for(x = 0; x < ret / (int)sizeof(struct our_signalfd_siginfo); x++) { #if __WORDSIZE == 32 && defined(__sparc__) uint32_t *q = (uint32_t *)&fdsig[x].svptr; ev = (struct ev_entry *)q[0]; #else ev = (struct ev_entry *)(uintptr_t)(fdsig[x].svptr); #endif if(ev == NULL) continue; rb_run_event(ev); } } }
int rb_select_kqueue(long delay) { int num, i; struct timespec poll_time; struct timespec *pt; rb_fde_t *F; if(delay < 0) { pt = NULL; } else { pt = &poll_time; poll_time.tv_sec = delay / 1000; poll_time.tv_nsec = (delay % 1000) * 1000000; } for(;;) { num = kevent(kq, kqlst, kqoff, kqout, kqmax, pt); kqoff = 0; if(num >= 0) break; if(rb_ignore_errno(errno)) break; rb_set_time(); return RB_ERROR; /* NOTREACHED */ } rb_set_time(); if(num == 0) return RB_OK; /* No error.. */ for(i = 0; i < num; i++) { PF *hdl = NULL; if(kqout[i].flags & EV_ERROR) { errno = kqout[i].data; /* XXX error == bad! -- adrian */ continue; /* XXX! */ } switch (kqout[i].filter) { case EVFILT_READ: F = kqout[i].udata; if((hdl = F->read_handler) != NULL) { F->read_handler = NULL; hdl(F, F->read_data); } break; case EVFILT_WRITE: F = kqout[i].udata; if((hdl = F->write_handler) != NULL) { F->write_handler = NULL; hdl(F, F->write_data); } break; #if defined(EVFILT_TIMER) case EVFILT_TIMER: rb_run_event(kqout[i].udata); break; #endif default: /* Bad! -- adrian */ break; } } return RB_OK; }
/* int rb_select(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 * rb_setselect and fd_table[] and calls callbacks for IO ready * events. */ int rb_select_sigio(long delay) { int num = 0; int revents = 0; int sig; int fd; int ci; PF *hdl; rb_fde_t *F; void *data; siginfo_t si; struct timespec timeout; if(rb_sigio_supports_event() || delay >= 0) { timeout.tv_sec = (delay / 1000); timeout.tv_nsec = (delay % 1000) * 1000000; } for(;;) { if(!sigio_is_screwed) { if(can_do_event || delay < 0) { sig = sigwaitinfo(&our_sigset, &si); } else sig = sigtimedwait(&our_sigset, &si, &timeout); if(sig > 0) { if(sig == SIGIO) { rb_lib_log ("Kernel RT Signal queue overflowed. Is ulimit -i too small(or perhaps /proc/sys/kernel/rtsig-max on old kernels)"); sigio_is_screwed = 1; break; } #ifdef SIGIO_SCHED_EVENT if(sig == RTSIGTIM && can_do_event) { struct ev_entry *ev = (struct ev_entry *)si.si_ptr; if(ev == NULL) continue; rb_run_event(ev); continue; } #endif fd = si.si_fd; pollfd_list.pollfds[fd].revents |= si.si_band; revents = pollfd_list.pollfds[fd].revents; num++; F = rb_find_fd(fd); if(F == NULL) continue; if(revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { hdl = F->read_handler; data = F->read_data; F->read_handler = NULL; F->read_data = NULL; if(hdl) hdl(F, data); } if(revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) { hdl = F->write_handler; data = F->write_data; F->write_handler = NULL; F->write_data = NULL; if(hdl) hdl(F, data); } } else break; } else break; } if(!sigio_is_screwed) { /* We don't need to proceed */ rb_set_time(); return 0; } signal(RTSIGIO, SIG_IGN); signal(RTSIGIO, SIG_DFL); sigio_is_screwed = 0; num = poll(pollfd_list.pollfds, pollfd_list.maxindex + 1, delay); rb_set_time(); if(num < 0) { if(!rb_ignore_errno(errno)) return RB_OK; else return RB_ERROR; } if(num == 0) return RB_OK; /* 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 = rb_find_fd(fd); if(F == NULL) continue; if(revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) { hdl = F->read_handler; data = F->read_data; F->read_handler = NULL; F->read_data = NULL; if(hdl) hdl(F, data); } if(IsFDOpen(F) && (revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR))) { hdl = F->write_handler; data = F->write_data; F->write_handler = NULL; F->write_data = NULL; if(hdl) hdl(F, data); } if(F->read_handler == NULL) rb_setselect_sigio(F, RB_SELECT_READ, NULL, NULL); if(F->write_handler == NULL) rb_setselect_sigio(F, RB_SELECT_WRITE, NULL, NULL); } return 0; }