[master] 39e2405 improve the vbm facility, rename former vbit_init to vbit_new
Nils Goroll
nils.goroll at uplex.de
Thu Mar 3 14:46:00 CET 2016
commit 39e2405bb04317c893726f38d43676570a1bdf1a
Author: Nils Goroll <nils.goroll at uplex.de>
Date: Thu Mar 3 14:35:28 2016 +0100
improve the vbm facility, rename former vbit_init to vbit_new
vbit_init now initializes a vbitmap from an arbitrary memory extent.
If more bits are used than the extent provided, auto-sizing falls
back to malloc, so vbit_destroy() should still be used.
adding a test program
diff --git a/.gitignore b/.gitignore
index 0cfaa04..fb9cde6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -57,6 +57,9 @@ cscope.*out
/include/tbl/vrt_stv_var.h
/include/tbl/vcc_types.h
/include/vcs_version.h
+/include/vbm_test
+/include/vbm_test.log
+/include/test-suite.log
/lib/libvcc/vcc_fixed_token.c
/lib/libvcc/vcc_obj.c
/lib/libvcc/vcc_token_defs.h
diff --git a/bin/varnishd/mgt/mgt_child.c b/bin/varnishd/mgt/mgt_child.c
index 1673169..3aee527 100644
--- a/bin/varnishd/mgt/mgt_child.c
+++ b/bin/varnishd/mgt/mgt_child.c
@@ -206,7 +206,7 @@ mgt_child_inherit(int fd, const char *what)
assert(fd >= 0);
if (fd_map == NULL)
- fd_map = vbit_init(128);
+ fd_map = vbit_new(128);
AN(fd_map);
if (what != NULL)
vbit_set(fd_map, fd);
diff --git a/include/Makefile.am b/include/Makefile.am
index ced33c8..816e416 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -152,3 +152,12 @@ CLEANFILES = \
vcl.h \
vrt_obj.h \
vmod_abi.h
+
+TESTS = vbm_test
+
+noinst_PROGRAMS = ${TESTS}
+
+vbm_test_SOURCES = vbm_test.c vbm.h
+
+test: ${TESTS}
+ @for test in ${TESTS} ; do ./$${test} ; done
diff --git a/include/vbm.h b/include/vbm.h
index 984a3ea..94497ab 100644
--- a/include/vbm.h
+++ b/include/vbm.h
@@ -29,17 +29,33 @@
* Self-sizeing bitmap operations
*/
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
/**********************************************************************
- * Generic bitmap functions, may be generalized at some point.
+ * Generic bitmap functions
*/
#define VBITMAP_TYPE unsigned /* Our preferred wordsize */
#define VBITMAP_LUMP (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))
+#define VBITMAP_IDX(n) ((n) / VBITMAP_WORD)
+#define VBITMAP_BIT(n) (1U << ((n) % VBITMAP_WORD))
+
+static inline unsigned
+vbit_rndup(unsigned bit, unsigned to) {
+ bit += to - 1;
+ bit -= (bit % to);
+
+ return (bit);
+}
struct vbitmap {
+ unsigned flags;
+#define VBITMAP_FL_MALLOC 1 /* struct vbitmap is malloced */
+#define VBITMAP_FL_MALLOC_BITS (1<<1) /* bits space is malloced */
+
VBITMAP_TYPE *bits;
unsigned nbits;
};
@@ -49,22 +65,64 @@ vbit_expand(struct vbitmap *vb, unsigned bit)
{
unsigned char *p;
- bit += VBITMAP_LUMP - 1;
- bit -= (bit % VBITMAP_LUMP);
- p = realloc(vb->bits, bit / 8);
- assert(p != NULL);
+ bit = vbit_rndup(bit, VBITMAP_LUMP);
+ assert(bit > vb->nbits);
+
+ if (vb->flags & VBITMAP_FL_MALLOC_BITS) {
+ p = realloc(vb->bits, bit / 8);
+ assert(p != NULL);
+ } else {
+ p = malloc(bit / 8);
+ assert(p != NULL);
+ if (vb->nbits > 0)
+ memcpy(p, vb->bits, vb->nbits / 8);
+ }
memset(p + vb->nbits / 8, 0, (bit - vb->nbits) / 8);
+ vb->flags |= VBITMAP_FL_MALLOC_BITS;
vb->bits = (void*)p;
vb->nbits = bit;
}
+#define VBITMAP_SZ(b) (sizeof(struct vbitmap) + \
+ vbit_rndup(b, VBITMAP_WORD))
+
+/*
+ * init from some extent of memory (e.g. workspace) which the caller must
+ * manage. Returns a vbitmap with as many bits as fit into sz in VBITMAP_WORD
+ * chunks.
+ *
+ * use VBITMAP_SZ to calculate sz
+ */
+static inline struct vbitmap *
+vbit_init(void *p, size_t sz)
+{
+ struct vbitmap *vb;
+
+ if (sz < sizeof(*vb))
+ return NULL;
+
+ memset(p, 0, sz);
+ vb = p;
+
+ p = (char *)p + sizeof(*vb);
+ sz -= sizeof(*vb);
+
+ vb->nbits = (sz / VBITMAP_WORD) * VBITMAP_WORD;
+ if (vb->nbits)
+ vb->bits = p;
+
+ return (vb);
+}
+
+/* init using malloc */
static inline struct vbitmap *
-vbit_init(unsigned initial)
+vbit_new(unsigned initial)
{
struct vbitmap *vb;
vb = calloc(sizeof *vb, 1);
assert(vb != NULL);
+ vb->flags |= VBITMAP_FL_MALLOC;
if (initial == 0)
initial = VBITMAP_LUMP;
vbit_expand(vb, initial);
@@ -77,8 +135,13 @@ vbit_destroy(struct vbitmap *vb)
if (vb == NULL)
return;
- free(vb->bits);
- free(vb);
+ if (vb->flags & VBITMAP_FL_MALLOC_BITS) {
+ free(vb->bits);
+ vb->bits = NULL;
+ vb->nbits = 0;
+ }
+ if (vb->flags & VBITMAP_FL_MALLOC)
+ free(vb);
}
static inline void
diff --git a/include/vbm_test.c b/include/vbm_test.c
new file mode 100644
index 0000000..f680597
--- /dev/null
+++ b/include/vbm_test.c
@@ -0,0 +1,92 @@
+/*-
+ * Copyright 2016 UPLEX - Nils Goroll Systemoptimierung
+ * All rights reserved.
+ *
+ * Author: Nils Goroll <nils.goroll at uplex.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Test Self-sizeing bitmap operations static initialization with dynamic growth
+ */
+
+#include <assert.h>
+#include <stdio.h>
+
+#include "vbm.h"
+
+int
+main(void)
+{
+
+ const unsigned sz = VBITMAP_SZ(1);
+ char spc[sz];
+ struct vbitmap *vb = vbit_init(spc, sz);
+
+ VBITMAP_TYPE *obits;
+ unsigned nbits;
+
+ assert(vb);
+ obits = vb->bits;
+ nbits = vb->nbits;
+ assert(nbits == VBITMAP_WORD);
+
+ vbit_set(vb, nbits - 1);
+ assert(vbit_test(vb, nbits - 1));
+
+ assert(vb->bits);
+ /* nothing malloc'ed - null ops */
+ vbit_destroy(vb);
+ assert(vb->bits);
+ assert(vb->bits == obits);
+
+ /* re-alloc */
+ vbit_set(vb, nbits);
+ assert(vbit_test(vb, nbits - 1));
+ assert(vbit_test(vb, nbits));
+ assert(vb->nbits == VBITMAP_LUMP);
+ assert(vb->bits != obits);
+ assert(vb->flags & VBITMAP_FL_MALLOC_BITS);
+
+ assert(vb->bits);
+ /* free the bits */
+ vbit_destroy(vb);
+ assert(vb->bits == NULL);
+ assert(vb->nbits == 0);
+
+ /* use again */
+ assert(20 < VBITMAP_LUMP);
+ vbit_set(vb, 20);
+ assert(vbit_test(vb, 20));
+ assert(vb->nbits == VBITMAP_LUMP);
+ assert(vb->flags & VBITMAP_FL_MALLOC_BITS);
+
+ /* grow */
+ vbit_set(vb, VBITMAP_LUMP);
+ assert(vbit_test(vb, 20));
+ assert(vbit_test(vb, VBITMAP_LUMP));
+ assert(vb->nbits == 2 * VBITMAP_LUMP);
+ assert(vb->flags & VBITMAP_FL_MALLOC_BITS);
+
+ vbit_destroy(vb);
+
+ return (0);
+}
diff --git a/lib/libvarnishapi/vsl.c b/lib/libvarnishapi/vsl.c
index 2bd801c..1efc453 100644
--- a/lib/libvarnishapi/vsl.c
+++ b/lib/libvarnishapi/vsl.c
@@ -101,8 +101,8 @@ VSL_New(void)
vsl->L_opt = 1000;
vsl->T_opt = 120.;
- vsl->vbm_select = vbit_init(SLT__MAX);
- vsl->vbm_supress = vbit_init(SLT__MAX);
+ vsl->vbm_select = vbit_new(SLT__MAX);
+ vsl->vbm_supress = vbit_new(SLT__MAX);
VTAILQ_INIT(&vsl->vslf_select);
VTAILQ_INIT(&vsl->vslf_suppress);
diff --git a/lib/libvarnishapi/vsl_arg.c b/lib/libvarnishapi/vsl_arg.c
index cc14e94..89ab29d 100644
--- a/lib/libvarnishapi/vsl_arg.c
+++ b/lib/libvarnishapi/vsl_arg.c
@@ -270,7 +270,7 @@ vsl_IX_arg(struct VSL_data *vsl, int opt, const char *arg)
b = arg;
e = strchr(b, ':');
if (e) {
- tags = vbit_init(SLT__MAX);
+ tags = vbit_new(SLT__MAX);
AN(tags);
l = e - b;
i = VSL_List2Tags(b, l, vsl_vbm_bitset, tags);
diff --git a/lib/libvarnishapi/vxp_parse.c b/lib/libvarnishapi/vxp_parse.c
index 7ec8865..7ec0d4f 100644
--- a/lib/libvarnishapi/vxp_parse.c
+++ b/lib/libvarnishapi/vxp_parse.c
@@ -75,7 +75,7 @@ vxp_expr_lhs(struct vxp *vxp, struct vex_lhs **plhs)
AZ(*plhs);
ALLOC_OBJ(*plhs, VEX_LHS_MAGIC);
AN(*plhs);
- (*plhs)->tags = vbit_init(SLT__MAX);
+ (*plhs)->tags = vbit_new(SLT__MAX);
(*plhs)->level = -1;
if (vxp->t->tok == '{') {
diff --git a/lib/libvmod_directors/vdir.c b/lib/libvmod_directors/vdir.c
index 22dfee3..15dd56a 100644
--- a/lib/libvmod_directors/vdir.c
+++ b/lib/libvmod_directors/vdir.c
@@ -72,7 +72,7 @@ vdir_new(struct vdir **vdp, const char *name, const char *vcl_name,
vd->dir->priv = priv;
vd->dir->healthy = healthy;
vd->dir->resolve = resolve;
- vd->vbm = vbit_init(8);
+ vd->vbm = vbit_new(8);
AN(vd->vbm);
}
More information about the varnish-commit
mailing list