xref: /freebsd/contrib/unbound/util/alloc.c (revision b5663de9eb877cb7ebb54c4ae4eb81007bb17df4)
1b7579f77SDag-Erling Smørgrav /*
2b7579f77SDag-Erling Smørgrav  * util/alloc.c - memory allocation service.
3b7579f77SDag-Erling Smørgrav  *
4b7579f77SDag-Erling Smørgrav  * Copyright (c) 2007, NLnet Labs. All rights reserved.
5b7579f77SDag-Erling Smørgrav  *
6b7579f77SDag-Erling Smørgrav  * This software is open source.
7b7579f77SDag-Erling Smørgrav  *
8b7579f77SDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
9b7579f77SDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
10b7579f77SDag-Erling Smørgrav  * are met:
11b7579f77SDag-Erling Smørgrav  *
12b7579f77SDag-Erling Smørgrav  * Redistributions of source code must retain the above copyright notice,
13b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer.
14b7579f77SDag-Erling Smørgrav  *
15b7579f77SDag-Erling Smørgrav  * Redistributions in binary form must reproduce the above copyright notice,
16b7579f77SDag-Erling Smørgrav  * this list of conditions and the following disclaimer in the documentation
17b7579f77SDag-Erling Smørgrav  * and/or other materials provided with the distribution.
18b7579f77SDag-Erling Smørgrav  *
19b7579f77SDag-Erling Smørgrav  * Neither the name of the NLNET LABS nor the names of its contributors may
20b7579f77SDag-Erling Smørgrav  * be used to endorse or promote products derived from this software without
21b7579f77SDag-Erling Smørgrav  * specific prior written permission.
22b7579f77SDag-Erling Smørgrav  *
23b7579f77SDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2417d15b25SDag-Erling Smørgrav  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2517d15b25SDag-Erling Smørgrav  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2617d15b25SDag-Erling Smørgrav  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2717d15b25SDag-Erling Smørgrav  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2817d15b25SDag-Erling Smørgrav  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2917d15b25SDag-Erling Smørgrav  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
3017d15b25SDag-Erling Smørgrav  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3117d15b25SDag-Erling Smørgrav  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3217d15b25SDag-Erling Smørgrav  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3317d15b25SDag-Erling Smørgrav  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34b7579f77SDag-Erling Smørgrav  */
35b7579f77SDag-Erling Smørgrav 
36b7579f77SDag-Erling Smørgrav /**
37b7579f77SDag-Erling Smørgrav  * \file
38b7579f77SDag-Erling Smørgrav  *
39b7579f77SDag-Erling Smørgrav  * This file contains memory allocation functions.
40b7579f77SDag-Erling Smørgrav  */
41b7579f77SDag-Erling Smørgrav 
42b7579f77SDag-Erling Smørgrav #include "config.h"
43b7579f77SDag-Erling Smørgrav #include "util/alloc.h"
44b7579f77SDag-Erling Smørgrav #include "util/regional.h"
45b7579f77SDag-Erling Smørgrav #include "util/data/packed_rrset.h"
46b7579f77SDag-Erling Smørgrav #include "util/fptr_wlist.h"
47b7579f77SDag-Erling Smørgrav 
48b7579f77SDag-Erling Smørgrav /** custom size of cached regional blocks */
49b7579f77SDag-Erling Smørgrav #define ALLOC_REG_SIZE	16384
50b7579f77SDag-Erling Smørgrav /** number of bits for ID part of uint64, rest for number of threads. */
51b7579f77SDag-Erling Smørgrav #define THRNUM_SHIFT	48	/* for 65k threads, 2^48 rrsets per thr. */
52b7579f77SDag-Erling Smørgrav 
53b7579f77SDag-Erling Smørgrav /** setup new special type */
54b7579f77SDag-Erling Smørgrav static void
55b7579f77SDag-Erling Smørgrav alloc_setup_special(alloc_special_t* t)
56b7579f77SDag-Erling Smørgrav {
57b7579f77SDag-Erling Smørgrav 	memset(t, 0, sizeof(*t));
58b7579f77SDag-Erling Smørgrav 	lock_rw_init(&t->entry.lock);
59b7579f77SDag-Erling Smørgrav 	t->entry.key = t;
60b7579f77SDag-Erling Smørgrav }
61b7579f77SDag-Erling Smørgrav 
62b7579f77SDag-Erling Smørgrav /** prealloc some entries in the cache. To minimize contention.
63b7579f77SDag-Erling Smørgrav  * Result is 1 lock per alloc_max newly created entries.
64b7579f77SDag-Erling Smørgrav  * @param alloc: the structure to fill up.
65b7579f77SDag-Erling Smørgrav  */
66b7579f77SDag-Erling Smørgrav static void
67*b5663de9SDag-Erling Smørgrav prealloc_setup(struct alloc_cache* alloc)
68b7579f77SDag-Erling Smørgrav {
69b7579f77SDag-Erling Smørgrav 	alloc_special_t* p;
70b7579f77SDag-Erling Smørgrav 	int i;
71b7579f77SDag-Erling Smørgrav 	for(i=0; i<ALLOC_SPECIAL_MAX; i++) {
72b7579f77SDag-Erling Smørgrav 		if(!(p = (alloc_special_t*)malloc(sizeof(alloc_special_t)))) {
73b7579f77SDag-Erling Smørgrav 			log_err("prealloc: out of memory");
74b7579f77SDag-Erling Smørgrav 			return;
75b7579f77SDag-Erling Smørgrav 		}
76b7579f77SDag-Erling Smørgrav 		alloc_setup_special(p);
77b7579f77SDag-Erling Smørgrav 		alloc_set_special_next(p, alloc->quar);
78b7579f77SDag-Erling Smørgrav 		alloc->quar = p;
79b7579f77SDag-Erling Smørgrav 		alloc->num_quar++;
80b7579f77SDag-Erling Smørgrav 	}
81b7579f77SDag-Erling Smørgrav }
82b7579f77SDag-Erling Smørgrav 
83b7579f77SDag-Erling Smørgrav /** prealloc region blocks */
84b7579f77SDag-Erling Smørgrav static void
85b7579f77SDag-Erling Smørgrav prealloc_blocks(struct alloc_cache* alloc, size_t num)
86b7579f77SDag-Erling Smørgrav {
87b7579f77SDag-Erling Smørgrav 	size_t i;
88b7579f77SDag-Erling Smørgrav 	struct regional* r;
89b7579f77SDag-Erling Smørgrav 	for(i=0; i<num; i++) {
90b7579f77SDag-Erling Smørgrav 		r = regional_create_custom(ALLOC_REG_SIZE);
91b7579f77SDag-Erling Smørgrav 		if(!r) {
92b7579f77SDag-Erling Smørgrav 			log_err("prealloc blocks: out of memory");
93b7579f77SDag-Erling Smørgrav 			return;
94b7579f77SDag-Erling Smørgrav 		}
95b7579f77SDag-Erling Smørgrav 		r->next = (char*)alloc->reg_list;
96b7579f77SDag-Erling Smørgrav 		alloc->reg_list = r;
97b7579f77SDag-Erling Smørgrav 		alloc->num_reg_blocks ++;
98b7579f77SDag-Erling Smørgrav 	}
99b7579f77SDag-Erling Smørgrav }
100b7579f77SDag-Erling Smørgrav 
101b7579f77SDag-Erling Smørgrav void
102b7579f77SDag-Erling Smørgrav alloc_init(struct alloc_cache* alloc, struct alloc_cache* super,
103b7579f77SDag-Erling Smørgrav 	int thread_num)
104b7579f77SDag-Erling Smørgrav {
105b7579f77SDag-Erling Smørgrav 	memset(alloc, 0, sizeof(*alloc));
106b7579f77SDag-Erling Smørgrav 	alloc->super = super;
107b7579f77SDag-Erling Smørgrav 	alloc->thread_num = thread_num;
108b7579f77SDag-Erling Smørgrav 	alloc->next_id = (uint64_t)thread_num; 	/* in steps, so that type */
109b7579f77SDag-Erling Smørgrav 	alloc->next_id <<= THRNUM_SHIFT; 	/* of *_id is used. */
110b7579f77SDag-Erling Smørgrav 	alloc->last_id = 1; 			/* so no 64bit constants, */
111b7579f77SDag-Erling Smørgrav 	alloc->last_id <<= THRNUM_SHIFT; 	/* or implicit 'int' ops. */
112b7579f77SDag-Erling Smørgrav 	alloc->last_id -= 1; 			/* for compiler portability. */
113b7579f77SDag-Erling Smørgrav 	alloc->last_id |= alloc->next_id;
114b7579f77SDag-Erling Smørgrav 	alloc->next_id += 1;			/* because id=0 is special. */
115b7579f77SDag-Erling Smørgrav 	alloc->max_reg_blocks = 100;
116b7579f77SDag-Erling Smørgrav 	alloc->num_reg_blocks = 0;
117b7579f77SDag-Erling Smørgrav 	alloc->reg_list = NULL;
118b7579f77SDag-Erling Smørgrav 	alloc->cleanup = NULL;
119b7579f77SDag-Erling Smørgrav 	alloc->cleanup_arg = NULL;
120b7579f77SDag-Erling Smørgrav 	if(alloc->super)
121b7579f77SDag-Erling Smørgrav 		prealloc_blocks(alloc, alloc->max_reg_blocks);
122b7579f77SDag-Erling Smørgrav 	if(!alloc->super) {
123b7579f77SDag-Erling Smørgrav 		lock_quick_init(&alloc->lock);
124b7579f77SDag-Erling Smørgrav 		lock_protect(&alloc->lock, alloc, sizeof(*alloc));
125b7579f77SDag-Erling Smørgrav 	}
126b7579f77SDag-Erling Smørgrav }
127b7579f77SDag-Erling Smørgrav 
128b7579f77SDag-Erling Smørgrav void
129b7579f77SDag-Erling Smørgrav alloc_clear(struct alloc_cache* alloc)
130b7579f77SDag-Erling Smørgrav {
131b7579f77SDag-Erling Smørgrav 	alloc_special_t* p, *np;
132b7579f77SDag-Erling Smørgrav 	struct regional* r, *nr;
133b7579f77SDag-Erling Smørgrav 	if(!alloc)
134b7579f77SDag-Erling Smørgrav 		return;
135b7579f77SDag-Erling Smørgrav 	if(!alloc->super) {
136b7579f77SDag-Erling Smørgrav 		lock_quick_destroy(&alloc->lock);
137b7579f77SDag-Erling Smørgrav 	}
138b7579f77SDag-Erling Smørgrav 	if(alloc->super && alloc->quar) {
139b7579f77SDag-Erling Smørgrav 		/* push entire list into super */
140b7579f77SDag-Erling Smørgrav 		p = alloc->quar;
141b7579f77SDag-Erling Smørgrav 		while(alloc_special_next(p)) /* find last */
142b7579f77SDag-Erling Smørgrav 			p = alloc_special_next(p);
143b7579f77SDag-Erling Smørgrav 		lock_quick_lock(&alloc->super->lock);
144b7579f77SDag-Erling Smørgrav 		alloc_set_special_next(p, alloc->super->quar);
145b7579f77SDag-Erling Smørgrav 		alloc->super->quar = alloc->quar;
146b7579f77SDag-Erling Smørgrav 		alloc->super->num_quar += alloc->num_quar;
147b7579f77SDag-Erling Smørgrav 		lock_quick_unlock(&alloc->super->lock);
148b7579f77SDag-Erling Smørgrav 	} else {
149b7579f77SDag-Erling Smørgrav 		/* free */
150b7579f77SDag-Erling Smørgrav 		p = alloc->quar;
151b7579f77SDag-Erling Smørgrav 		while(p) {
152b7579f77SDag-Erling Smørgrav 			np = alloc_special_next(p);
153b7579f77SDag-Erling Smørgrav 			/* deinit special type */
154b7579f77SDag-Erling Smørgrav 			lock_rw_destroy(&p->entry.lock);
155b7579f77SDag-Erling Smørgrav 			free(p);
156b7579f77SDag-Erling Smørgrav 			p = np;
157b7579f77SDag-Erling Smørgrav 		}
158b7579f77SDag-Erling Smørgrav 	}
159b7579f77SDag-Erling Smørgrav 	alloc->quar = 0;
160b7579f77SDag-Erling Smørgrav 	alloc->num_quar = 0;
161b7579f77SDag-Erling Smørgrav 	r = alloc->reg_list;
162b7579f77SDag-Erling Smørgrav 	while(r) {
163b7579f77SDag-Erling Smørgrav 		nr = (struct regional*)r->next;
164b7579f77SDag-Erling Smørgrav 		free(r);
165b7579f77SDag-Erling Smørgrav 		r = nr;
166b7579f77SDag-Erling Smørgrav 	}
167b7579f77SDag-Erling Smørgrav 	alloc->reg_list = NULL;
168b7579f77SDag-Erling Smørgrav 	alloc->num_reg_blocks = 0;
169b7579f77SDag-Erling Smørgrav }
170b7579f77SDag-Erling Smørgrav 
171b7579f77SDag-Erling Smørgrav uint64_t
172b7579f77SDag-Erling Smørgrav alloc_get_id(struct alloc_cache* alloc)
173b7579f77SDag-Erling Smørgrav {
174b7579f77SDag-Erling Smørgrav 	uint64_t id = alloc->next_id++;
175b7579f77SDag-Erling Smørgrav 	if(id == alloc->last_id) {
176b7579f77SDag-Erling Smørgrav 		log_warn("rrset alloc: out of 64bit ids. Clearing cache.");
177b7579f77SDag-Erling Smørgrav 		fptr_ok(fptr_whitelist_alloc_cleanup(alloc->cleanup));
178b7579f77SDag-Erling Smørgrav 		(*alloc->cleanup)(alloc->cleanup_arg);
179b7579f77SDag-Erling Smørgrav 
180b7579f77SDag-Erling Smørgrav 		/* start back at first number */   	/* like in alloc_init*/
181b7579f77SDag-Erling Smørgrav 		alloc->next_id = (uint64_t)alloc->thread_num;
182b7579f77SDag-Erling Smørgrav 		alloc->next_id <<= THRNUM_SHIFT; 	/* in steps for comp. */
183b7579f77SDag-Erling Smørgrav 		alloc->next_id += 1;			/* portability. */
184b7579f77SDag-Erling Smørgrav 		/* and generate new and safe id */
185b7579f77SDag-Erling Smørgrav 		id = alloc->next_id++;
186b7579f77SDag-Erling Smørgrav 	}
187b7579f77SDag-Erling Smørgrav 	return id;
188b7579f77SDag-Erling Smørgrav }
189b7579f77SDag-Erling Smørgrav 
190b7579f77SDag-Erling Smørgrav alloc_special_t*
191b7579f77SDag-Erling Smørgrav alloc_special_obtain(struct alloc_cache* alloc)
192b7579f77SDag-Erling Smørgrav {
193b7579f77SDag-Erling Smørgrav 	alloc_special_t* p;
194b7579f77SDag-Erling Smørgrav 	log_assert(alloc);
195b7579f77SDag-Erling Smørgrav 	/* see if in local cache */
196b7579f77SDag-Erling Smørgrav 	if(alloc->quar) {
197b7579f77SDag-Erling Smørgrav 		p = alloc->quar;
198b7579f77SDag-Erling Smørgrav 		alloc->quar = alloc_special_next(p);
199b7579f77SDag-Erling Smørgrav 		alloc->num_quar--;
200b7579f77SDag-Erling Smørgrav 		p->id = alloc_get_id(alloc);
201b7579f77SDag-Erling Smørgrav 		return p;
202b7579f77SDag-Erling Smørgrav 	}
203b7579f77SDag-Erling Smørgrav 	/* see if in global cache */
204b7579f77SDag-Erling Smørgrav 	if(alloc->super) {
205b7579f77SDag-Erling Smørgrav 		/* could maybe grab alloc_max/2 entries in one go,
206b7579f77SDag-Erling Smørgrav 		 * but really, isn't that just as fast as this code? */
207b7579f77SDag-Erling Smørgrav 		lock_quick_lock(&alloc->super->lock);
208b7579f77SDag-Erling Smørgrav 		if((p = alloc->super->quar)) {
209b7579f77SDag-Erling Smørgrav 			alloc->super->quar = alloc_special_next(p);
210b7579f77SDag-Erling Smørgrav 			alloc->super->num_quar--;
211b7579f77SDag-Erling Smørgrav 		}
212b7579f77SDag-Erling Smørgrav 		lock_quick_unlock(&alloc->super->lock);
213b7579f77SDag-Erling Smørgrav 		if(p) {
214b7579f77SDag-Erling Smørgrav 			p->id = alloc_get_id(alloc);
215b7579f77SDag-Erling Smørgrav 			return p;
216b7579f77SDag-Erling Smørgrav 		}
217b7579f77SDag-Erling Smørgrav 	}
218b7579f77SDag-Erling Smørgrav 	/* allocate new */
219*b5663de9SDag-Erling Smørgrav 	prealloc_setup(alloc);
220b7579f77SDag-Erling Smørgrav 	if(!(p = (alloc_special_t*)malloc(sizeof(alloc_special_t)))) {
221b7579f77SDag-Erling Smørgrav 		log_err("alloc_special_obtain: out of memory");
222b7579f77SDag-Erling Smørgrav 		return NULL;
223b7579f77SDag-Erling Smørgrav 	}
224b7579f77SDag-Erling Smørgrav 	alloc_setup_special(p);
225b7579f77SDag-Erling Smørgrav 	p->id = alloc_get_id(alloc);
226b7579f77SDag-Erling Smørgrav 	return p;
227b7579f77SDag-Erling Smørgrav }
228b7579f77SDag-Erling Smørgrav 
229b7579f77SDag-Erling Smørgrav /** push mem and some more items to the super */
230b7579f77SDag-Erling Smørgrav static void
231b7579f77SDag-Erling Smørgrav pushintosuper(struct alloc_cache* alloc, alloc_special_t* mem)
232b7579f77SDag-Erling Smørgrav {
233b7579f77SDag-Erling Smørgrav 	int i;
234b7579f77SDag-Erling Smørgrav 	alloc_special_t *p = alloc->quar;
235b7579f77SDag-Erling Smørgrav 	log_assert(p);
236b7579f77SDag-Erling Smørgrav 	log_assert(alloc && alloc->super &&
237b7579f77SDag-Erling Smørgrav 		alloc->num_quar >= ALLOC_SPECIAL_MAX);
238b7579f77SDag-Erling Smørgrav 	/* push ALLOC_SPECIAL_MAX/2 after mem */
239b7579f77SDag-Erling Smørgrav 	alloc_set_special_next(mem, alloc->quar);
240b7579f77SDag-Erling Smørgrav 	for(i=1; i<ALLOC_SPECIAL_MAX/2; i++) {
241b7579f77SDag-Erling Smørgrav 		p = alloc_special_next(p);
242b7579f77SDag-Erling Smørgrav 	}
243b7579f77SDag-Erling Smørgrav 	alloc->quar = alloc_special_next(p);
244b7579f77SDag-Erling Smørgrav 	alloc->num_quar -= ALLOC_SPECIAL_MAX/2;
245b7579f77SDag-Erling Smørgrav 
246b7579f77SDag-Erling Smørgrav 	/* dump mem+list into the super quar list */
247b7579f77SDag-Erling Smørgrav 	lock_quick_lock(&alloc->super->lock);
248b7579f77SDag-Erling Smørgrav 	alloc_set_special_next(p, alloc->super->quar);
249b7579f77SDag-Erling Smørgrav 	alloc->super->quar = mem;
250b7579f77SDag-Erling Smørgrav 	alloc->super->num_quar += ALLOC_SPECIAL_MAX/2 + 1;
251b7579f77SDag-Erling Smørgrav 	lock_quick_unlock(&alloc->super->lock);
252b7579f77SDag-Erling Smørgrav 	/* so 1 lock per mem+alloc/2 deletes */
253b7579f77SDag-Erling Smørgrav }
254b7579f77SDag-Erling Smørgrav 
255b7579f77SDag-Erling Smørgrav void
256b7579f77SDag-Erling Smørgrav alloc_special_release(struct alloc_cache* alloc, alloc_special_t* mem)
257b7579f77SDag-Erling Smørgrav {
258b7579f77SDag-Erling Smørgrav 	log_assert(alloc);
259b7579f77SDag-Erling Smørgrav 	if(!mem)
260b7579f77SDag-Erling Smørgrav 		return;
261b7579f77SDag-Erling Smørgrav 	if(!alloc->super) {
262b7579f77SDag-Erling Smørgrav 		lock_quick_lock(&alloc->lock); /* superalloc needs locking */
263b7579f77SDag-Erling Smørgrav 	}
264b7579f77SDag-Erling Smørgrav 
265b7579f77SDag-Erling Smørgrav 	alloc_special_clean(mem);
266b7579f77SDag-Erling Smørgrav 	if(alloc->super && alloc->num_quar >= ALLOC_SPECIAL_MAX) {
267b7579f77SDag-Erling Smørgrav 		/* push it to the super structure */
268b7579f77SDag-Erling Smørgrav 		pushintosuper(alloc, mem);
269b7579f77SDag-Erling Smørgrav 		return;
270b7579f77SDag-Erling Smørgrav 	}
271b7579f77SDag-Erling Smørgrav 
272b7579f77SDag-Erling Smørgrav 	alloc_set_special_next(mem, alloc->quar);
273b7579f77SDag-Erling Smørgrav 	alloc->quar = mem;
274b7579f77SDag-Erling Smørgrav 	alloc->num_quar++;
275b7579f77SDag-Erling Smørgrav 	if(!alloc->super) {
276b7579f77SDag-Erling Smørgrav 		lock_quick_unlock(&alloc->lock);
277b7579f77SDag-Erling Smørgrav 	}
278b7579f77SDag-Erling Smørgrav }
279b7579f77SDag-Erling Smørgrav 
280b7579f77SDag-Erling Smørgrav void
281b7579f77SDag-Erling Smørgrav alloc_stats(struct alloc_cache* alloc)
282b7579f77SDag-Erling Smørgrav {
283b7579f77SDag-Erling Smørgrav 	log_info("%salloc: %d in cache, %d blocks.", alloc->super?"":"sup",
284b7579f77SDag-Erling Smørgrav 		(int)alloc->num_quar, (int)alloc->num_reg_blocks);
285b7579f77SDag-Erling Smørgrav }
286b7579f77SDag-Erling Smørgrav 
287b7579f77SDag-Erling Smørgrav size_t alloc_get_mem(struct alloc_cache* alloc)
288b7579f77SDag-Erling Smørgrav {
289b7579f77SDag-Erling Smørgrav 	alloc_special_t* p;
290b7579f77SDag-Erling Smørgrav 	size_t s = sizeof(*alloc);
291b7579f77SDag-Erling Smørgrav 	if(!alloc->super) {
292b7579f77SDag-Erling Smørgrav 		lock_quick_lock(&alloc->lock); /* superalloc needs locking */
293b7579f77SDag-Erling Smørgrav 	}
294b7579f77SDag-Erling Smørgrav 	s += sizeof(alloc_special_t) * alloc->num_quar;
295b7579f77SDag-Erling Smørgrav 	for(p = alloc->quar; p; p = alloc_special_next(p)) {
296b7579f77SDag-Erling Smørgrav 		s += lock_get_mem(&p->entry.lock);
297b7579f77SDag-Erling Smørgrav 	}
298b7579f77SDag-Erling Smørgrav 	s += alloc->num_reg_blocks * ALLOC_REG_SIZE;
299b7579f77SDag-Erling Smørgrav 	if(!alloc->super) {
300b7579f77SDag-Erling Smørgrav 		lock_quick_unlock(&alloc->lock);
301b7579f77SDag-Erling Smørgrav 	}
302b7579f77SDag-Erling Smørgrav 	return s;
303b7579f77SDag-Erling Smørgrav }
304b7579f77SDag-Erling Smørgrav 
305b7579f77SDag-Erling Smørgrav struct regional*
306b7579f77SDag-Erling Smørgrav alloc_reg_obtain(struct alloc_cache* alloc)
307b7579f77SDag-Erling Smørgrav {
308b7579f77SDag-Erling Smørgrav 	if(alloc->num_reg_blocks > 0) {
309b7579f77SDag-Erling Smørgrav 		struct regional* r = alloc->reg_list;
310b7579f77SDag-Erling Smørgrav 		alloc->reg_list = (struct regional*)r->next;
311b7579f77SDag-Erling Smørgrav 		r->next = NULL;
312b7579f77SDag-Erling Smørgrav 		alloc->num_reg_blocks--;
313b7579f77SDag-Erling Smørgrav 		return r;
314b7579f77SDag-Erling Smørgrav 	}
315b7579f77SDag-Erling Smørgrav 	return regional_create_custom(ALLOC_REG_SIZE);
316b7579f77SDag-Erling Smørgrav }
317b7579f77SDag-Erling Smørgrav 
318b7579f77SDag-Erling Smørgrav void
319b7579f77SDag-Erling Smørgrav alloc_reg_release(struct alloc_cache* alloc, struct regional* r)
320b7579f77SDag-Erling Smørgrav {
321b7579f77SDag-Erling Smørgrav 	if(alloc->num_reg_blocks >= alloc->max_reg_blocks) {
322b7579f77SDag-Erling Smørgrav 		regional_destroy(r);
323b7579f77SDag-Erling Smørgrav 		return;
324b7579f77SDag-Erling Smørgrav 	}
325b7579f77SDag-Erling Smørgrav 	if(!r) return;
326b7579f77SDag-Erling Smørgrav 	regional_free_all(r);
327b7579f77SDag-Erling Smørgrav 	log_assert(r->next == NULL);
328b7579f77SDag-Erling Smørgrav 	r->next = (char*)alloc->reg_list;
329b7579f77SDag-Erling Smørgrav 	alloc->reg_list = r;
330b7579f77SDag-Erling Smørgrav 	alloc->num_reg_blocks++;
331b7579f77SDag-Erling Smørgrav }
332b7579f77SDag-Erling Smørgrav 
333b7579f77SDag-Erling Smørgrav void
334b7579f77SDag-Erling Smørgrav alloc_set_id_cleanup(struct alloc_cache* alloc, void (*cleanup)(void*),
335b7579f77SDag-Erling Smørgrav         void* arg)
336b7579f77SDag-Erling Smørgrav {
337b7579f77SDag-Erling Smørgrav 	alloc->cleanup = cleanup;
338b7579f77SDag-Erling Smørgrav 	alloc->cleanup_arg = arg;
339b7579f77SDag-Erling Smørgrav }
340b7579f77SDag-Erling Smørgrav 
341b7579f77SDag-Erling Smørgrav /** global debug value to keep track of total memory mallocs */
342b7579f77SDag-Erling Smørgrav size_t unbound_mem_alloc = 0;
343b7579f77SDag-Erling Smørgrav /** global debug value to keep track of total memory frees */
344b7579f77SDag-Erling Smørgrav size_t unbound_mem_freed = 0;
345b7579f77SDag-Erling Smørgrav #ifdef UNBOUND_ALLOC_STATS
346b7579f77SDag-Erling Smørgrav /** special value to know if the memory is being tracked */
347b7579f77SDag-Erling Smørgrav uint64_t mem_special = (uint64_t)0xfeed43327766abcdLL;
348b7579f77SDag-Erling Smørgrav #ifdef malloc
349b7579f77SDag-Erling Smørgrav #undef malloc
350b7579f77SDag-Erling Smørgrav #endif
351b7579f77SDag-Erling Smørgrav /** malloc with stats */
352b7579f77SDag-Erling Smørgrav void *unbound_stat_malloc(size_t size)
353b7579f77SDag-Erling Smørgrav {
354b7579f77SDag-Erling Smørgrav 	void* res;
355b7579f77SDag-Erling Smørgrav 	if(size == 0) size = 1;
356b7579f77SDag-Erling Smørgrav 	res = malloc(size+16);
357b7579f77SDag-Erling Smørgrav 	if(!res) return NULL;
358b7579f77SDag-Erling Smørgrav 	unbound_mem_alloc += size;
359b7579f77SDag-Erling Smørgrav 	log_info("stat %p=malloc(%u)", res+16, (unsigned)size);
360b7579f77SDag-Erling Smørgrav 	memcpy(res, &size, sizeof(size));
361b7579f77SDag-Erling Smørgrav 	memcpy(res+8, &mem_special, sizeof(mem_special));
362b7579f77SDag-Erling Smørgrav 	return res+16;
363b7579f77SDag-Erling Smørgrav }
364b7579f77SDag-Erling Smørgrav #ifdef calloc
365b7579f77SDag-Erling Smørgrav #undef calloc
366b7579f77SDag-Erling Smørgrav #endif
36709a3aaf3SDag-Erling Smørgrav #ifndef INT_MAX
36809a3aaf3SDag-Erling Smørgrav #define INT_MAX (((int)-1)>>1)
36909a3aaf3SDag-Erling Smørgrav #endif
370b7579f77SDag-Erling Smørgrav /** calloc with stats */
371b7579f77SDag-Erling Smørgrav void *unbound_stat_calloc(size_t nmemb, size_t size)
372b7579f77SDag-Erling Smørgrav {
37309a3aaf3SDag-Erling Smørgrav 	size_t s;
37409a3aaf3SDag-Erling Smørgrav 	void* res;
37509a3aaf3SDag-Erling Smørgrav 	if(nmemb != 0 && INT_MAX/nmemb < size)
37609a3aaf3SDag-Erling Smørgrav 		return NULL; /* integer overflow check */
37709a3aaf3SDag-Erling Smørgrav 	s = (nmemb*size==0)?(size_t)1:nmemb*size;
37809a3aaf3SDag-Erling Smørgrav 	res = calloc(1, s+16);
379b7579f77SDag-Erling Smørgrav 	if(!res) return NULL;
380b7579f77SDag-Erling Smørgrav 	log_info("stat %p=calloc(%u, %u)", res+16, (unsigned)nmemb, (unsigned)size);
381b7579f77SDag-Erling Smørgrav 	unbound_mem_alloc += s;
382b7579f77SDag-Erling Smørgrav 	memcpy(res, &s, sizeof(s));
383b7579f77SDag-Erling Smørgrav 	memcpy(res+8, &mem_special, sizeof(mem_special));
384b7579f77SDag-Erling Smørgrav 	return res+16;
385b7579f77SDag-Erling Smørgrav }
386b7579f77SDag-Erling Smørgrav #ifdef free
387b7579f77SDag-Erling Smørgrav #undef free
388b7579f77SDag-Erling Smørgrav #endif
389b7579f77SDag-Erling Smørgrav /** free with stats */
390b7579f77SDag-Erling Smørgrav void unbound_stat_free(void *ptr)
391b7579f77SDag-Erling Smørgrav {
392b7579f77SDag-Erling Smørgrav 	size_t s;
393b7579f77SDag-Erling Smørgrav 	if(!ptr) return;
394b7579f77SDag-Erling Smørgrav 	if(memcmp(ptr-8, &mem_special, sizeof(mem_special)) != 0) {
395b7579f77SDag-Erling Smørgrav 		free(ptr);
396b7579f77SDag-Erling Smørgrav 		return;
397b7579f77SDag-Erling Smørgrav 	}
398b7579f77SDag-Erling Smørgrav 	ptr-=16;
399b7579f77SDag-Erling Smørgrav 	memcpy(&s, ptr, sizeof(s));
400b7579f77SDag-Erling Smørgrav 	log_info("stat free(%p) size %u", ptr+16, (unsigned)s);
401b7579f77SDag-Erling Smørgrav 	memset(ptr+8, 0, 8);
402b7579f77SDag-Erling Smørgrav 	unbound_mem_freed += s;
403b7579f77SDag-Erling Smørgrav 	free(ptr);
404b7579f77SDag-Erling Smørgrav }
405b7579f77SDag-Erling Smørgrav #ifdef realloc
406b7579f77SDag-Erling Smørgrav #undef realloc
407b7579f77SDag-Erling Smørgrav #endif
408b7579f77SDag-Erling Smørgrav /** realloc with stats */
409b7579f77SDag-Erling Smørgrav void *unbound_stat_realloc(void *ptr, size_t size)
410b7579f77SDag-Erling Smørgrav {
411b7579f77SDag-Erling Smørgrav 	size_t cursz;
412b7579f77SDag-Erling Smørgrav 	void* res;
413b7579f77SDag-Erling Smørgrav 	if(!ptr) return unbound_stat_malloc(size);
414b7579f77SDag-Erling Smørgrav 	if(memcmp(ptr-8, &mem_special, sizeof(mem_special)) != 0) {
415b7579f77SDag-Erling Smørgrav 		return realloc(ptr, size);
416b7579f77SDag-Erling Smørgrav 	}
417b7579f77SDag-Erling Smørgrav 	if(size==0) {
418b7579f77SDag-Erling Smørgrav 		unbound_stat_free(ptr);
419b7579f77SDag-Erling Smørgrav 		return NULL;
420b7579f77SDag-Erling Smørgrav 	}
421b7579f77SDag-Erling Smørgrav 	ptr -= 16;
422b7579f77SDag-Erling Smørgrav 	memcpy(&cursz, ptr, sizeof(cursz));
423b7579f77SDag-Erling Smørgrav 	if(cursz == size) {
424b7579f77SDag-Erling Smørgrav 		/* nothing changes */
425b7579f77SDag-Erling Smørgrav 		return ptr;
426b7579f77SDag-Erling Smørgrav 	}
427b7579f77SDag-Erling Smørgrav 	res = malloc(size+16);
428b7579f77SDag-Erling Smørgrav 	if(!res) return NULL;
429b7579f77SDag-Erling Smørgrav 	unbound_mem_alloc += size;
430b7579f77SDag-Erling Smørgrav 	unbound_mem_freed += cursz;
431b7579f77SDag-Erling Smørgrav 	log_info("stat realloc(%p, %u) from %u", ptr+16, (unsigned)size, (unsigned)cursz);
432b7579f77SDag-Erling Smørgrav 	if(cursz > size) {
433b7579f77SDag-Erling Smørgrav 		memcpy(res+16, ptr+16, size);
434b7579f77SDag-Erling Smørgrav 	} else if(size > cursz) {
435b7579f77SDag-Erling Smørgrav 		memcpy(res+16, ptr+16, cursz);
436b7579f77SDag-Erling Smørgrav 	}
437b7579f77SDag-Erling Smørgrav 	memset(ptr+8, 0, 8);
438b7579f77SDag-Erling Smørgrav 	free(ptr);
439b7579f77SDag-Erling Smørgrav 	memcpy(res, &size, sizeof(size));
440b7579f77SDag-Erling Smørgrav 	memcpy(res+8, &mem_special, sizeof(mem_special));
441b7579f77SDag-Erling Smørgrav 	return res+16;
442b7579f77SDag-Erling Smørgrav }
443b7579f77SDag-Erling Smørgrav 
444b7579f77SDag-Erling Smørgrav /** log to file where alloc was done */
445b7579f77SDag-Erling Smørgrav void *unbound_stat_malloc_log(size_t size, const char* file, int line,
446b7579f77SDag-Erling Smørgrav         const char* func)
447b7579f77SDag-Erling Smørgrav {
448b7579f77SDag-Erling Smørgrav 	log_info("%s:%d %s malloc(%u)", file, line, func, (unsigned)size);
449b7579f77SDag-Erling Smørgrav 	return unbound_stat_malloc(size);
450b7579f77SDag-Erling Smørgrav }
451b7579f77SDag-Erling Smørgrav 
452b7579f77SDag-Erling Smørgrav /** log to file where alloc was done */
453b7579f77SDag-Erling Smørgrav void *unbound_stat_calloc_log(size_t nmemb, size_t size, const char* file,
454b7579f77SDag-Erling Smørgrav         int line, const char* func)
455b7579f77SDag-Erling Smørgrav {
456b7579f77SDag-Erling Smørgrav 	log_info("%s:%d %s calloc(%u, %u)", file, line, func,
457b7579f77SDag-Erling Smørgrav 		(unsigned) nmemb, (unsigned)size);
458b7579f77SDag-Erling Smørgrav 	return unbound_stat_calloc(nmemb, size);
459b7579f77SDag-Erling Smørgrav }
460b7579f77SDag-Erling Smørgrav 
461b7579f77SDag-Erling Smørgrav /** log to file where free was done */
462b7579f77SDag-Erling Smørgrav void unbound_stat_free_log(void *ptr, const char* file, int line,
463b7579f77SDag-Erling Smørgrav         const char* func)
464b7579f77SDag-Erling Smørgrav {
465b7579f77SDag-Erling Smørgrav 	if(ptr && memcmp(ptr-8, &mem_special, sizeof(mem_special)) == 0) {
466b7579f77SDag-Erling Smørgrav 		size_t s;
467b7579f77SDag-Erling Smørgrav 		memcpy(&s, ptr-16, sizeof(s));
468b7579f77SDag-Erling Smørgrav 		log_info("%s:%d %s free(%p) size %u",
469b7579f77SDag-Erling Smørgrav 			file, line, func, ptr, (unsigned)s);
470b7579f77SDag-Erling Smørgrav 	} else
471b7579f77SDag-Erling Smørgrav 		log_info("%s:%d %s unmatched free(%p)", file, line, func, ptr);
472b7579f77SDag-Erling Smørgrav 	unbound_stat_free(ptr);
473b7579f77SDag-Erling Smørgrav }
474b7579f77SDag-Erling Smørgrav 
475b7579f77SDag-Erling Smørgrav /** log to file where alloc was done */
476b7579f77SDag-Erling Smørgrav void *unbound_stat_realloc_log(void *ptr, size_t size, const char* file,
477b7579f77SDag-Erling Smørgrav         int line, const char* func)
478b7579f77SDag-Erling Smørgrav {
479b7579f77SDag-Erling Smørgrav 	log_info("%s:%d %s realloc(%p, %u)", file, line, func,
480b7579f77SDag-Erling Smørgrav 		ptr, (unsigned)size);
481b7579f77SDag-Erling Smørgrav 	return unbound_stat_realloc(ptr, size);
482b7579f77SDag-Erling Smørgrav }
483b7579f77SDag-Erling Smørgrav 
484b7579f77SDag-Erling Smørgrav #endif /* UNBOUND_ALLOC_STATS */
485b7579f77SDag-Erling Smørgrav #ifdef UNBOUND_ALLOC_LITE
486b7579f77SDag-Erling Smørgrav #undef malloc
487b7579f77SDag-Erling Smørgrav #undef calloc
488b7579f77SDag-Erling Smørgrav #undef free
489b7579f77SDag-Erling Smørgrav #undef realloc
490b7579f77SDag-Erling Smørgrav /** length of prefix and suffix */
491b7579f77SDag-Erling Smørgrav static size_t lite_pad = 16;
492b7579f77SDag-Erling Smørgrav /** prefix value to check */
493b7579f77SDag-Erling Smørgrav static char* lite_pre = "checkfront123456";
494b7579f77SDag-Erling Smørgrav /** suffix value to check */
495b7579f77SDag-Erling Smørgrav static char* lite_post= "checkafter123456";
496b7579f77SDag-Erling Smørgrav 
497b7579f77SDag-Erling Smørgrav void *unbound_stat_malloc_lite(size_t size, const char* file, int line,
498b7579f77SDag-Erling Smørgrav         const char* func)
499b7579f77SDag-Erling Smørgrav {
500b7579f77SDag-Erling Smørgrav 	/*  [prefix .. len .. actual data .. suffix] */
501b7579f77SDag-Erling Smørgrav 	void* res = malloc(size+lite_pad*2+sizeof(size_t));
502b7579f77SDag-Erling Smørgrav 	if(!res) return NULL;
503b7579f77SDag-Erling Smørgrav 	memmove(res, lite_pre, lite_pad);
504b7579f77SDag-Erling Smørgrav 	memmove(res+lite_pad, &size, sizeof(size_t));
505b7579f77SDag-Erling Smørgrav 	memset(res+lite_pad+sizeof(size_t), 0x1a, size); /* init the memory */
506b7579f77SDag-Erling Smørgrav 	memmove(res+lite_pad+size+sizeof(size_t), lite_post, lite_pad);
507b7579f77SDag-Erling Smørgrav 	return res+lite_pad+sizeof(size_t);
508b7579f77SDag-Erling Smørgrav }
509b7579f77SDag-Erling Smørgrav 
510b7579f77SDag-Erling Smørgrav void *unbound_stat_calloc_lite(size_t nmemb, size_t size, const char* file,
511b7579f77SDag-Erling Smørgrav         int line, const char* func)
512b7579f77SDag-Erling Smørgrav {
51309a3aaf3SDag-Erling Smørgrav 	size_t req;
51409a3aaf3SDag-Erling Smørgrav 	void* res;
51509a3aaf3SDag-Erling Smørgrav 	if(nmemb != 0 && INT_MAX/nmemb < size)
51609a3aaf3SDag-Erling Smørgrav 		return NULL; /* integer overflow check */
51709a3aaf3SDag-Erling Smørgrav 	req = nmemb * size;
51809a3aaf3SDag-Erling Smørgrav 	res = malloc(req+lite_pad*2+sizeof(size_t));
519b7579f77SDag-Erling Smørgrav 	if(!res) return NULL;
520b7579f77SDag-Erling Smørgrav 	memmove(res, lite_pre, lite_pad);
521b7579f77SDag-Erling Smørgrav 	memmove(res+lite_pad, &req, sizeof(size_t));
522b7579f77SDag-Erling Smørgrav 	memset(res+lite_pad+sizeof(size_t), 0, req);
523b7579f77SDag-Erling Smørgrav 	memmove(res+lite_pad+req+sizeof(size_t), lite_post, lite_pad);
524b7579f77SDag-Erling Smørgrav 	return res+lite_pad+sizeof(size_t);
525b7579f77SDag-Erling Smørgrav }
526b7579f77SDag-Erling Smørgrav 
527b7579f77SDag-Erling Smørgrav void unbound_stat_free_lite(void *ptr, const char* file, int line,
528b7579f77SDag-Erling Smørgrav         const char* func)
529b7579f77SDag-Erling Smørgrav {
530b7579f77SDag-Erling Smørgrav 	void* real;
531b7579f77SDag-Erling Smørgrav 	size_t orig = 0;
532b7579f77SDag-Erling Smørgrav 	if(!ptr) return;
533b7579f77SDag-Erling Smørgrav 	real = ptr-lite_pad-sizeof(size_t);
534b7579f77SDag-Erling Smørgrav 	if(memcmp(real, lite_pre, lite_pad) != 0) {
535b7579f77SDag-Erling Smørgrav 		log_err("free(): prefix failed %s:%d %s", file, line, func);
536b7579f77SDag-Erling Smørgrav 		log_hex("prefix here", real, lite_pad);
537b7579f77SDag-Erling Smørgrav 		log_hex("  should be", lite_pre, lite_pad);
538b7579f77SDag-Erling Smørgrav 		fatal_exit("alloc assertion failed");
539b7579f77SDag-Erling Smørgrav 	}
540b7579f77SDag-Erling Smørgrav 	memmove(&orig, real+lite_pad, sizeof(size_t));
541b7579f77SDag-Erling Smørgrav 	if(memcmp(real+lite_pad+orig+sizeof(size_t), lite_post, lite_pad)!=0){
542b7579f77SDag-Erling Smørgrav 		log_err("free(): suffix failed %s:%d %s", file, line, func);
543b7579f77SDag-Erling Smørgrav 		log_err("alloc size is %d", (int)orig);
544b7579f77SDag-Erling Smørgrav 		log_hex("suffix here", real+lite_pad+orig+sizeof(size_t),
545b7579f77SDag-Erling Smørgrav 			lite_pad);
546b7579f77SDag-Erling Smørgrav 		log_hex("  should be", lite_post, lite_pad);
547b7579f77SDag-Erling Smørgrav 		fatal_exit("alloc assertion failed");
548b7579f77SDag-Erling Smørgrav 	}
549b7579f77SDag-Erling Smørgrav 	memset(real, 0xdd, orig+lite_pad*2+sizeof(size_t)); /* mark it */
550b7579f77SDag-Erling Smørgrav 	free(real);
551b7579f77SDag-Erling Smørgrav }
552b7579f77SDag-Erling Smørgrav 
553b7579f77SDag-Erling Smørgrav void *unbound_stat_realloc_lite(void *ptr, size_t size, const char* file,
554b7579f77SDag-Erling Smørgrav         int line, const char* func)
555b7579f77SDag-Erling Smørgrav {
556b7579f77SDag-Erling Smørgrav 	/* always free and realloc (no growing) */
557b7579f77SDag-Erling Smørgrav 	void* real, *newa;
558b7579f77SDag-Erling Smørgrav 	size_t orig = 0;
559b7579f77SDag-Erling Smørgrav 	if(!ptr) {
560b7579f77SDag-Erling Smørgrav 		/* like malloc() */
561b7579f77SDag-Erling Smørgrav 		return unbound_stat_malloc_lite(size, file, line, func);
562b7579f77SDag-Erling Smørgrav 	}
563b7579f77SDag-Erling Smørgrav 	if(!size) {
564b7579f77SDag-Erling Smørgrav 		/* like free() */
565b7579f77SDag-Erling Smørgrav 		unbound_stat_free_lite(ptr, file, line, func);
566b7579f77SDag-Erling Smørgrav 		return NULL;
567b7579f77SDag-Erling Smørgrav 	}
568b7579f77SDag-Erling Smørgrav 	/* change allocation size and copy */
569b7579f77SDag-Erling Smørgrav 	real = ptr-lite_pad-sizeof(size_t);
570b7579f77SDag-Erling Smørgrav 	if(memcmp(real, lite_pre, lite_pad) != 0) {
571b7579f77SDag-Erling Smørgrav 		log_err("realloc(): prefix failed %s:%d %s", file, line, func);
572b7579f77SDag-Erling Smørgrav 		log_hex("prefix here", real, lite_pad);
573b7579f77SDag-Erling Smørgrav 		log_hex("  should be", lite_pre, lite_pad);
574b7579f77SDag-Erling Smørgrav 		fatal_exit("alloc assertion failed");
575b7579f77SDag-Erling Smørgrav 	}
576b7579f77SDag-Erling Smørgrav 	memmove(&orig, real+lite_pad, sizeof(size_t));
577b7579f77SDag-Erling Smørgrav 	if(memcmp(real+lite_pad+orig+sizeof(size_t), lite_post, lite_pad)!=0){
578b7579f77SDag-Erling Smørgrav 		log_err("realloc(): suffix failed %s:%d %s", file, line, func);
579b7579f77SDag-Erling Smørgrav 		log_err("alloc size is %d", (int)orig);
580b7579f77SDag-Erling Smørgrav 		log_hex("suffix here", real+lite_pad+orig+sizeof(size_t),
581b7579f77SDag-Erling Smørgrav 			lite_pad);
582b7579f77SDag-Erling Smørgrav 		log_hex("  should be", lite_post, lite_pad);
583b7579f77SDag-Erling Smørgrav 		fatal_exit("alloc assertion failed");
584b7579f77SDag-Erling Smørgrav 	}
585b7579f77SDag-Erling Smørgrav 	/* new alloc and copy over */
586b7579f77SDag-Erling Smørgrav 	newa = unbound_stat_malloc_lite(size, file, line, func);
587b7579f77SDag-Erling Smørgrav 	if(!newa)
588b7579f77SDag-Erling Smørgrav 		return NULL;
589b7579f77SDag-Erling Smørgrav 	if(orig < size)
590b7579f77SDag-Erling Smørgrav 		memmove(newa, ptr, orig);
591b7579f77SDag-Erling Smørgrav 	else	memmove(newa, ptr, size);
592b7579f77SDag-Erling Smørgrav 	memset(real, 0xdd, orig+lite_pad*2+sizeof(size_t)); /* mark it */
593b7579f77SDag-Erling Smørgrav 	free(real);
594b7579f77SDag-Erling Smørgrav 	return newa;
595b7579f77SDag-Erling Smørgrav }
596b7579f77SDag-Erling Smørgrav 
597b7579f77SDag-Erling Smørgrav char* unbound_strdup_lite(const char* s, const char* file, int line,
598b7579f77SDag-Erling Smørgrav         const char* func)
599b7579f77SDag-Erling Smørgrav {
600b7579f77SDag-Erling Smørgrav 	/* this routine is made to make sure strdup() uses the malloc_lite */
601b7579f77SDag-Erling Smørgrav 	size_t l = strlen(s)+1;
602b7579f77SDag-Erling Smørgrav 	char* n = (char*)unbound_stat_malloc_lite(l, file, line, func);
603b7579f77SDag-Erling Smørgrav 	if(!n) return NULL;
604b7579f77SDag-Erling Smørgrav 	memmove(n, s, l);
605b7579f77SDag-Erling Smørgrav 	return n;
606b7579f77SDag-Erling Smørgrav }
607b7579f77SDag-Erling Smørgrav 
608b7579f77SDag-Erling Smørgrav char* unbound_lite_wrapstr(char* s)
609b7579f77SDag-Erling Smørgrav {
610b7579f77SDag-Erling Smørgrav 	char* n = unbound_strdup_lite(s, __FILE__, __LINE__, __func__);
611b7579f77SDag-Erling Smørgrav 	free(s);
612b7579f77SDag-Erling Smørgrav 	return n;
613b7579f77SDag-Erling Smørgrav }
614b7579f77SDag-Erling Smørgrav 
61517d15b25SDag-Erling Smørgrav #undef sldns_pkt2wire
61617d15b25SDag-Erling Smørgrav sldns_status unbound_lite_pkt2wire(uint8_t **dest, const sldns_pkt *p,
617b7579f77SDag-Erling Smørgrav 	size_t *size)
618b7579f77SDag-Erling Smørgrav {
619b7579f77SDag-Erling Smørgrav 	uint8_t* md = NULL;
620b7579f77SDag-Erling Smørgrav 	size_t ms = 0;
62117d15b25SDag-Erling Smørgrav 	sldns_status s = sldns_pkt2wire(&md, p, &ms);
622b7579f77SDag-Erling Smørgrav 	if(md) {
623b7579f77SDag-Erling Smørgrav 		*dest = unbound_stat_malloc_lite(ms, __FILE__, __LINE__,
624b7579f77SDag-Erling Smørgrav 			__func__);
625b7579f77SDag-Erling Smørgrav 		*size = ms;
626b7579f77SDag-Erling Smørgrav 		if(!*dest) { free(md); return LDNS_STATUS_MEM_ERR; }
627b7579f77SDag-Erling Smørgrav 		memcpy(*dest, md, ms);
628b7579f77SDag-Erling Smørgrav 		free(md);
629b7579f77SDag-Erling Smørgrav 	} else {
630b7579f77SDag-Erling Smørgrav 		*dest = NULL;
631b7579f77SDag-Erling Smørgrav 		*size = 0;
632b7579f77SDag-Erling Smørgrav 	}
633b7579f77SDag-Erling Smørgrav 	return s;
634b7579f77SDag-Erling Smørgrav }
635b7579f77SDag-Erling Smørgrav 
636b7579f77SDag-Erling Smørgrav #undef i2d_DSA_SIG
637b7579f77SDag-Erling Smørgrav int unbound_lite_i2d_DSA_SIG(DSA_SIG* dsasig, unsigned char** sig)
638b7579f77SDag-Erling Smørgrav {
639b7579f77SDag-Erling Smørgrav 	unsigned char* n = NULL;
640b7579f77SDag-Erling Smørgrav 	int r= i2d_DSA_SIG(dsasig, &n);
641b7579f77SDag-Erling Smørgrav 	if(n) {
642b7579f77SDag-Erling Smørgrav 		*sig = unbound_stat_malloc_lite((size_t)r, __FILE__, __LINE__,
643b7579f77SDag-Erling Smørgrav 			__func__);
644b7579f77SDag-Erling Smørgrav 		if(!*sig) return -1;
645b7579f77SDag-Erling Smørgrav 		memcpy(*sig, n, (size_t)r);
646b7579f77SDag-Erling Smørgrav 		free(n);
647b7579f77SDag-Erling Smørgrav 		return r;
648b7579f77SDag-Erling Smørgrav 	}
649b7579f77SDag-Erling Smørgrav 	*sig = NULL;
650b7579f77SDag-Erling Smørgrav 	return r;
651b7579f77SDag-Erling Smørgrav }
652b7579f77SDag-Erling Smørgrav 
653b7579f77SDag-Erling Smørgrav #endif /* UNBOUND_ALLOC_LITE */
654