]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
regional.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 18 Oct 2007 15:40:31 +0000 (15:40 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Thu, 18 Oct 2007 15:40:31 +0000 (15:40 +0000)
git-svn-id: file:///svn/unbound/trunk@696 be551aaa-1e26-0410-a405-d3ace91eadb9

doc/Changelog
doc/unbound.doxygen
testdata/01-doc.tpkg
util/regional.c [new file with mode: 0644]
util/regional.h [new file with mode: 0644]

index 7ac4f45615fabcd1bd986631f8a2b2c343b5c8d9..c13265b74cb849dc57bff9b7513a03c4e4f3ed88 100644 (file)
@@ -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.
index 04abbce53efa8f4ad1bdebb29c4202827223d637..d9b87e85ecb18b768b5b9287e5901f1ba4571761 100644 (file)
@@ -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 
index 0e4ea228aa452cac5022b7bcc3a595411279d03d..b4a7f11ee739c27153bccf69407bf0348bf751a5 100644 (file)
Binary files a/testdata/01-doc.tpkg and b/testdata/01-doc.tpkg differ
diff --git a/util/regional.c b/util/regional.c
new file mode 100644 (file)
index 0000000..d22f149
--- /dev/null
@@ -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;
+}
diff --git a/util/regional.h b/util/regional.h
new file mode 100644 (file)
index 0000000..7c2975f
--- /dev/null
@@ -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_ */