static void * vwe_thread(void *priv) { struct epoll_event ev[NEEV], *ep; struct sess *sp; char junk; double now, deadline; int dotimer, i, n; struct vwe *vwe; CAST_OBJ_NOTNULL(vwe, priv, VWE_MAGIC); THR_SetName("cache-epoll"); vwe->epfd = epoll_create(1); assert(vwe->epfd >= 0); vwe_modadd(vwe, vwe->pipes[0], vwe->pipes, EPOLL_CTL_ADD); vwe_modadd(vwe, vwe->timer_pipes[0], vwe->timer_pipes, EPOLL_CTL_ADD); while (1) { dotimer = 0; n = epoll_wait(vwe->epfd, ev, NEEV, -1); now = VTIM_real(); for (ep = ev, i = 0; i < n; i++, ep++) { if (ep->data.ptr == vwe->timer_pipes && (ep->events == EPOLLIN || ep->events == EPOLLPRI)) { assert(read(vwe->timer_pipes[0], &junk, 1)); dotimer = 1; } else vwe_eev(vwe, ep, now); } if (!dotimer) continue; /* check for timeouts */ deadline = now - cache_param->timeout_idle; for (;;) { sp = VTAILQ_FIRST(&vwe->sesshead); if (sp == NULL) break; if (sp->t_idle > deadline) break; VTAILQ_REMOVE(&vwe->sesshead, sp, list); // XXX: not yet VTCP_linger(sp->fd, 0); SES_Delete(sp, SC_RX_TIMEOUT, now); } } return (NULL); }
static void vwe_eev(struct vwe *vwe, const struct epoll_event *ep) { struct sess *ss[NEEV], *sp; int i, j; AN(ep->data.ptr); if (ep->data.ptr == vwe->pipes) { if (ep->events & EPOLLIN || ep->events & EPOLLPRI) { j = 0; i = read(vwe->pipes[0], ss, sizeof ss); if (i == -1 && errno == EAGAIN) return; while (i >= sizeof ss[0]) { CHECK_OBJ_NOTNULL(ss[j], SESS_MAGIC); assert(ss[j]->fd >= 0); AZ(ss[j]->obj); VTAILQ_INSERT_TAIL(&vwe->sesshead, ss[j], list); vwe_cond_modadd(vwe, ss[j]->fd, ss[j]); j++; i -= sizeof ss[0]; } assert(i == 0); } } else { CAST_OBJ_NOTNULL(sp, ep->data.ptr, SESS_MAGIC); if (ep->events & EPOLLIN || ep->events & EPOLLPRI) { i = HTC_Rx(sp->htc); if (i == 0) { vwe_modadd(vwe, sp->fd, sp, EPOLL_CTL_MOD); return; /* more needed */ } VTAILQ_REMOVE(&vwe->sesshead, sp, list); SES_Handle(sp, i); } else if (ep->events & EPOLLERR) { VTAILQ_REMOVE(&vwe->sesshead, sp, list); SES_Delete(sp, "ERR"); } else if (ep->events & EPOLLHUP) { VTAILQ_REMOVE(&vwe->sesshead, sp, list); SES_Delete(sp, "HUP"); } else if (ep->events & EPOLLRDHUP) { VTAILQ_REMOVE(&vwe->sesshead, sp, list); SES_Delete(sp, "RHUP"); } } }