Commit 39e2405b authored by Nils Goroll's avatar Nils Goroll

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
parent ba519f4d
......@@ -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
......
......@@ -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);
......
......@@ -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
......@@ -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
......
/*-
* Copyright 2016 UPLEX - Nils Goroll Systemoptimierung
* All rights reserved.
*
* Author: Nils Goroll <nils.goroll@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);
}
......@@ -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);
......
......@@ -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);
......
......@@ -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 == '{') {
......
......@@ -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);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment