]> err.no Git - varnish/commitdiff
Use a bitmap to check if we own a given file handle, before we
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Tue, 20 Nov 2007 12:11:04 +0000 (12:11 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Tue, 20 Nov 2007 12:11:04 +0000 (12:11 +0000)
do anything about the associated session.

May be relevant relative to: #162

(Bitmap functions slightly general, for possible later reuse)

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@2267 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/bin/varnishd/cache_acceptor_kqueue.c

index 2e7ab013483b8ab72fbcbc55cbefb6d4e3d42d04..ed297cb2ea400c47735e12167a6b95eaa7c0e181 100644 (file)
@@ -36,6 +36,7 @@
 #if defined(HAVE_KQUEUE)
 
 #include <stdio.h>
+#include <string.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include "cache.h"
 #include "cache_acceptor.h"
 
+/**********************************************************************
+ * Generic bitmap functions, may be generalized at some point.
+ */
+
+#define VBITMAP_TYPE   unsigned        /* Our preferred wordsize */
+#define VBITMAP_LUMP   (32*1024)       /* How many bits we alloc at a time */
+#define VBITMAP_WORD   (sizeof(VBITMAP_TYPE) * 8)
+#define VBITMAP_IDX(n) (n / VBITMAP_WORD)
+#define VBITMAP_BIT(n) (1U << (n % VBITMAP_WORD))
+
+struct vbitmap {
+       VBITMAP_TYPE    *bits;
+       unsigned        nbits;
+};
+
+static void
+vbit_expand(struct vbitmap *vb, unsigned bit)
+{
+       unsigned char *p;
+
+       bit += VBITMAP_LUMP - 1;
+       bit -= (bit % VBITMAP_LUMP);
+       VSL(SLT_Debug, 0, "Expanding KQ VBIT to %u", bit);
+       p = realloc(vb->bits, bit / 8);
+       AN(p);
+       memset(p + vb->nbits / 8, 0, (bit - vb->nbits) / 8);
+       vb->bits = (void*)p;
+       vb->nbits = bit;
+}
+
+static struct vbitmap *
+vbit_init(unsigned initial)
+{
+       struct vbitmap *vb;
+
+       vb = calloc(sizeof *vb, 1);
+       AN(vb);
+       if (initial == 0)
+               initial = VBITMAP_LUMP;
+       vbit_expand(vb, initial);
+       return (vb);
+}
+
+static void
+vbit_set(struct vbitmap *vb, unsigned bit)
+{
+
+       if (bit >= vb->nbits)
+               vbit_expand(vb, bit);
+       vb->bits[VBITMAP_IDX(bit)] |= VBITMAP_BIT(bit);
+}
+
+static void
+vbit_clr(struct vbitmap *vb, unsigned bit)
+{
+
+       if (bit >= vb->nbits)
+               vbit_expand(vb, bit);
+       vb->bits[VBITMAP_IDX(bit)] &= ~VBITMAP_BIT(bit);
+}
+
+static int
+vbit_test(struct vbitmap *vb, unsigned bit)
+{
+
+       if (bit >= vb->nbits)
+               vbit_expand(vb, bit);
+       return (vb->bits[VBITMAP_IDX(bit)] & VBITMAP_BIT(bit));
+}
+
+/**********************************************************************/
+
+
 static pthread_t vca_kqueue_thread;
 static int kq = -1;
 
+struct vbitmap *vca_kqueue_bits;
+
 static VTAILQ_HEAD(,sess) sesshead = VTAILQ_HEAD_INITIALIZER(sesshead);
 
 #define NKEV   100
@@ -66,7 +142,7 @@ vca_kq_sess(struct sess *sp, short arm)
        if (sp->fd < 0)
                return;
        EV_SET(&ki[nki], sp->fd, EVFILT_READ, arm, 0, 0, sp);
-       if (++nki == NKEV || arm == EV_DELETE) {
+       if (++nki == NKEV) {
                AZ(kevent(kq, ki, nki, NULL, 0, NULL));
                nki = 0;
        }
@@ -89,6 +165,8 @@ vca_kev(const struct kevent *kp)
                        CHECK_OBJ_NOTNULL(ss[j], SESS_MAGIC);
                        assert(ss[j]->fd >= 0);
                        AZ(ss[j]->obj);
+                       AZ(vbit_test(vca_kqueue_bits, ss[j]->fd));
+                       vbit_set(vca_kqueue_bits, ss[j]->fd);
                        VTAILQ_INSERT_TAIL(&sesshead, ss[j], list);
                        vca_kq_sess(ss[j], EV_ADD);
                        j++;
@@ -97,6 +175,13 @@ vca_kev(const struct kevent *kp)
                assert(i == 0);
                return;
        }
+       if (!vbit_test(vca_kqueue_bits, kp->ident)) {
+               VSL(SLT_Debug, kp->ident,
+                   "KQ: not my fd %d, sp %p kev data %lu flags 0x%x%s",
+                   kp->ident, kp->udata, (unsigned long)kp->data, kp->flags,
+                   (kp->flags & EV_EOF) ? " EOF" : "");
+               return;
+       }
        CAST_OBJ_NOTNULL(sp, kp->udata, SESS_MAGIC);
 #ifdef DIAGNOSTICS
        VSL(SLT_Debug, sp->id, "sp %p kev data %lu flags 0x%x%s",
@@ -107,11 +192,13 @@ vca_kev(const struct kevent *kp)
                i = HTC_Rx(sp->htc);
                if (i == 0)
                        return; /* more needed */
+               vbit_clr(vca_kqueue_bits, sp->fd);
                VTAILQ_REMOVE(&sesshead, sp, list);
                vca_kq_sess(sp, EV_DELETE);
                vca_handover(sp, i);
                return;
        } else if (kp->flags == EV_EOF) {
+               vbit_clr(vca_kqueue_bits, sp->fd);
                VTAILQ_REMOVE(&sesshead, sp, list);
                vca_close_session(sp, "EOF");
                SES_Delete(sp);
@@ -164,6 +251,7 @@ vca_kqueue_main(void *arg)
                                break;
                        if (sp->t_open > deadline)
                                break;
+                       vbit_clr(vca_kqueue_bits, sp->fd);
                        VTAILQ_REMOVE(&sesshead, sp, list);
                        vca_close_session(sp, "timeout");
                        SES_Delete(sp);
@@ -182,6 +270,7 @@ vca_kqueue_init(void)
        i |= O_NONBLOCK;
        i = fcntl(vca_pipes[0], F_SETFL, i);
 
+       vca_kqueue_bits = vbit_init(0);
        AZ(pthread_create(&vca_kqueue_thread, NULL, vca_kqueue_main, NULL));
 }