]>
git.ipfire.org Git - thirdparty/bird.git/blob - lib/resource.c
2 * BIRD Resource Manager
4 * (c) 1998--2000 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL.
13 #include "nest/bird.h"
14 #include "lib/resource.h"
15 #include "lib/string.h"
20 * Resource pools (&pool) are just containers holding a list of
21 * other resources. Freeing a pool causes all the listed resources
22 * to be freed as well. Each existing &resource is linked to some pool
23 * except for a root pool which isn't linked anywhere, so all the
24 * resources form a tree structure with internal nodes corresponding
25 * to pools and leaves being the other resources.
27 * Example: Almost all modules of BIRD have their private pool which
28 * is freed upon shutdown of the module.
37 static void pool_dump(resource
*);
38 static void pool_free(resource
*);
39 static resource
*pool_lookup(resource
*, unsigned long);
40 static size_t pool_memsize(resource
*P
);
42 static struct resclass pool_class
= {
56 * rp_new - create a resource pool
58 * @name: pool name (to be included in debugging dumps)
60 * rp_new() creates a new resource pool inside the specified
64 rp_new(pool
*p
, char *name
)
66 pool
*z
= ralloc(p
, &pool_class
);
68 init_list(&z
->inside
);
73 pool_free(resource
*P
)
79 while (rr
= (resource
*) r
->n
.next
)
88 pool_dump(resource
*P
)
93 debug("%s\n", p
->name
);
95 WALK_LIST(r
, p
->inside
)
101 pool_memsize(resource
*P
)
103 pool
*p
= (pool
*) P
;
105 size_t sum
= sizeof(pool
) + ALLOC_OVERHEAD
;
107 WALK_LIST(r
, p
->inside
)
114 pool_lookup(resource
*P
, unsigned long a
)
116 pool
*p
= (pool
*) P
;
119 WALK_LIST(r
, p
->inside
)
120 if (r
->class->lookup
&& (q
= r
->class->lookup(r
, a
)))
126 * rmove - move a resource
128 * @p: pool to move the resource to
130 * rmove() moves a resource from one pool to another.
133 void rmove(void *res
, pool
*p
)
141 add_tail(&p
->inside
, &r
->n
);
146 * rfree - free a resource
149 * rfree() frees the given resource and all information associated
150 * with it. In case it's a resource pool, it also frees all the objects
151 * living inside the pool.
153 * It works by calling a class-specific freeing function.
170 * rdump - dump a resource
173 * This function prints out all available information about the given
174 * resource to the debugging output.
176 * It works by calling a class-specific dump function.
184 bsprintf(x
, "%%%ds%%p ", indent
);
188 debug("%s ", r
->class->name
);
201 if (!r
->class->memsize
)
202 return r
->class->size
+ ALLOC_OVERHEAD
;
203 return r
->class->memsize(r
);
207 * ralloc - create a resource
208 * @p: pool to create the resource in
209 * @c: class of the new resource
211 * This function is called by the resource classes to create a new
212 * resource of the specified class and link it to the given pool.
213 * Allocated memory is zeroed. Size of the resource structure is taken
214 * from the @size field of the &resclass.
217 ralloc(pool
*p
, struct resclass
*c
)
219 resource
*r
= xmalloc(c
->size
);
224 add_tail(&p
->inside
, &r
->n
);
229 * rlookup - look up a memory location
232 * This function examines all existing resources to see whether
233 * the address @a is inside any resource. It's used for debugging
236 * It works by calling a class-specific lookup function for each
240 rlookup(unsigned long a
)
244 debug("Looking up %08lx\n", a
);
245 if (r
= pool_lookup(&root_pool
.r
, a
))
248 debug("Not found.\n");
252 * resource_init - initialize the resource manager
254 * This function is called during BIRD startup. It initializes
255 * all data structures of the resource manager and creates the
261 root_pool
.r
.class = &pool_class
;
262 root_pool
.name
= "Root";
263 init_list(&root_pool
.inside
);
269 * Memory blocks are pieces of contiguous allocated memory.
270 * They are a bit non-standard since they are represented not by a pointer
271 * to &resource, but by a void pointer to the start of data of the
272 * memory block. All memory block functions know how to locate the header
273 * given the data pointer.
275 * Example: All "unique" data structures such as hash tables are allocated
282 uintptr_t data_align
[0];
286 static void mbl_free(resource
*r UNUSED
)
290 static void mbl_debug(resource
*r
)
292 struct mblock
*m
= (struct mblock
*) r
;
294 debug("(size=%d)\n", m
->size
);
298 mbl_lookup(resource
*r
, unsigned long a
)
300 struct mblock
*m
= (struct mblock
*) r
;
302 if ((unsigned long) m
->data
<= a
&& (unsigned long) m
->data
+ m
->size
> a
)
308 mbl_memsize(resource
*r
)
310 struct mblock
*m
= (struct mblock
*) r
;
311 return ALLOC_OVERHEAD
+ sizeof(struct mblock
) + m
->size
;
314 static struct resclass mb_class
= {
324 * mb_alloc - allocate a memory block
326 * @size: size of the block
328 * mb_alloc() allocates memory of a given size and creates
329 * a memory block resource representing this memory chunk
332 * Please note that mb_alloc() returns a pointer to the memory
333 * chunk, not to the resource, hence you have to free it using
334 * mb_free(), not rfree().
337 mb_alloc(pool
*p
, unsigned size
)
339 struct mblock
*b
= xmalloc(sizeof(struct mblock
) + size
);
341 b
->r
.class = &mb_class
;
342 add_tail(&p
->inside
, &b
->r
.n
);
348 * mb_allocz - allocate and clear a memory block
350 * @size: size of the block
352 * mb_allocz() allocates memory of a given size, initializes it to
353 * zeroes and creates a memory block resource representing this memory
354 * chunk in the pool @p.
356 * Please note that mb_allocz() returns a pointer to the memory
357 * chunk, not to the resource, hence you have to free it using
358 * mb_free(), not rfree().
361 mb_allocz(pool
*p
, unsigned size
)
363 void *x
= mb_alloc(p
, size
);
369 * mb_realloc - reallocate a memory block
371 * @size: new size of the block
373 * mb_realloc() changes the size of the memory block @m to a given size.
374 * The contents will be unchanged to the minimum of the old and new sizes;
375 * newly allocated memory will be uninitialized. Contrary to realloc()
376 * behavior, @m must be non-NULL, because the resource pool is inherited
379 * Like mb_alloc(), mb_realloc() also returns a pointer to the memory
380 * chunk, not to the resource, hence you have to free it using
381 * mb_free(), not rfree().
384 mb_realloc(void *m
, unsigned size
)
386 struct mblock
*ob
= NULL
;
390 ob
= SKIP_BACK(struct mblock
, data
, m
);
395 struct mblock
*b
= xrealloc(ob
, sizeof(struct mblock
) + size
);
396 replace_node(&b
->r
.n
, &b
->r
.n
);
403 * mb_free - free a memory block
406 * mb_free() frees all memory associated with the block @m.
414 struct mblock
*b
= SKIP_BACK(struct mblock
, data
, m
);
420 #define STEP_UP(x) ((x) + (x)/2 + 4)
423 buffer_realloc(void **buf
, unsigned *size
, unsigned need
, unsigned item_size
)
425 unsigned nsize
= MIN(*size
, need
);
428 nsize
= STEP_UP(nsize
);
430 *buf
= mb_realloc(*buf
, nsize
* item_size
);