static void * vwk_thread(void *priv) { struct vwk *vwk; struct kevent ke[NKEV], *kp; int j, n, dotimer; double deadline; struct sess *sp; CAST_OBJ_NOTNULL(vwk, priv, VWK_MAGIC); THR_SetName("cache-kqueue"); vwk->kq = kqueue(); assert(vwk->kq >= 0); j = 0; EV_SET(&ke[j], 0, EVFILT_TIMER, EV_ADD, 0, 100, NULL); j++; EV_SET(&ke[j], vwk->pipes[0], EVFILT_READ, EV_ADD, 0, 0, vwk->pipes); j++; AZ(kevent(vwk->kq, ke, j, NULL, 0, NULL)); vwk->nki = 0; while (1) { dotimer = 0; n = kevent(vwk->kq, vwk->ki, vwk->nki, ke, NKEV, NULL); assert(n >= 1 && n <= NKEV); vwk->nki = 0; for (kp = ke, j = 0; j < n; j++, kp++) { if (kp->filter == EVFILT_TIMER) { dotimer = 1; continue; } assert(kp->filter == EVFILT_READ); vwk_kev(vwk, kp); } if (!dotimer) continue; /* * Make sure we have no pending changes for the fd's * we are about to close, in case the accept(2) in the * other thread creates new fd's betwen our close and * the kevent(2) at the top of this loop, the kernel * would not know we meant "the old fd of this number". */ vwk_kq_flush(vwk); deadline = VTIM_real() - params->sess_timeout; for (;;) { sp = VTAILQ_FIRST(&vwk->sesshead); if (sp == NULL) break; if (sp->t_open > deadline) break; VTAILQ_REMOVE(&vwk->sesshead, sp, list); // XXX: not yet (void)VTCP_linger(sp->fd, 0); SES_Delete(sp, "timeout"); } } }
static void vwk_kq_sess(struct vwk *vwk, struct sess *sp, short arm) { CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); assert(sp->fd >= 0); DSL(DBG_WAITER, sp->vxid, "KQ: EV_SET sp %p arm %x", sp, arm); EV_SET(&vwk->ki[vwk->nki], sp->fd, EVFILT_READ, arm, 0, 0, sp); if (++vwk->nki == NKEV) vwk_kq_flush(vwk); }
static void * vwk_thread(void *priv) { struct vwk *vwk; struct kevent ke[NKEV], *kp; int j, n, dotimer; double now, deadline; struct sess *sp; CAST_OBJ_NOTNULL(vwk, priv, VWK_MAGIC); THR_SetName("cache-kqueue"); vwk->kq = kqueue(); assert(vwk->kq >= 0); j = 0; EV_SET(&ke[j], 0, EVFILT_TIMER, EV_ADD, 0, 100, NULL); j++; EV_SET(&ke[j], vwk->pipes[0], EVFILT_READ, EV_ADD, 0, 0, vwk->pipes); j++; AZ(kevent(vwk->kq, ke, j, NULL, 0, NULL)); vwk->nki = 0; while (1) { dotimer = 0; n = kevent(vwk->kq, vwk->ki, vwk->nki, ke, NKEV, NULL); now = VTIM_real(); assert(n <= NKEV); if (n == 0) { /* This happens on OSX in m00011.vtc */ dotimer = 1; (void)usleep(10000); } vwk->nki = 0; for (kp = ke, j = 0; j < n; j++, kp++) { if (kp->filter == EVFILT_TIMER) { dotimer = 1; } else if (kp->filter == EVFILT_READ && kp->udata == vwk->pipes) { vwk_pipe_ev(vwk, kp); } else { assert(kp->filter == EVFILT_READ); vwk_sess_ev(vwk, kp, now); } } if (!dotimer) continue; /* * Make sure we have no pending changes for the fd's * we are about to close, in case the accept(2) in the * other thread creates new fd's betwen our close and * the kevent(2) at the top of this loop, the kernel * would not know we meant "the old fd of this number". */ vwk_kq_flush(vwk); deadline = now - cache_param->timeout_idle; for (;;) { sp = VTAILQ_FIRST(&vwk->sesshead); if (sp == NULL) break; if (sp->t_idle > deadline) break; VTAILQ_REMOVE(&vwk->sesshead, sp, list); // XXX: not yet (void)VTCP_linger(sp->fd, 0); SES_Delete(sp, SC_RX_TIMEOUT, now); } } NEEDLESS_RETURN(NULL); }