int tvhpoll_add ( tvhpoll_t *tp, tvhpoll_event_t *evs, size_t num ) { #if ENABLE_EPOLL int i; struct epoll_event ev; for (i = 0; i < num; i++) { memset(&ev, 0, sizeof(ev)); ev.data.u64 = evs[i].data.u64; if (evs[i].events & TVHPOLL_IN) ev.events |= EPOLLIN; if (evs[i].events & TVHPOLL_OUT) ev.events |= EPOLLOUT; if (evs[i].events & TVHPOLL_PRI) ev.events |= EPOLLPRI; if (evs[i].events & TVHPOLL_ERR) ev.events |= EPOLLERR; if (evs[i].events & TVHPOLL_HUP) ev.events |= EPOLLHUP; if (epoll_ctl(tp->fd, EPOLL_CTL_ADD, evs[i].fd, &ev) != 0) return -1; } return 0; #elif ENABLE_KQUEUE int i; uint32_t fflags; tvhpoll_alloc(tp, num); for (i = 0; i < num; i++) { fflags = 0; if (evs[i].events & TVHPOLL_OUT) fflags |= EVFILT_WRITE; if (evs[i].events & TVHPOLL_IN) fflags |= EVFILT_READ; EV_SET(tp->ev+i, evs[i].fd, fflags, EV_ADD, 0, 0, (void*)evs[i].data.u64); } return kevent(tp->fd, tp->ev, num, NULL, 0, NULL); #else #endif }
int tvhpoll_add ( tvhpoll_t *tp, tvhpoll_event_t *evs, size_t num ) { int i, rc; #if ENABLE_EPOLL struct epoll_event ev; for (i = 0; i < num; i++) { memset(&ev, 0, sizeof(ev)); ev.data.u64 = evs[i].data.u64; if (evs[i].events & TVHPOLL_IN) ev.events |= EPOLLIN; if (evs[i].events & TVHPOLL_OUT) ev.events |= EPOLLOUT; if (evs[i].events & TVHPOLL_PRI) ev.events |= EPOLLPRI; if (evs[i].events & TVHPOLL_ERR) ev.events |= EPOLLERR; if (evs[i].events & TVHPOLL_HUP) ev.events |= EPOLLHUP; rc = epoll_ctl(tp->fd, EPOLL_CTL_ADD, evs[i].fd, &ev); if (rc && errno == EEXIST) { if (epoll_ctl(tp->fd, EPOLL_CTL_MOD, evs[i].fd, &ev)) return -1; } } return 0; #elif ENABLE_KQUEUE tvhpoll_alloc(tp, num); for (i = 0; i < num; i++) { if (evs[i].events & TVHPOLL_OUT){ EV_SET(tp->ev+i, evs[i].fd, EVFILT_WRITE, EV_ADD, 0, 0, (intptr_t*)evs[i].data.u64); rc = kevent(tp->fd, tp->ev+i, 1, NULL, 0, NULL); if (rc == -1) { tvhlog(LOG_ERR, "tvhpoll", "failed to add kqueue WRITE filter [%d|%d]", evs[i].fd, rc); return -1; } } if (evs[i].events & TVHPOLL_IN){ EV_SET(tp->ev+i, evs[i].fd, EVFILT_READ, EV_ADD, 0, 0, (intptr_t*)evs[i].data.u64); rc = kevent(tp->fd, tp->ev+i, 1, NULL, 0, NULL); if (rc == -1) { tvhlog(LOG_ERR, "tvhpoll", "failed to add kqueue READ filter [%d|%d]", evs[i].fd, rc); return -1; } } } return 0; #else return -1; #endif }
int tvhpoll_rem ( tvhpoll_t *tp, tvhpoll_event_t *evs, size_t num ) { tvhpoll_alloc(tp, num); #if ENABLE_EPOLL int i; for (i = 0; i < num; i++) epoll_ctl(tp->fd, EPOLL_CTL_DEL, evs[i].fd, NULL); #elif ENABLE_KQUEUE int i; for (i = 0; i < num; i++) EV_SET(tp->ev+i, evs[i].fd, 0, EV_DELETE, 0, 0, NULL); kevent(tp->fd, tp->ev, num, NULL, 0, NULL); #else #endif return 0; }
tvhpoll_t * tvhpoll_create ( size_t n ) { int fd; #if ENABLE_EPOLL if ((fd = epoll_create(n)) < 0) { tvhlog(LOG_ERR, "tvhpoll", "failed to create epoll [%s]", strerror(errno)); return NULL; } #elif ENABLE_KQUEUE if ((fd = kqueue()) == -1) { tvhlog(LOG_ERR, "tvhpoll", "failed to create kqueue [%s]", strerror(errno)); return NULL; } #else #endif tvhpoll_t *tp = calloc(1, sizeof(tvhpoll_t)); tp->fd = fd; tvhpoll_alloc(tp, n); return tp; }
int tvhpoll_wait ( tvhpoll_t *tp, tvhpoll_event_t *evs, size_t num, int ms ) { int nfds = 0, i; tvhpoll_alloc(tp, num); #if ENABLE_EPOLL nfds = epoll_wait(tp->fd, tp->ev, num, ms); for (i = 0; i < nfds; i++) { evs[i].data.u64 = tp->ev[i].data.u64; evs[i].events = 0; if (tp->ev[i].events & EPOLLIN) evs[i].events |= TVHPOLL_IN; if (tp->ev[i].events & EPOLLOUT) evs[i].events |= TVHPOLL_OUT; if (tp->ev[i].events & EPOLLERR) evs[i].events |= TVHPOLL_ERR; if (tp->ev[i].events & EPOLLPRI) evs[i].events |= TVHPOLL_PRI; if (tp->ev[i].events & EPOLLHUP) evs[i].events |= TVHPOLL_HUP; } #elif ENABLE_KQUEUE struct timespec tm, *to = NULL; if (ms > 0) { tm.tv_sec = ms / 1000; tm.tv_nsec = (ms % 1000) * 1000000LL; to = &tm; } nfds = kevent(tp->fd, NULL, 0, tp->ev, num, to); for (i = 0; i < nfds; i++) { evs[i].fd = tp->ev[i].ident; evs[i].events = 0; evs[i].data.u64 = (intptr_t)tp->ev[i].udata; if (tp->ev[i].filter == EVFILT_WRITE) evs[i].events |= TVHPOLL_OUT; if (tp->ev[i].filter == EVFILT_READ) evs[i].events |= TVHPOLL_IN; if (tp->ev[i].flags & EV_ERROR) evs[i].events |= TVHPOLL_ERR; if (tp->ev[i].flags & EV_EOF) evs[i].events |= TVHPOLL_HUP; } #else #endif return nfds; }