mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
regional.
git-svn-id: file:///svn/unbound/trunk@696 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
f768fc1148
commit
63bef95aac
5 changed files with 364 additions and 1 deletions
|
|
@ -10,6 +10,7 @@
|
|||
make download_ldns refreshes the tarball with ldns svn trunk.
|
||||
- ldns-src.tar.gz is used if no ldns is found on the system, and
|
||||
statically linked into unbound.
|
||||
- start of regional allocator code.
|
||||
|
||||
17 October 2007: Wouter
|
||||
- fixup another cycle detect and ns-addr timeout resolution bug.
|
||||
|
|
|
|||
|
|
@ -495,7 +495,8 @@ EXCLUDE = ./build \
|
|||
util/configparser.c \
|
||||
util/configparser.h \
|
||||
util/configlexer.c \
|
||||
util/locks.h
|
||||
util/locks.h \
|
||||
./ldns-src
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
|
||||
# directories that are symbolic links (a Unix filesystem feature) are excluded
|
||||
|
|
|
|||
BIN
testdata/01-doc.tpkg
vendored
BIN
testdata/01-doc.tpkg
vendored
Binary file not shown.
213
util/regional.c
Normal file
213
util/regional.c
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* regional.c -- region based memory allocator.
|
||||
*
|
||||
* Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE REGENTS 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Region allocator. Allocates small portions of of larger chunks.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "util/log.h"
|
||||
#include "util/regional.h"
|
||||
|
||||
#ifdef ALIGNMENT
|
||||
# undef ALIGNMENT
|
||||
#endif
|
||||
/** increase size until it fits alignment of s bytes */
|
||||
#define ALIGN_UP(x, s) (((x) + s - 1) & (~(s - 1)))
|
||||
/** what size to align on; make sure a char* fits in it. */
|
||||
#define ALIGNMENT (sizeof(uint64_t))
|
||||
|
||||
/** Default reasonable size for chunks */
|
||||
#define REGIONAL_CHUNK_SIZE 8192
|
||||
/** Default size for large objects - allocated outside of chunks. */
|
||||
#define REGIONAL_LARGE_OBJECT_SIZE 2048
|
||||
|
||||
struct regional*
|
||||
regional_create()
|
||||
{
|
||||
void *block = malloc(REGIONAL_CHUNK_SIZE);
|
||||
if(!block) return NULL;
|
||||
return regional_create_custom(block, REGIONAL_CHUNK_SIZE);
|
||||
}
|
||||
|
||||
/** init regional struct with first block */
|
||||
static void
|
||||
regional_init(struct regional* r)
|
||||
{
|
||||
r->next = NULL;
|
||||
r->size = r->first_size;
|
||||
r->allocated = ALIGN_UP(sizeof(struct regional), ALIGNMENT);
|
||||
r->data = (char*)r;
|
||||
r->total_large = 0;
|
||||
r->large_list = NULL;
|
||||
}
|
||||
|
||||
struct regional*
|
||||
regional_create_custom(void* block, size_t size)
|
||||
{
|
||||
struct regional* r = (struct regional*)block;
|
||||
log_assert(sizeof(struct regional) <= size);
|
||||
r->first_size = size;
|
||||
regional_init(r);
|
||||
return r;
|
||||
}
|
||||
|
||||
void
|
||||
regional_free_all(struct regional *r)
|
||||
{
|
||||
char* p = r->next, *np;
|
||||
while(p) {
|
||||
np = *(char**)p;
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
p = r->large_list;
|
||||
while(p) {
|
||||
np = *(char**)p;
|
||||
free(p);
|
||||
p = np;
|
||||
}
|
||||
regional_init(r);
|
||||
}
|
||||
|
||||
void
|
||||
regional_destroy(struct regional *r)
|
||||
{
|
||||
regional_free_all(r);
|
||||
free(r);
|
||||
}
|
||||
|
||||
void *
|
||||
regional_alloc(struct regional *r, size_t size)
|
||||
{
|
||||
size_t a = ALIGN_UP(size, ALIGNMENT);
|
||||
void *s;
|
||||
/* large objects */
|
||||
if(a > REGIONAL_LARGE_OBJECT_SIZE) {
|
||||
s = malloc(ALIGNMENT + size);
|
||||
if(!s) return NULL;
|
||||
r->total_large += ALIGNMENT+size;
|
||||
*(char**)s = r->large_list;
|
||||
r->large_list = (char*)s;
|
||||
return s+ALIGNMENT;
|
||||
}
|
||||
/* create a new chunk */
|
||||
if(r->allocated + a > r->size) {
|
||||
s = malloc(REGIONAL_CHUNK_SIZE);
|
||||
if(!s) return NULL;
|
||||
*(char**)s = r->data;
|
||||
r->data = s;
|
||||
r->allocated = ALIGNMENT;
|
||||
r->size = REGIONAL_CHUNK_SIZE;
|
||||
}
|
||||
/* put in this chunk */
|
||||
s = r->data + r->allocated;
|
||||
r->allocated += a;
|
||||
return s;
|
||||
}
|
||||
|
||||
void *
|
||||
regional_alloc_init(struct regional* r, const void *init, size_t size)
|
||||
{
|
||||
void *s = regional_alloc(r, size);
|
||||
if(!s)
|
||||
return NULL;
|
||||
memcpy(s, init, size);
|
||||
return s;
|
||||
}
|
||||
|
||||
void *
|
||||
regional_alloc_zero(struct regional *r, size_t size)
|
||||
{
|
||||
void *s = regional_alloc(r, size);
|
||||
if(!s)
|
||||
return NULL;
|
||||
memset(s, 0, size);
|
||||
return s;
|
||||
}
|
||||
|
||||
char *
|
||||
regional_strdup(struct regional *r, const char *string)
|
||||
{
|
||||
return regional_alloc_init(r, string, strlen(string)+1);
|
||||
}
|
||||
|
||||
/**
|
||||
* reasonably slow, but stats and get_mem are not supposed to be fast
|
||||
* count the number of chunks in use
|
||||
*/
|
||||
static size_t
|
||||
count_chunks(struct regional* r)
|
||||
{
|
||||
size_t c = 1;
|
||||
char* p = r->next;
|
||||
while(p) {
|
||||
c++;
|
||||
p = *(char**)p;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* also reasonably slow, counts the number of large objects
|
||||
*/
|
||||
static size_t
|
||||
count_large(struct regional* r)
|
||||
{
|
||||
size_t c = 0;
|
||||
char* p = r->large_list;
|
||||
while(p) {
|
||||
c++;
|
||||
p = *(char**)p;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
regional_log_stats(struct regional *r)
|
||||
{
|
||||
log_info("regional %u chunks, %u large",
|
||||
(unsigned)count_chunks(r), (unsigned)count_large(r));
|
||||
}
|
||||
|
||||
size_t
|
||||
regional_get_mem(struct regional* r)
|
||||
{
|
||||
return r->first_size + (count_chunks(r)-1)*REGIONAL_CHUNK_SIZE
|
||||
+ r->total_large;
|
||||
}
|
||||
148
util/regional.h
Normal file
148
util/regional.h
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* regional.h -- region based memory allocator.
|
||||
*
|
||||
* Copyright (c) 2007, NLnet Labs. All rights reserved.
|
||||
*
|
||||
* This software is open source.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* Neither the name of the NLNET LABS nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 THE REGENTS 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
* Region allocator. Allocates small portions of of larger chunks.
|
||||
*
|
||||
* Different from (nsd) region-allocator.h
|
||||
* o does not have recycle bin
|
||||
* o does not collect stats
|
||||
* o does not keep cleanup list
|
||||
* o does not have function pointers to setup
|
||||
* o allocs the regional struct inside the first block.
|
||||
* o can take a block to create regional from.
|
||||
*/
|
||||
|
||||
#ifndef UTIL_REGIONAL_H_
|
||||
#define UTIL_REGIONAL_H_
|
||||
|
||||
/**
|
||||
* the regional* is the first block*.
|
||||
* every block has a ptr to the next in first bytes.
|
||||
* and so does the regional struct, which is the first block.
|
||||
*/
|
||||
struct regional
|
||||
{
|
||||
/** next chunk. NULL if first chunk is the only chunk. */
|
||||
char* next;
|
||||
/** number of bytes allocated in the current chunk. */
|
||||
size_t allocated;
|
||||
/** initial chunk size */
|
||||
size_t first_size;
|
||||
/** current chunk size */
|
||||
size_t size;
|
||||
/** total large size */
|
||||
size_t total_large;
|
||||
/**
|
||||
* current chunk
|
||||
* can be cast to char** to obtain next chunk pointer.
|
||||
*/
|
||||
char *data;
|
||||
/** first large object, cast to char** to obtain next ptr */
|
||||
char* large_list;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new regional.
|
||||
*/
|
||||
struct regional* regional_create();
|
||||
|
||||
/**
|
||||
* Create a new region, with custom settings.
|
||||
* @param block: initial data block
|
||||
* The regional returned is allocated in the block (start of it).
|
||||
* @param size: length of block.
|
||||
*/
|
||||
struct regional* regional_create_custom(void* block, size_t size);
|
||||
|
||||
/**
|
||||
* Free all memory associated with REGION. Only keeps the first block with
|
||||
* the regional inside it.
|
||||
* @param r: the region.
|
||||
*/
|
||||
void regional_free_all(struct regional *r);
|
||||
|
||||
/**
|
||||
* Destroy regional. All memory associated with regional is freed as if
|
||||
* regional_free_all was called, as well as destroying the regional struct.
|
||||
* @param r: to delete.
|
||||
*/
|
||||
void regional_destroy(struct regional *r);
|
||||
|
||||
/**
|
||||
* Allocate SIZE bytes of memory inside REGION. The memory is
|
||||
* deallocated when region_free_all is called for this region.
|
||||
* @param r: the region.
|
||||
* @param size: number of bytes.
|
||||
* @return: pointer to memory allocated.
|
||||
*/
|
||||
void *regional_alloc(struct regional *r, size_t size);
|
||||
|
||||
/**
|
||||
* Allocate SIZE bytes of memory inside REGION and copy INIT into it.
|
||||
* The memory is deallocated when region_free_all is called for this
|
||||
* region.
|
||||
* @param r: the region.
|
||||
* @param init: to copy.
|
||||
* @param size: number of bytes.
|
||||
* @return: pointer to memory allocated.
|
||||
*/
|
||||
void *regional_alloc_init(struct regional* r, const void *init, size_t size);
|
||||
|
||||
/**
|
||||
* Allocate SIZE bytes of memory inside REGION that are initialized to
|
||||
* 0. The memory is deallocated when region_free_all is called for
|
||||
* this region.
|
||||
* @param r: the region.
|
||||
* @param size: number of bytes.
|
||||
* @return: pointer to memory allocated.
|
||||
*/
|
||||
void *regional_alloc_zero(struct regional *r, size_t size);
|
||||
|
||||
/**
|
||||
* Duplicate STRING and allocate the result in REGION.
|
||||
* @param r: the region.
|
||||
* @param string: null terminated string.
|
||||
*/
|
||||
char *regional_strdup(struct regional *r, const char *string);
|
||||
|
||||
/** Debug print REGION statistics to LOG */
|
||||
void regional_log_stats(struct regional *r);
|
||||
|
||||
/** get total memory size in use by region */
|
||||
size_t regional_get_mem(struct regional* r);
|
||||
|
||||
#endif /* UTIL_REGIONAL_H_ */
|
||||
Loading…
Reference in a new issue