extern int fdwatch_del_fd(int idx) { if (idx < 0 || idx >= fdw_maxcons) { ERROR2("out of bounds idx [{}] (max: {})", idx, fdw_maxcons); return -1; } t_fdwatch_fd *cfd = fdw_fds + idx; if (!fdw_rw(cfd)) { ERROR0("found reseted rw"); return -1; } fdw->del(idx); /* remove it from uselist, add it to freelist */ uselist.remove(*cfd); freelist.push_back(*cfd); fdw_fd(cfd) = 0; fdw_rw(cfd) = 0; fdw_data(cfd) = NULL; fdw_hnd(cfd) = NULL; return 0; }
static void fdw_poll_handle(void) { register unsigned i; int changed; t_fdwatch_fd *cfd; for(i = 0; i < nofds && sr; i++) { changed = 0; cfd = fdw_fds + _rridx[i]; if (fdw_rw(cfd) & fdwatch_type_read && fds[i].revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL)) { if (fdw_hnd(cfd)(fdw_data(cfd), fdwatch_type_read) == -2) { sr--; continue; } changed = 1; } if (fdw_rw(cfd) & fdwatch_type_write && fds[i].revents & (POLLOUT | POLLERR | POLLHUP | POLLNVAL)) { fdw_hnd(cfd)(fdw_data(cfd), fdwatch_type_write); changed = 1; } if (changed) sr--; } }
static int fdw_select_cb(t_fdwatch_fd *cfd, void *data) { // eventlog(eventlog_level_trace, __FUNCTION__, "idx: %d fd: %d", idx, fdw_fd->fd); if (fdw_rw(cfd) & fdwatch_type_read && PSOCK_FD_ISSET(fdw_fd(cfd), rfds) && fdw_hnd(cfd)(fdw_data(cfd), fdwatch_type_read) == -2) return 0; if (fdw_rw(cfd) & fdwatch_type_write && PSOCK_FD_ISSET(fdw_fd(cfd), wfds)) fdw_hnd(cfd)(fdw_data(cfd), fdwatch_type_write); return 0; }
void FDWKqueueBackend::handle() { /* eventlog(eventlog_level_trace, __FUNCTION__, "called"); */ for (unsigned i = 0; i < sr; i++) { /* eventlog(eventlog_level_trace, __FUNCTION__, "checking %d ident: %d read: %d write: %d", i, kqevents[i].ident, kqevents[i].filter & EVFILT_READ, kqevents[i].filter & EVFILT_WRITE); */ t_fdwatch_fd *cfd = fdw_fds + (unsigned long)kqevents[i].udata; if (fdw_rw(cfd) & fdwatch_type_read && kqevents[i].filter == EVFILT_READ) if (fdw_hnd(cfd) (fdw_data(cfd), fdwatch_type_read) == -2) continue; if (fdw_rw(cfd) & fdwatch_type_write && kqevents[i].filter == EVFILT_WRITE) fdw_hnd(cfd) (fdw_data(cfd), fdwatch_type_write); } sr = 0; }
void FDWEpollBackend::handle() { // eventlog(eventlog_level_trace, __FUNCTION__, "called"); for (struct epoll_event *ev = epevents.get(); sr; sr--, ev++) { // eventlog(eventlog_level_trace, __FUNCTION__, "checking %d ident: %d read: %d write: %d", i, kqevents[i].ident, kqevents[i].filter & EVFILT_READ, kqevents[i].filter & EVFILT_WRITE); t_fdwatch_fd *cfd = fdw_fds + ev->data.fd; if (fdw_rw(cfd) & fdwatch_type_read && ev->events & (EPOLLIN | EPOLLERR | EPOLLHUP)) if (fdw_hnd(cfd) (fdw_data(cfd), fdwatch_type_read) == -2) continue; if (fdw_rw(cfd) & fdwatch_type_write && ev->events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) fdw_hnd(cfd) (fdw_data(cfd), fdwatch_type_write); } sr = 0; }
extern int fdwatch_update_fd(int idx, unsigned rw) { if (idx < 0 || idx >= fdw_maxcons) { ERROR2("out of bounds idx [{}] (max: {})", idx, fdw_maxcons); return -1; } /* do not allow completly reset the access because then backend codes * can get confused */ if (!rw) { ERROR0("tried to reset rw, not allowed"); return -1; } if (!fdw_rw(fdw_fds + idx)) { ERROR0("found reseted rw"); return -1; } if (fdw->add(idx, rw)) return -1; fdw_rw(&fdw_fds[idx]) = rw; return 0; }
int FDWEpollBackend::del(int idx) { // eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d", fd); if (sr > 0) ERROR0("BUG: called while still handling sockets"); if (fdw_rw(fdw_fds + idx)) { struct epoll_event tmpev; std::memset(&tmpev, 0, sizeof(tmpev)); tmpev.events = 0; tmpev.data.fd = idx; if (epoll_ctl(epfd, EPOLL_CTL_DEL, fdw_fd(fdw_fds + idx), &tmpev)) { ERROR0("got error from epoll_ctl()"); return -1; } } return 0; }
extern int fdwatch_add_fd(int fd, unsigned rw, fdwatch_handler h, void *data) { /* max sockets reached */ if (freelist.empty()) return -1; t_fdwatch_fd *cfd = &freelist.front(); fdw_fd(cfd) = fd; if (fdw->add(fdw_idx(cfd), rw)) return -1; /* add it to used sockets list, remove it from free list */ uselist.push_back(*cfd); freelist.remove(*cfd); fdw_rw(cfd) = rw; fdw_data(cfd) = data; fdw_hnd(cfd) = h; return fdw_idx(cfd); }
int FDWEpollBackend::add(int idx, unsigned rw) { // eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d rw: %d", fd, rw); struct epoll_event tmpev; std::memset(&tmpev, 0, sizeof(tmpev)); tmpev.events = 0; if (rw & fdwatch_type_read) tmpev.events |= EPOLLIN; if (rw & fdwatch_type_write) tmpev.events |= EPOLLOUT; int op = fdw_rw(fdw_fds + idx) ? EPOLL_CTL_MOD : EPOLL_CTL_ADD; tmpev.data.fd = idx; if (epoll_ctl(epfd, op, fdw_fd(fdw_fds + idx), &tmpev)) { ERROR0("got error from epoll_ctl()"); return -1; } return 0; }
int FDWKqueueBackend::add(int idx, unsigned rw) { int idxr; t_fdwatch_fd *cfd = fdw_fds + idx; /* eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d rw: %d", fd, rw); */ /* adding read event filter */ if (!(fdw_rw(cfd) & fdwatch_type_read) && rw & fdwatch_type_read) { if (rridx[idx] >= 0 && rridx[idx] < nochanges && kqchanges[rridx[idx]].ident == fdw_fd(cfd)) { idxr = rridx[idx]; /* eventlog(eventlog_level_trace, __FUNCTION__, "updating change event (read) fd on %d", ridx); */ } else { idxr = nochanges++; rridx[idx] = idxr; /* eventlog(eventlog_level_trace, __FUNCTION__, "adding new change event (read) fd on %d", ridx); */ } EV_SET(kqchanges.get() + idxr, fdw_fd(cfd), EVFILT_READ, EV_ADD, 0, 0, (void*)idx); } else if (fdw_rw(cfd) & fdwatch_type_read && !( rw & fdwatch_type_read)) { if (rridx[idx] >= 0 && rridx[idx] < nochanges && kqchanges[rridx[idx]].ident == fdw_fd(cfd)) { idxr = rridx[idx]; /* eventlog(eventlog_level_trace, __FUNCTION__, "updating change event (read) fd on %d", ridx); */ } else { idxr = nochanges++; rridx[idx] = idxr; /* eventlog(eventlog_level_trace, __FUNCTION__, "adding new change event (read) fd on %d", ridx); */ } EV_SET(kqchanges.get() + idxr, fdw_fd(cfd), EVFILT_READ, EV_DELETE, 0, 0, (void*)idx); } /* adding write event filter */ if (!(fdw_rw(cfd) & fdwatch_type_write) && rw & fdwatch_type_write) { if (wridx[idx] >= 0 && wridx[idx] < nochanges && kqchanges[wridx[idx]].ident == fdw_fd(cfd)) { idxr = wridx[idx]; /* eventlog(eventlog_level_trace, __FUNCTION__, "updating change event (write) fd on %d", ridx); */ } else { idxr = nochanges++; wridx[idx] = idxr; /* eventlog(eventlog_level_trace, __FUNCTION__, "adding new change event (write) fd on %d", ridx); */ } EV_SET(kqchanges.get() + idxr, fdw_fd(cfd), EVFILT_WRITE, EV_ADD, 0, 0, (void*)idx); } else if (fdw_rw(cfd) & fdwatch_type_write && !(rw & fdwatch_type_write)) { if (wridx[idx] >= 0 && wridx[idx] < nochanges && kqchanges[wridx[idx]].ident == fdw_fd(cfd)) { idxr = wridx[idx]; /* eventlog(eventlog_level_trace, __FUNCTION__, "updating change event (write) fd on %d", ridx); */ } else { idxr = nochanges++; wridx[idx] = idxr; /* eventlog(eventlog_level_trace, __FUNCTION__, "adding new change event (write) fd on %d", ridx); */ } EV_SET(kqchanges.get() + idxr, fdw_fd(cfd), EVFILT_WRITE, EV_DELETE, 0, 0, (void*)idx); } return 0; }
int FDWKqueueBackend::del(int idx) { /* eventlog(eventlog_level_trace, __FUNCTION__, "called fd: %d", fd); */ if (sr > 0) eventlog(eventlog_level_error, __FUNCTION__, "BUG: called while still handling sockets"); t_fdwatch_fd *cfd = fdw_fds + idx; /* the last event changes about this fd has not yet been sent to kernel */ if (fdw_rw(cfd) & fdwatch_type_read && nochanges && rridx[idx] >= 0 && rridx[idx] < nochanges && kqchanges[rridx[idx]].ident == fdw_fd(cfd)) { nochanges--; if (rridx[idx] < nochanges) { int oidx; oidx = (unsigned long)(kqchanges[nochanges].udata); if (kqchanges[nochanges].filter == EVFILT_READ && rridx[oidx] == nochanges) { /* eventlog(eventlog_level_trace, __FUNCTION__, "not last, moving %d", kqchanges[rnfds].ident); */ rridx[oidx] = rridx[idx]; std::memcpy(kqchanges.get() + rridx[idx], kqchanges.get() + nochanges, sizeof(struct kevent)); } if (kqchanges[nochanges].filter == EVFILT_WRITE && wridx[oidx] == nochanges) { /* eventlog(eventlog_level_trace, __FUNCTION__, "not last, moving %d", kqchanges[rnfds].ident); */ wridx[oidx] = rridx[idx]; std::memcpy(kqchanges.get() + rridx[idx], kqchanges.get() + nochanges, sizeof(struct kevent)); } } rridx[idx] = -1; } if (fdw_rw(cfd) & fdwatch_type_write && nochanges && wridx[idx] >= 0 && wridx[idx] < nochanges && kqchanges[wridx[idx]].ident == fdw_fd(cfd)) { nochanges--; if (wridx[idx] < nochanges) { int oidx; oidx = (unsigned long)(kqchanges[nochanges].udata); if (kqchanges[nochanges].filter == EVFILT_READ && rridx[oidx] == nochanges) { /* eventlog(eventlog_level_trace, __FUNCTION__, "not last, moving %d", kqchanges[rnfds].ident); */ rridx[oidx] = wridx[idx]; std::memcpy(kqchanges.get() + wridx[idx], kqchanges.get() + nochanges, sizeof(struct kevent)); } if (kqchanges[nochanges].filter == EVFILT_WRITE && wridx[oidx] == nochanges) { /* eventlog(eventlog_level_trace, __FUNCTION__, "not last, moving %d", kqchanges[rnfds].ident); */ wridx[oidx] = wridx[idx]; std::memcpy(kqchanges.get() + wridx[idx], kqchanges.get() + nochanges, sizeof(struct kevent)); } } wridx[idx] = -1; } /* here we presume the calling code does close() on the socket and if so * it is automatically removed from any kernel kqueues */ return 0; }