1538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/*
2538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *	Copyright (c) 2004i-2010 Alex Pankratov. All rights reserved.
3538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *
4538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *	Hierarchical memory allocator, 1.2.1
5538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *	http://swapped.cc/halloc
6538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber */
7538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
8538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/*
9538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *	The program is distributed under terms of BSD license.
10538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *	You can obtain the copy of the license by visiting:
11538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *
12538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *	http://www.opensource.org/licenses/bsd-license.php
13538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber */
14538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
15538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include <stdlib.h>  /* realloc */
16538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include <string.h>  /* memset & co */
17538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
18538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include "../halloc.h"
19538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include "align.h"
20538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include "hlist.h"
21538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
22538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/*
23538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *	block control header
24538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber */
25538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubertypedef struct hblock
26538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
27538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#ifndef NDEBUG
28538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define HH_MAGIC    0x20040518L
29538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	long          magic;
30538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#endif
31538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	hlist_item_t  siblings; /* 2 pointers */
32538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	hlist_head_t  children; /* 1 pointer  */
33538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	max_align_t   data[1];  /* not allocated, see below */
34538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
35538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber} hblock_t;
36538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
37538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define sizeof_hblock offsetof(hblock_t, data)
38538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
39538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/*
40538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *
41538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber */
42538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberrealloc_t halloc_allocator = NULL;
43538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
44538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define allocator halloc_allocator
45538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
46538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/*
47538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *	static methods
48538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber */
49538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void _set_allocator(void);
50538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void * _realloc(void * ptr, size_t n);
51538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
52538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int  _relate(hblock_t * b, hblock_t * p);
53538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void _free_children(hblock_t * p);
54538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
55538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/*
56538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *	Core API
57538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber */
58538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubervoid * halloc(void * ptr, size_t len)
59538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
60538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	hblock_t * p;
61538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
62538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	/* set up default allocator */
63538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	if (! allocator)
64538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	{
65538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		_set_allocator();
66538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		assert(allocator);
67538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	}
68538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
69538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	/* calloc */
70538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	if (! ptr)
71538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	{
72538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		if (! len)
73538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber			return NULL;
74538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
75538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		p = allocator(0, len + sizeof_hblock);
76538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		if (! p)
77538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber			return NULL;
78538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#ifndef NDEBUG
79538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		p->magic = HH_MAGIC;
80538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#endif
81538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		hlist_init(&p->children);
82538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		hlist_init_item(&p->siblings);
83538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
84538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		return p->data;
85538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	}
86538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
87538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	p = structof(ptr, hblock_t, data);
88538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	assert(p->magic == HH_MAGIC);
89538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
90538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	/* realloc */
91538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	if (len)
92538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	{
93538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		p = allocator(p, len + sizeof_hblock);
94538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		if (! p)
95538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber			return NULL;
96538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
97538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		hlist_relink(&p->siblings);
98538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		hlist_relink_head(&p->children);
99538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
100538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		return p->data;
101538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	}
102538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
103538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	/* free */
104538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	_free_children(p);
105538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	hlist_del(&p->siblings);
106538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	allocator(p, 0);
107538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
108538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	return NULL;
109538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
110538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
111538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubervoid hattach(void * block, void * parent)
112538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
113538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	hblock_t * b, * p;
114538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
115538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	if (! block)
116538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	{
117538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		assert(! parent);
118538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		return;
119538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	}
120538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
121538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	/* detach */
122538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	b = structof(block, hblock_t, data);
123538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	assert(b->magic == HH_MAGIC);
124538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
125538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	hlist_del(&b->siblings);
126538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
127538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	if (! parent)
128538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		return;
129538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
130538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	/* attach */
131538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	p = structof(parent, hblock_t, data);
132538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	assert(p->magic == HH_MAGIC);
133538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
134538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	/* sanity checks */
135538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	assert(b != p);          /* trivial */
136538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	assert(! _relate(p, b)); /* heavy ! */
137538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
138538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	hlist_add(&p->children, &b->siblings);
139538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
140538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
141538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/*
142538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *	malloc/free api
143538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber */
144538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubervoid * h_malloc(size_t len)
145538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
146538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	return halloc(0, len);
147538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
148538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
149538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubervoid * h_calloc(size_t n, size_t len)
150538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
151538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	void * ptr = halloc(0, len*=n);
152538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	return ptr ? memset(ptr, 0, len) : NULL;
153538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
154538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
155538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubervoid * h_realloc(void * ptr, size_t len)
156538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
157538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	return halloc(ptr, len);
158538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
159538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
160538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubervoid   h_free(void * ptr)
161538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
162538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	halloc(ptr, 0);
163538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
164538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
165538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberchar * h_strdup(const char * str)
166538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
167538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	size_t len = strlen(str);
168538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	char * ptr = halloc(0, len + 1);
169538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	return ptr ? (ptr[len] = 0, memcpy(ptr, str, len)) : NULL;
170538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
171538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
172538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/*
173538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *	static stuff
174538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber */
175538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void _set_allocator(void)
176538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
177538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	void * p;
178538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	assert(! allocator);
179538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
180538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	/*
181538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 *	the purpose of the test below is to check the behaviour
182538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 *	of realloc(ptr, 0), which is defined in the standard
183538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 *	as an implementation-specific. if it returns zero,
184538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 *	then it's equivalent to free(). it can however return
185538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 *	non-zero, in which case it cannot be used for freeing
186538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 *	memory blocks and we'll need to supply our own version
187538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 *
188538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 *	Thanks to Stan Tobias for pointing this tricky part out.
189538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 */
190538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	allocator = realloc;
191538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	if (! (p = malloc(1)))
192538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		/* hmm */
193538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		return;
194538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
195538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	if ((p = realloc(p, 0)))
196538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	{
197538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		/* realloc cannot be used as free() */
198538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		allocator = _realloc;
199538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		free(p);
200538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	}
201538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
202538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
203538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void * _realloc(void * ptr, size_t n)
204538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
205538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	/*
206538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 *	free'ing realloc()
207538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 */
208538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	if (n)
209538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		return realloc(ptr, n);
210538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	free(ptr);
211538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	return NULL;
212538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
213538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
214538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int _relate(hblock_t * b, hblock_t * p)
215538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
216538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	hlist_item_t * i;
217538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
218538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	if (!b || !p)
219538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		return 0;
220538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
221538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	/*
222538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 *  since there is no 'parent' pointer, which would've allowed
223538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 *  O(log(n)) upward traversal, the check must use O(n) downward
224538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 *  iteration of the entire hierarchy; and this can be VERY SLOW
225538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 */
226538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	hlist_for_each(i, &p->children)
227538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	{
228538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		hblock_t * q = structof(i, hblock_t, siblings);
229538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		if (q == b || _relate(b, q))
230538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber			return 1;
231538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	}
232538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	return 0;
233538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
234538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
235538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void _free_children(hblock_t * p)
236538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
237538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	hlist_item_t * i, * tmp;
238538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
239538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#ifndef NDEBUG
240538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	/*
241538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 *	this catches loops in hierarchy with almost zero
242538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 *	overhead (compared to _relate() running time)
243538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	 */
244538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	assert(p && p->magic == HH_MAGIC);
245538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	p->magic = 0;
246538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#endif
247538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	hlist_for_each_safe(i, tmp, &p->children)
248538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	{
249538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		hblock_t * q = structof(i, hblock_t, siblings);
250538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		_free_children(q);
251538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber		allocator(q, 0);
252538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber	}
253538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
254538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
255