[master] 27bab72 Update and reenable epoll(2) waiter to new reality.
Poul-Henning Kamp
phk at FreeBSD.org
Thu May 21 22:43:49 CEST 2015
commit 27bab7228eab7872c4248f91cae2587178cd7aff
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Thu May 21 20:43:07 2015 +0000
Update and reenable epoll(2) waiter to new reality.
diff --git a/bin/varnishd/waiter/cache_waiter_epoll.c b/bin/varnishd/waiter/cache_waiter_epoll.c
index 2e85b87..0452fe9 100644
--- a/bin/varnishd/waiter/cache_waiter_epoll.c
+++ b/bin/varnishd/waiter/cache_waiter_epoll.c
@@ -31,7 +31,6 @@
* write the session pointer to a pipe which the event engine monitors.
*/
-#if 0
#include "config.h"
#if defined(HAVE_EPOLL_CTL)
@@ -56,44 +55,29 @@
struct vwe {
unsigned magic;
#define VWE_MAGIC 0x6bd73424
+ int epfd;
struct waiter *waiter;
-
pthread_t thread;
- int epfd;
+ VTAILQ_HEAD(,waited) list;
+ struct lock mtx;
+ int die;
};
static void
-vwe_inject(const struct waiter *w, struct waited *wp)
-{
- struct vwe *vwe;
- struct epoll_event ev;
-
- CAST_OBJ_NOTNULL(vwe, w->priv, VWE_MAGIC);
- CHECK_OBJ_NOTNULL(wp, WAITED_MAGIC);
- assert(wp->fd >= 0);
-
- ev.data.ptr = wp;
- ev.events = EPOLLIN | EPOLLRDHUP;
- AZ(epoll_ctl(vwe->epfd, EPOLL_CTL_ADD, wp->fd, &ev));
-}
-
-static void
vwe_eev(struct vwe *vwe, const struct epoll_event *ep, double now)
{
struct waited *wp;
AN(ep->data.ptr);
CAST_OBJ_NOTNULL(wp, ep->data.ptr, WAITED_MAGIC);
- if (wp != vwe->waiter->pipe_w)
- AZ(epoll_ctl(vwe->epfd, EPOLL_CTL_DEL, wp->fd, NULL));
if (ep->events & EPOLLIN) {
- Wait_Handle(vwe->waiter, wp, WAITER_ACTION, now);
+ vwe->waiter->func(wp, WAITER_ACTION, now);
} else if (ep->events & EPOLLERR) {
- Wait_Handle(vwe->waiter, wp, WAITER_REMCLOSE, now);
+ vwe->waiter->func(wp, WAITER_REMCLOSE, now);
} else if (ep->events & EPOLLHUP) {
- Wait_Handle(vwe->waiter, wp, WAITER_REMCLOSE, now);
+ vwe->waiter->func(wp, WAITER_REMCLOSE, now);
} else if (ep->events & EPOLLRDHUP) {
- Wait_Handle(vwe->waiter, wp, WAITER_REMCLOSE, now);
+ vwe->waiter->func(wp, WAITER_REMCLOSE, now);
}
}
@@ -103,26 +87,77 @@ static void *
vwe_thread(void *priv)
{
struct epoll_event ev[NEEV], *ep;
- double now;
+ struct waited *wp, *wp2;
+ double now, idle, last_idle;
int i, n;
struct vwe *vwe;
+ VTAILQ_HEAD(,waited) tlist;
CAST_OBJ_NOTNULL(vwe, priv, VWE_MAGIC);
THR_SetName("cache-epoll");
- while (!vwe->waiter->dismantle) {
- n = epoll_wait(vwe->epfd, ev, NEEV, -1);
+ last_idle = 0.0;
+ while (1) {
+ i = floor(.3 * 1e3 * *vwe->waiter->tmo);
+ n = epoll_wait(vwe->epfd, ev, NEEV, i);
+ if (n < 0 && vwe->die)
+ break;
+ assert(n >= 0);
now = VTIM_real();
- for (ep = ev, i = 0; i < n; i++, ep++)
+ for (ep = ev, i = 0; i < n; i++, ep++) {
+ CAST_OBJ_NOTNULL(wp, ep->data.ptr, WAITED_MAGIC);
+ AZ(epoll_ctl(vwe->epfd, EPOLL_CTL_DEL, wp->fd, NULL));
+ Lck_Lock(&vwe->mtx);
+ VTAILQ_REMOVE(&vwe->list, wp, list);
+ Lck_Unlock(&vwe->mtx);
vwe_eev(vwe, ep, now);
- Wait_Handle(vwe->waiter, NULL, WAITER_ACTION, now);
+ }
+ idle = now - *vwe->waiter->tmo;
+ if (now - last_idle < .3 * *vwe->waiter->tmo)
+ continue;
+ last_idle = now;
+ VTAILQ_INIT(&tlist);
+ Lck_Lock(&vwe->mtx);
+ VTAILQ_FOREACH_SAFE(wp, &vwe->list, list, wp2) {
+ if (wp->idle > idle)
+ continue;
+ VTAILQ_REMOVE(&vwe->list, wp, list);
+ VTAILQ_INSERT_TAIL(&tlist, wp, list);
+ AZ(epoll_ctl(vwe->epfd, EPOLL_CTL_DEL, wp->fd, NULL));
+ }
+ Lck_Unlock(&vwe->mtx);
+ while(1) {
+ wp = VTAILQ_FIRST(&tlist);
+ if (wp == NULL)
+ break;
+ VTAILQ_REMOVE(&tlist, wp, list);
+ vwe->waiter->func(wp, WAITER_TIMEOUT, now);
+ }
}
return (NULL);
}
/*--------------------------------------------------------------------*/
+static int __match_proto__(waiter_enter_f)
+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);
+ VTAILQ_INSERT_TAIL(&vwe->list, wp, list);
+ AZ(epoll_ctl(vwe->epfd, EPOLL_CTL_ADD, wp->fd, &ee));
+ Lck_Unlock(&vwe->mtx);
+ return(0);
+}
+
+/*--------------------------------------------------------------------*/
+
static void __match_proto__(waiter_init_f)
vwe_init(struct waiter *w)
{
@@ -135,24 +170,39 @@ vwe_init(struct waiter *w)
vwe->epfd = epoll_create(1);
assert(vwe->epfd >= 0);
-
- Wait_UsePipe(w);
+ VTAILQ_INIT(&vwe->list);
+ Lck_New(&vwe->mtx, lck_misc);
AZ(pthread_create(&vwe->thread, NULL, vwe_thread, vwe));
}
-/*--------------------------------------------------------------------*/
+/*--------------------------------------------------------------------
+ * It is the callers responsibility to trigger all fd's waited on to
+ * fail somehow.
+ */
static void __match_proto__(waiter_fini_f)
vwe_fini(struct waiter *w)
{
struct vwe *vwe;
void *vp;
+ int i;
CAST_OBJ_NOTNULL(vwe, w->priv, VWE_MAGIC);
+ Lck_Lock(&vwe->mtx);
+ while (!VTAILQ_EMPTY(&vwe->list)) {
+ Lck_Unlock(&vwe->mtx);
+ (void)usleep(100000);
+ Lck_Lock(&vwe->mtx);
+ }
+ vwe->die = 1;
+ i = vwe->epfd;
+ vwe->epfd = -1;
+ AZ(close(i));
+ Lck_Unlock(&vwe->mtx);
AZ(pthread_join(vwe->thread, &vp));
- AZ(close(vwe->epfd));
+ Lck_Delete(&vwe->mtx);
}
/*--------------------------------------------------------------------*/
@@ -161,9 +211,8 @@ const struct waiter_impl waiter_epoll = {
.name = "epoll",
.init = vwe_init,
.fini = vwe_fini,
- .inject = vwe_inject,
+ .enter = vwe_enter,
.size = sizeof(struct vwe),
};
#endif /* defined(HAVE_EPOLL_CTL) */
-#endif
diff --git a/bin/varnishd/waiter/mgt_waiter.c b/bin/varnishd/waiter/mgt_waiter.c
index 52a380f..3f344fd 100644
--- a/bin/varnishd/waiter/mgt_waiter.c
+++ b/bin/varnishd/waiter/mgt_waiter.c
@@ -42,10 +42,10 @@ static const struct waiter_impl *const waiter_impls[] = {
#if defined(HAVE_KQUEUE)
&waiter_kqueue,
#endif
-#if 0
#if defined(HAVE_EPOLL_CTL)
&waiter_epoll,
#endif
+#if 0
#if defined(HAVE_PORT_CREATE)
&waiter_ports,
#endif
More information about the varnish-commit
mailing list