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 regional_create_custom(size_t size
)
86 struct regional
* r
= (struct regional
*)malloc(size
);
87 log_assert(sizeof(struct regional
) <= size
);
95 regional_free_all(struct regional
*r
)
97 char* p
= r
->next
, *np
;
113 regional_destroy(struct regional
*r
)
116 regional_free_all(r
);
121 regional_alloc(struct regional
*r
, size_t size
)
123 size_t a
= ALIGN_UP(size
, ALIGNMENT
);
126 if(a
> REGIONAL_LARGE_OBJECT_SIZE
) {
127 s
= malloc(ALIGNMENT
+ size
);
129 r
->total_large
+= ALIGNMENT
+size
;
130 *(char**)s
= r
->large_list
;
131 r
->large_list
= (char*)s
;
132 return (char*)s
+ALIGNMENT
;
134 /* create a new chunk */
135 if(a
> r
->available
) {
136 s
= malloc(REGIONAL_CHUNK_SIZE
);
138 *(char**)s
= r
->next
;
140 r
->data
= (char*)s
+ ALIGNMENT
;
141 r
->available
= REGIONAL_CHUNK_SIZE
- ALIGNMENT
;
143 /* put in this chunk */
151 regional_alloc_init(struct regional
* r
, const void *init
, size_t size
)
153 void *s
= regional_alloc(r
, size
);
155 memcpy(s
, init
, size
);
160 regional_alloc_zero(struct regional
*r
, size_t size
)
162 void *s
= regional_alloc(r
, size
);
169 regional_strdup(struct regional
*r
, const char *string
)
171 return (char*)regional_alloc_init(r
, string
, strlen(string
)+1);
175 * reasonably slow, but stats and get_mem are not supposed to be fast
176 * count the number of chunks in use
179 count_chunks(struct regional
* r
)
191 * also reasonably slow, counts the number of large objects
194 count_large(struct regional
* r
)
197 char* p
= r
->large_list
;
206 regional_log_stats(struct regional
*r
)
208 /* some basic assertions put here (non time critical code) */
209 log_assert(ALIGNMENT
>= sizeof(char*));
210 log_assert(REGIONAL_CHUNK_SIZE
> ALIGNMENT
);
211 log_assert(REGIONAL_CHUNK_SIZE
-ALIGNMENT
> REGIONAL_LARGE_OBJECT_SIZE
);
212 log_assert(REGIONAL_CHUNK_SIZE
>= sizeof(struct regional
));
214 log_info("regional %u chunks, %u large",
215 (unsigned)count_chunks(r
), (unsigned)count_large(r
));
219 regional_get_mem(struct regional
* r
)
221 return r
->first_size
+ (count_chunks(r
)-1)*REGIONAL_CHUNK_SIZE