2 * regional.c -- region based memory allocator.
4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved.
6 * Copyright (c) 2007, NLnet Labs. All rights reserved.
8 * This software is open source.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * Redistributions of source code must retain the above copyright notice,
15 * this list of conditions and the following disclaimer.
17 * Redistributions in binary form must reproduce the above copyright notice,
18 * this list of conditions and the following disclaimer in the documentation
19 * and/or other materials provided with the distribution.
21 * Neither the name of the NLNET LABS nor the names of its contributors may
22 * be used to endorse or promote products derived from this software without
23 * specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
31 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
40 * Regional allocator. Allocates small portions of of larger chunks.
45 #include "util/regional.h"
50 /** increase size until it fits alignment of s bytes */
51 #define ALIGN_UP(x, s) (((x) + s - 1) & (~(s - 1)))
52 /** what size to align on; make sure a char* fits in it. */
53 #define ALIGNMENT (sizeof(uint64_t))
55 /** Default reasonable size for chunks */
56 #define REGIONAL_CHUNK_SIZE 8192
57 #ifdef UNBOUND_ALLOC_NONREGIONAL
58 /** All objects allocated outside of chunks, for debug */
59 #define REGIONAL_LARGE_OBJECT_SIZE 0
61 /** Default size for large objects - allocated outside of chunks. */
62 #define REGIONAL_LARGE_OBJECT_SIZE 2048
68 return regional_create_custom(REGIONAL_CHUNK_SIZE);
71 /** init regional struct with first block */
73 regional_init(struct regional* r)
75 size_t a = ALIGN_UP(sizeof(struct regional), ALIGNMENT);
76 r->data = (char*)r + a;
77 r->available = r->first_size - a;
84 * Create a new region, with custom first block and large-object sizes.
85 * @param size: length of first block.
86 * @param large_object_size: outside of chunk allocation threshold.
87 * @return: newly allocated regional.
89 static struct regional*
90 regional_create_custom_large_object(size_t size, size_t large_object_size)
93 size = ALIGN_UP(size, ALIGNMENT);
94 r = (struct regional*)malloc(size);
95 log_assert(sizeof(struct regional) <= size);
98 r->large_object_size = large_object_size;
104 regional_create_custom(size_t size)
106 return regional_create_custom_large_object(size,
107 REGIONAL_LARGE_OBJECT_SIZE);
111 regional_create_nochunk(size_t size)
113 return regional_create_custom_large_object(size, 0);
117 regional_free_all(struct regional *r)
119 char* p = r->next, *np;
135 regional_destroy(struct regional *r)
138 regional_free_all(r);
143 regional_alloc(struct regional *r, size_t size)
148 #if SIZEOF_SIZE_T == 8
149 (unsigned long long)size >= 0xffffffffffffff00ULL
151 (unsigned)size >= (unsigned)0xffffff00UL
154 return NULL; /* protect against integer overflow in
155 malloc and ALIGN_UP */
156 a = ALIGN_UP(size, ALIGNMENT);
158 if(a > r->large_object_size) {
159 s = malloc(ALIGNMENT + size);
161 r->total_large += ALIGNMENT+size;
162 *(char**)s = r->large_list;
163 r->large_list = (char*)s;
164 return (char*)s+ALIGNMENT;
166 /* create a new chunk */
167 if(a > r->available) {
168 s = malloc(REGIONAL_CHUNK_SIZE);
170 *(char**)s = r->next;
172 r->data = (char*)s + ALIGNMENT;
173 r->available = REGIONAL_CHUNK_SIZE - ALIGNMENT;
175 /* put in this chunk */
183 regional_alloc_init(struct regional* r, const void *init, size_t size)
185 void *s = regional_alloc(r, size);
187 memcpy(s, init, size);
192 regional_alloc_zero(struct regional *r, size_t size)
194 void *s = regional_alloc(r, size);
201 regional_strdup(struct regional *r, const char *string)
203 return (char*)regional_alloc_init(r, string, strlen(string)+1);
207 * reasonably slow, but stats and get_mem are not supposed to be fast
208 * count the number of chunks in use
211 count_chunks(struct regional* r)
223 * also reasonably slow, counts the number of large objects
226 count_large(struct regional* r)
229 char* p = r->large_list;
238 regional_log_stats(struct regional *r)
240 /* some basic assertions put here (non time critical code) */
241 log_assert(ALIGNMENT >= sizeof(char*));
242 log_assert(REGIONAL_CHUNK_SIZE > ALIGNMENT);
243 log_assert(REGIONAL_CHUNK_SIZE-ALIGNMENT > r->large_object_size);
244 log_assert(REGIONAL_CHUNK_SIZE >= sizeof(struct regional));
246 log_info("regional %u chunks, %u large",
247 (unsigned)count_chunks(r), (unsigned)count_large(r));
251 regional_get_mem(struct regional* r)
253 return r->first_size + (count_chunks(r)-1)*REGIONAL_CHUNK_SIZE