waited_cmp(void *priv, const void *a, const void *b) { const struct waiter *ww; const struct waited *aa, *bb; CAST_OBJ_NOTNULL(ww, priv, WAITER_MAGIC); CAST_OBJ_NOTNULL(aa, a, WAITED_MAGIC); CAST_OBJ_NOTNULL(bb, b, WAITED_MAGIC); return (Wait_When(aa) < Wait_When(bb)); }
static void * vwp_main(void *priv) { int v; struct vwp *vwp; struct waiter *w; struct waited *wp; double now, then; int i; THR_SetName("cache-poll"); CAST_OBJ_NOTNULL(vwp, priv, VWP_MAGIC); w = vwp->waiter; while (1) { then = Wait_HeapDue(w, &wp); if (wp == NULL) i = -1; else i = (int)floor(1e3 * (then - VTIM_real())); assert(vwp->hpoll > 0); AN(vwp->pollfd); v = poll(vwp->pollfd, vwp->hpoll, i); assert(v >= 0); now = VTIM_real(); if (vwp->pollfd[0].revents) v--; for (i = 1; i < vwp->hpoll;) { VSL(SLT_Debug, vwp->pollfd[i].fd, "POLL loop i=%d revents=0x%x", i, vwp->pollfd[i].revents); assert(vwp->pollfd[i].fd != vwp->pipes[0]); wp = vwp->idx[i]; CHECK_OBJ_NOTNULL(wp, WAITED_MAGIC); if (v == 0 && Wait_HeapDue(w, NULL) > now) break; if (vwp->pollfd[i].revents) v--; then = Wait_When(wp); if (then <= now) { Wait_HeapDelete(w, wp); Wait_Call(w, wp, WAITER_TIMEOUT, now); vwp_del(vwp, i); } else if (vwp->pollfd[i].revents & POLLIN) { assert(wp->fd > 0); assert(wp->fd == vwp->pollfd[i].fd); Wait_HeapDelete(w, wp); Wait_Call(w, wp, WAITER_ACTION, now); vwp_del(vwp, i); } else { i++; } } if (vwp->pollfd[0].revents) vwp_dopipe(vwp); } NEEDLESS_RETURN(NULL); }
double Wait_HeapDue(const struct waiter *w, struct waited **wpp) { struct waited *wp; wp = binheap_root(w->heap); CHECK_OBJ_ORNULL(wp, WAITED_MAGIC); if (wp == NULL) { if (wpp != NULL) *wpp = NULL; return (0); } if (wpp != NULL) *wpp = wp; return(Wait_When(wp)); }
vwe_enter(void *priv, struct waited *wp) { struct vwe *vwe; struct epoll_event ee; CAST_OBJ_NOTNULL(vwe, priv, VWE_MAGIC); ee.events = EPOLLIN | EPOLLRDHUP; ee.data.ptr = wp; Lck_Lock(&vwe->mtx); vwe->nwaited++; Wait_HeapInsert(vwe->waiter, wp); AZ(epoll_ctl(vwe->epfd, EPOLL_CTL_ADD, wp->fd, &ee)); /* If the epoll isn't due before our timeout, poke it via the pipe */ if (Wait_When(wp) < vwe->next) assert(write(vwe->pipe[1], "X", 1) == 1); Lck_Unlock(&vwe->mtx); return(0); }