#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
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;
}
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++;
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",
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);
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);
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));
}