+ return 0;
+}
+
+static void
+vcl_epoll_wait_handle_lt (vcl_worker_t *wrk, struct epoll_event *events,
+ int maxevents, u32 *n_evts)
+{
+ u32 add_event = 0, evt_flags = 0, next, *to_remove = 0, *si;
+ vcl_session_t *s;
+ u64 evt_data;
+ int rv;
+
+ ASSERT (wrk->ep_lt_current != VCL_INVALID_SESSION_INDEX);
+ if (*n_evts >= maxevents)
+ return;
+
+ next = wrk->ep_lt_current;
+ do
+ {
+ s = vcl_session_get (wrk, next);
+ next = s->vep.lt_next;
+
+ if (s->vep.ev.events == 0)
+ {
+ vec_add1 (to_remove, s->session_index);
+ continue;
+ }
+ if ((s->vep.ev.events & EPOLLIN) && (rv = vcl_session_read_ready (s)))
+ {
+ add_event = 1;
+ evt_flags |= rv > 0 ? EPOLLIN : EPOLLHUP | EPOLLRDHUP;
+ evt_data = s->vep.ev.data.u64;
+ }
+ if ((s->vep.ev.events & EPOLLOUT) && (rv = vcl_session_write_ready (s)))
+ {
+ add_event = 1;
+ evt_flags |= rv > 0 ? EPOLLOUT : EPOLLHUP | EPOLLRDHUP;
+ evt_data = s->vep.ev.data.u64;
+ }
+ if (!add_event && s->session_state > VCL_STATE_READY)
+ {
+ add_event = 1;
+ evt_flags |= EPOLLHUP | EPOLLRDHUP;
+ evt_data = s->vep.ev.data.u64;
+ }
+ if (add_event)
+ {
+ events[*n_evts].events = evt_flags;
+ events[*n_evts].data.u64 = evt_data;
+ if (EPOLLONESHOT & s->vep.ev.events)
+ s->vep.ev.events = EPOLLHUP | EPOLLERR;
+ if (evt_flags & EPOLLHUP)
+ s->vep.ev.events = 0;
+ *n_evts += 1;
+ add_event = 0;
+ evt_flags = 0;
+ if (*n_evts == maxevents)
+ {
+ wrk->ep_lt_current = next;
+ break;
+ }
+ }
+ else
+ {
+ vec_add1 (to_remove, s->session_index);
+ }
+ }
+ while (next != wrk->ep_lt_current);
+
+ vec_foreach (si, to_remove)
+ {
+ s = vcl_session_get (wrk, *si);
+ vcl_epoll_lt_del (wrk, s);
+ }
+ vec_free (to_remove);