/* * BIRD Resource Manager * * (c) 1998 Martin Mares <mj@ucw.cz> * * Can be freely distributed and used under the terms of the GNU GPL. */ #include <stdio.h> #include <stdlib.h> #include "nest/bird.h" #include "lib/resource.h" #include "lib/string.h" struct pool { resource r; list inside; char *name; }; static void pool_dump(resource *); static void pool_free(resource *); static resource *pool_lookup(resource *, unsigned long); static struct resclass pool_class = { "Pool", sizeof(pool), pool_free, pool_dump, pool_lookup }; pool root_pool; static int indent; pool * rp_new(pool *p, char *name) { pool *z = ralloc(p, &pool_class); z->name = name; init_list(&z->inside); return z; } static void pool_free(resource *P) { pool *p = (pool *) P; resource *r, *rr; r = HEAD(p->inside); while (rr = (resource *) r->n.next) { r->class->free(r); xfree(r); r = rr; } } static void pool_dump(resource *P) { pool *p = (pool *) P; resource *r; debug("%s\n", p->name); indent += 3; WALK_LIST(r, p->inside) rdump(r); indent -= 3; } static resource * pool_lookup(resource *P, unsigned long a) { pool *p = (pool *) P; resource *r, *q; WALK_LIST(r, p->inside) if (r->class->lookup && (q = r->class->lookup(r, a))) return q; return NULL; } void rfree(void *res) { resource *r = res; if (r) { if (r->n.next) rem_node(&r->n); r->class->free(r); xfree(r); } } void rdump(void *res) { char x[16]; resource *r = res; bsprintf(x, "%%%ds%%08x ", indent); debug(x, "", (int) r); if (r) { debug("%s ", r->class->name); r->class->dump(r); } else debug("NULL\n"); } void * ralloc(pool *p, struct resclass *c) { resource *r = xmalloc(c->size); r->class = c; add_tail(&p->inside, &r->n); return r; } void rlookup(unsigned long a) { resource *r; debug("Looking up %08lx\n", a); if (r = pool_lookup(&root_pool.r, a)) rdump(r); else debug("Not found.\n"); } void resource_init(void) { root_pool.r.class = &pool_class; root_pool.name = "Root"; init_list(&root_pool.inside); } /* * Memory blocks. */ struct mblock { resource r; unsigned size; byte data[0]; }; static void mbl_free(resource *r) { } static void mbl_debug(resource *r) { struct mblock *m = (struct mblock *) r; debug("(size=%d)\n", m->size); } static resource * mbl_lookup(resource *r, unsigned long a) { struct mblock *m = (struct mblock *) r; if ((unsigned long) m->data <= a && (unsigned long) m->data + m->size > a) return r; return NULL; } static struct resclass mb_class = { "Memory", 0, mbl_free, mbl_debug, mbl_lookup }; void * mb_alloc(pool *p, unsigned size) { struct mblock *b = xmalloc(sizeof(struct mblock) + size); b->r.class = &mb_class; add_tail(&p->inside, &b->r.n); b->size = size; return b->data; } void * mb_allocz(pool *p, unsigned size) { void *x = mb_alloc(p, size); bzero(x, size); return x; } void mb_free(void *m) { struct mblock *b = SKIP_BACK(struct mblock, data, m); rfree(b); }