/* * rb_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 rb_setselect_ports(rb_fde_t *F, unsigned int type, PF * handler, void *client_data) { lrb_assert(IsFDOpen(F)); int old_flags = F->pflags; if(type & RB_SELECT_READ) { F->read_handler = handler; F->read_data = client_data; } if(type & RB_SELECT_WRITE) { F->write_handler = handler; F->write_data = client_data; } F->pflags = 0; if(F->read_handler != NULL) F->pflags = POLLIN; if(F->write_handler != NULL) F->pflags |= POLLOUT; if(old_flags == 0 && F->pflags == 0) return; else if(F->pflags <= 0) { port_dissociate(pe, PORT_SOURCE_FD, F->fd); return; } port_associate(pe, PORT_SOURCE_FD, F->fd, F->pflags, F); }
static LRESULT CALLBACK rb_process_events(HWND nhwnd, UINT umsg, WPARAM wparam, LPARAM lparam) { rb_fde_t *F; PF *hdl; void *data; switch (umsg) { case WM_SOCKET: { F = rb_find_fd(wparam); if(F != NULL && IsFDOpen(F)) { switch (WSAGETSELECTEVENT(lparam)) { case FD_ACCEPT: case FD_CLOSE: case FD_READ: { if((hdl = F->read_handler) != NULL) { F->read_handler = NULL; data = F->read_data; F->read_data = NULL; hdl(F, data); } break; } case FD_CONNECT: case FD_WRITE: { if((hdl = F->write_handler) != NULL) { F->write_handler = NULL; data = F->write_data; F->write_data = NULL; hdl(F, data); } } } } return 0; } case WM_DESTROY: { PostQuitMessage(0); return 0; } default: return DefWindowProc(nhwnd, umsg, wparam, lparam); } return 0; }
/* * rb_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 rb_setselect_epoll(rb_fde_t *F, unsigned int type, PF * handler, void *client_data) { struct epoll_event ep_event; int old_flags = F->pflags; int op = -1; lrb_assert(IsFDOpen(F)); /* Update the list, even though we're not using it .. */ if(type & RB_SELECT_READ) { if(handler != NULL) F->pflags |= EPOLLIN; else F->pflags &= ~EPOLLIN; F->read_handler = handler; F->read_data = client_data; } if(type & RB_SELECT_WRITE) { if(handler != NULL) F->pflags |= EPOLLOUT; else F->pflags &= ~EPOLLOUT; F->write_handler = handler; F->write_data = client_data; } if(old_flags == 0 && F->pflags == 0) return; else if(F->pflags <= 0) op = EPOLL_CTL_DEL; else if(old_flags == 0 && F->pflags > 0) op = EPOLL_CTL_ADD; else if(F->pflags != old_flags) op = EPOLL_CTL_MOD; if(op == -1) return; ep_event.events = F->pflags; ep_event.data.ptr = F; if(op == EPOLL_CTL_ADD || op == EPOLL_CTL_MOD) ep_event.events |= EPOLLET; if(epoll_ctl(ep_info->ep, op, F->fd, &ep_event) != 0) { rb_lib_log("rb_setselect_epoll(): epoll_ctl failed: %s", strerror(errno)); abort(); } }
int rb_select_select(long delay) { int num; int fd; PF *hdl; rb_fde_t *F; struct timeval to; /* Copy over the read/write sets so we don't have to rebuild em */ memcpy(&tmpreadfds, &select_readfds, sizeof(fd_set)); memcpy(&tmpwritefds, &select_writefds, sizeof(fd_set)); for (;;) { to.tv_sec = 0; to.tv_usec = delay * 1000; num = select(rb_maxfd + 1, &tmpreadfds, &tmpwritefds, NULL, &to); if (num >= 0) break; if (rb_ignore_errno(errno)) continue; rb_set_time(); /* error! */ return -1; /* NOTREACHED */ } rb_set_time(); if (num == 0) return 0; /* XXX we *could* optimise by falling out after doing num fds ... */ for (fd = 0; fd < rb_maxfd + 1; fd++) { F = rb_find_fd(fd); if (F == NULL) continue; if (FD_ISSET(fd, &tmpreadfds)) { hdl = F->read_handler; F->read_handler = NULL; if (hdl) hdl(F, F->read_data); } if (!IsFDOpen(F)) continue; /* Read handler closed us..go on */ if (FD_ISSET(fd, &tmpwritefds)) { hdl = F->write_handler; F->write_handler = NULL; if (hdl) hdl(F, F->write_data); } if (F->read_handler == NULL) select_update_selectfds(F, RB_SELECT_READ, NULL); if (F->write_handler == NULL) select_update_selectfds(F, RB_SELECT_WRITE, NULL); } return 0; }
/* * rb_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 rb_setselect_select(rb_fde_t *F, unsigned int type, PF * handler, void *client_data) { lrb_assert(IsFDOpen(F)); if (type & RB_SELECT_READ) { F->read_handler = handler; F->read_data = client_data; select_update_selectfds(F, RB_SELECT_READ, handler); } if (type & RB_SELECT_WRITE) { F->write_handler = handler; F->write_data = client_data; select_update_selectfds(F, RB_SELECT_WRITE, handler); } }
/* * rb_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 rb_setselect_kqueue(rb_fde_t *F, unsigned int type, PF * handler, void *client_data) { lrb_assert(IsFDOpen(F)); if(type & RB_SELECT_READ) { kq_update_events(F, EVFILT_READ, handler); F->read_handler = handler; F->read_data = client_data; } if(type & RB_SELECT_WRITE) { kq_update_events(F, EVFILT_WRITE, handler); F->write_handler = handler; F->write_data = client_data; } }
void rb_setselect_win32(rb_fde_t *F, unsigned int type, PF * handler, void *client_data) { int old_flags = F->pflags; lrb_assert(IsFDOpen(F)); /* Update the list, even though we're not using it .. */ if(type & RB_SELECT_READ) { if(handler != NULL) F->pflags |= FD_CLOSE | FD_READ | FD_ACCEPT; else F->pflags &= ~(FD_CLOSE | FD_READ | FD_ACCEPT); F->read_handler = handler; F->read_data = client_data; } if(type & RB_SELECT_WRITE) { if(handler != NULL) F->pflags |= FD_WRITE | FD_CONNECT; else F->pflags &= ~(FD_WRITE | FD_CONNECT); F->write_handler = handler; F->write_data = client_data; } if(old_flags == 0 && F->pflags == 0) return; if(F->pflags != old_flags) { WSAAsyncSelect(F->fd, hwnd, WM_SOCKET, F->pflags); } }
int rb_select_epoll(long delay) { int num, i, flags, old_flags, op; struct epoll_event ep_event; int o_errno; void *data; num = epoll_wait(ep_info->ep, ep_info->pfd, ep_info->pfd_size, delay); /* save errno as rb_set_time() will likely clobber it */ o_errno = errno; rb_set_time(); errno = o_errno; if(num < 0 && !rb_ignore_errno(o_errno)) return RB_ERROR; if(num <= 0) return RB_OK; for(i = 0; i < num; i++) { PF *hdl; rb_fde_t *F = ep_info->pfd[i].data.ptr; old_flags = F->pflags; if(ep_info->pfd[i].events & (EPOLLIN | EPOLLHUP | EPOLLERR)) { hdl = F->read_handler; data = F->read_data; F->read_handler = NULL; F->read_data = NULL; if(hdl) { hdl(F, data); } } if(!IsFDOpen(F)) continue; if(ep_info->pfd[i].events & (EPOLLOUT | EPOLLHUP | EPOLLERR)) { hdl = F->write_handler; data = F->write_data; F->write_handler = NULL; F->write_data = NULL; if(hdl) { hdl(F, data); } } if(!IsFDOpen(F)) continue; flags = 0; if(F->read_handler != NULL) flags |= EPOLLIN; if(F->write_handler != NULL) flags |= EPOLLOUT; if(old_flags != flags) { if(flags == 0) op = EPOLL_CTL_DEL; else op = EPOLL_CTL_MOD; F->pflags = ep_event.events = flags; ep_event.data.ptr = F; if(op == EPOLL_CTL_MOD || op == EPOLL_CTL_ADD) ep_event.events |= EPOLLET; if(epoll_ctl(ep_info->ep, op, F->fd, &ep_event) != 0) { rb_lib_log("rb_select_epoll(): epoll_ctl failed: %s", strerror(errno)); } } } return RB_OK; }
int rb_select_poll(long delay) { int num; int fd; int ci; PF *hdl; void *data; struct pollfd *pfd; int revents; 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++) { rb_fde_t *F; pfd = &pollfd_list.pollfds[ci]; revents = pfd->revents; fd = pfd->fd; if(revents == 0 || fd == -1) continue; 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_poll(F, RB_SELECT_READ, NULL, NULL); if(F->write_handler == NULL) rb_setselect_poll(F, RB_SELECT_WRITE, NULL, NULL); } return 0; }
int rb_select_devpoll(long delay) { int num, i; struct pollfd pollfds[maxfd]; struct dvpoll dopoll; do { for(;;) { dopoll.dp_timeout = delay; dopoll.dp_nfds = maxfd; dopoll.dp_fds = &pollfds[0]; num = ioctl(dpfd, DP_POLL, &dopoll); if(num >= 0) break; if(rb_ignore_errno(errno)) break; rb_set_time(); return RB_ERROR; } rb_set_time(); if(num == 0) continue; for(i = 0; i < num; i++) { int fd = dopoll.dp_fds[i].fd; PF *hdl = NULL; rb_fde_t *F = rb_find_fd(fd); if((dopoll.dp_fds[i].revents & (POLLRDNORM | POLLIN | POLLHUP | POLLERR)) && (dopoll.dp_fds[i].events & (POLLRDNORM | POLLIN))) { if((hdl = F->read_handler) != NULL) { F->read_handler = NULL; hdl(F, F->read_data); /* * this call used to be with a NULL pointer, BUT * in the devpoll case we only want to update the * poll set *if* the handler changes state (active -> * NULL or vice versa.) */ devpoll_update_events(F, RB_SELECT_READ, F->read_handler); } } if(!IsFDOpen(F)) continue; /* Read handler closed us..go on to do something more useful */ if((dopoll.dp_fds[i].revents & (POLLWRNORM | POLLOUT | POLLHUP | POLLERR)) && (dopoll.dp_fds[i].events & (POLLWRNORM | POLLOUT))) { if((hdl = F->write_handler) != NULL) { F->write_handler = NULL; hdl(F, F->write_data); /* See above similar code in the read case */ devpoll_update_events(F, RB_SELECT_WRITE, F->write_handler); } } } return RB_OK; } while(0); /* XXX Get here, we broke! */ return 0; }
/* 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; }