]>
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
, const 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.
171 * rdump - dump a resource
174 * This function prints out all available information about the given
175 * resource to the debugging output.
177 * It works by calling a class-specific dump function.
185 bsprintf(x
, "%%%ds%%p ", indent
);
189 debug("%s ", r
->class->name
);
202 if (!r
->class->memsize
)
203 return r
->class->size
+ ALLOC_OVERHEAD
;
204 return r
->class->memsize(r
);
208 * ralloc - create a resource
209 * @p: pool to create the resource in
210 * @c: class of the new resource
212 * This function is called by the resource classes to create a new
213 * resource of the specified class and link it to the given pool.
214 * Allocated memory is zeroed. Size of the resource structure is taken
215 * from the @size field of the &resclass.
218 ralloc(pool
*p
, struct resclass
*c
)
220 resource
*r
= xmalloc(c
->size
);
225 add_tail(&p
->inside
, &r
->n
);
230 * rlookup - look up a memory location
233 * This function examines all existing resources to see whether
234 * the address @a is inside any resource. It's used for debugging
237 * It works by calling a class-specific lookup function for each
241 rlookup(unsigned long a
)
245 debug("Looking up %08lx\n", a
);
246 if (r
= pool_lookup(&root_pool
.r
, a
))
249 debug("Not found.\n");
253 * resource_init - initialize the resource manager
255 * This function is called during BIRD startup. It initializes
256 * all data structures of the resource manager and creates the
262 root_pool
.r
.class = &pool_class
;
263 root_pool
.name
= "Root";
264 init_list(&root_pool
.inside
);
270 * Memory blocks are pieces of contiguous allocated memory.
271 * They are a bit non-standard since they are represented not by a pointer
272 * to &resource, but by a void pointer to the start of data of the
273 * memory block. All memory block functions know how to locate the header
274 * given the data pointer.
276 * Example: All "unique" data structures such as hash tables are allocated
283 uintptr_t data_align
[0];
287 static void mbl_free(resource
*r UNUSED
)
291 static void mbl_debug(resource
*r
)
293 struct mblock
*m
= (struct mblock
*) r
;
295 debug("(size=%d)\n", m
->size
);
299 mbl_lookup(resource
*r
, unsigned long a
)
301 struct mblock
*m
= (struct mblock
*) r
;
303 if ((unsigned long) m
->data
<= a
&& (unsigned long) m
->data
+ m
->size
> a
)
309 mbl_memsize(resource
*r
)
311 struct mblock
*m
= (struct mblock
*) r
;
312 return ALLOC_OVERHEAD
+ sizeof(struct mblock
) + m
->size
;
315 static struct resclass mb_class
= {
325 * mb_alloc - allocate a memory block
327 * @size: size of the block
329 * mb_alloc() allocates memory of a given size and creates
330 * a memory block resource representing this memory chunk
333 * Please note that mb_alloc() returns a pointer to the memory
334 * chunk, not to the resource, hence you have to free it using
335 * mb_free(), not rfree().
338 mb_alloc(pool
*p
, unsigned size
)
340 struct mblock
*b
= xmalloc(sizeof(struct mblock
) + size
);
342 b
->r
.class = &mb_class
;
344 add_tail(&p
->inside
, &b
->r
.n
);
350 * mb_allocz - allocate and clear a memory block
352 * @size: size of the block
354 * mb_allocz() allocates memory of a given size, initializes it to
355 * zeroes and creates a memory block resource representing this memory
356 * chunk in the pool @p.
358 * Please note that mb_allocz() returns a pointer to the memory
359 * chunk, not to the resource, hence you have to free it using
360 * mb_free(), not rfree().
363 mb_allocz(pool
*p
, unsigned size
)
365 void *x
= mb_alloc(p
, size
);
371 * mb_realloc - reallocate a memory block
373 * @size: new size of the block
375 * mb_realloc() changes the size of the memory block @m to a given size.
376 * The contents will be unchanged to the minimum of the old and new sizes;
377 * newly allocated memory will be uninitialized. Contrary to realloc()
378 * behavior, @m must be non-NULL, because the resource pool is inherited
381 * Like mb_alloc(), mb_realloc() also returns a pointer to the memory
382 * chunk, not to the resource, hence you have to free it using
383 * mb_free(), not rfree().
386 mb_realloc(void *m
, unsigned size
)
388 struct mblock
*b
= SKIP_BACK(struct mblock
, data
, m
);
390 b
= xrealloc(b
, sizeof(struct mblock
) + size
);
391 update_node(&b
->r
.n
);
398 * mb_free - free a memory block
401 * mb_free() frees all memory associated with the block @m.
409 struct mblock
*b
= SKIP_BACK(struct mblock
, data
, m
);
415 #define STEP_UP(x) ((x) + (x)/2 + 4)
418 buffer_realloc(void **buf
, unsigned *size
, unsigned need
, unsigned item_size
)
420 unsigned nsize
= MIN(*size
, need
);
423 nsize
= STEP_UP(nsize
);
425 *buf
= mb_realloc(*buf
, nsize
* item_size
);