1998-05-03 16:43:39 +00:00
|
|
|
/*
|
|
|
|
* BIRD Resource Manager -- Memory Pools
|
|
|
|
*
|
|
|
|
* (c) 1998 Martin Mares <mj@ucw.cz>
|
|
|
|
*
|
|
|
|
* Can be freely distributed and used under the terms of the GNU GPL.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include "nest/bird.h"
|
|
|
|
#include "lib/resource.h"
|
|
|
|
|
|
|
|
struct mp_chunk {
|
|
|
|
struct mp_chunk *next;
|
|
|
|
byte data[0];
|
|
|
|
};
|
|
|
|
|
|
|
|
struct mempool {
|
|
|
|
resource r;
|
|
|
|
byte *ptr, *end;
|
|
|
|
struct mp_chunk *first, **plast;
|
|
|
|
unsigned chunk_size, threshold, total;
|
|
|
|
};
|
|
|
|
|
|
|
|
void mp_free(resource *);
|
|
|
|
void mp_dump(resource *);
|
|
|
|
|
1998-05-24 14:46:20 +00:00
|
|
|
static struct resclass mp_class = {
|
1998-05-03 16:43:39 +00:00
|
|
|
"MemPool",
|
|
|
|
sizeof(struct mempool),
|
|
|
|
mp_free,
|
|
|
|
mp_dump
|
|
|
|
};
|
|
|
|
|
|
|
|
mempool
|
|
|
|
*mp_new(pool *p, unsigned blk)
|
|
|
|
{
|
|
|
|
mempool *m = ralloc(p, &mp_class);
|
|
|
|
m->ptr = m->end = NULL;
|
|
|
|
m->first = NULL;
|
|
|
|
m->plast = &m->first;
|
|
|
|
m->chunk_size = blk;
|
|
|
|
m->threshold = 3*blk/4;
|
|
|
|
m->total = 0;
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
mp_alloc(mempool *m, unsigned size)
|
|
|
|
{
|
|
|
|
byte *a = (byte *) ALIGN((unsigned long) m->ptr, CPU_STRUCT_ALIGN);
|
|
|
|
byte *e = a + size;
|
|
|
|
|
|
|
|
if (e <= m->end)
|
|
|
|
{
|
|
|
|
m->ptr = e;
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
struct mp_chunk *c;
|
|
|
|
if (size >= m->threshold)
|
|
|
|
{
|
|
|
|
c = xmalloc(sizeof(struct mp_chunk) + size);
|
|
|
|
m->total += size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
c = xmalloc(sizeof(struct mp_chunk) + m->chunk_size);
|
|
|
|
m->ptr = c->data + size;
|
|
|
|
m->end = c->data + m->chunk_size;
|
|
|
|
m->total += m->chunk_size;
|
|
|
|
}
|
|
|
|
*m->plast = c;
|
|
|
|
m->plast = &c->next;
|
|
|
|
c->next = NULL;
|
|
|
|
return c->data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
mp_allocu(mempool *m, unsigned size)
|
|
|
|
{
|
|
|
|
byte *a = m->ptr;
|
|
|
|
byte *e = a + size;
|
|
|
|
|
|
|
|
if (e <= m->end)
|
|
|
|
{
|
|
|
|
m->ptr = e;
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
return mp_alloc(m, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
mp_allocz(mempool *m, unsigned size)
|
|
|
|
{
|
|
|
|
void *z = mp_alloc(m, size);
|
|
|
|
|
|
|
|
bzero(z, size);
|
|
|
|
return z;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mp_free(resource *r)
|
|
|
|
{
|
|
|
|
mempool *m = (mempool *) r;
|
|
|
|
struct mp_chunk *c, *d;
|
|
|
|
|
|
|
|
for(d=m->first; d; d = c)
|
|
|
|
{
|
|
|
|
c = d->next;
|
|
|
|
xfree(d);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
mp_dump(resource *r)
|
|
|
|
{
|
|
|
|
mempool *m = (mempool *) r;
|
|
|
|
struct mp_chunk *c;
|
|
|
|
int cnt;
|
|
|
|
|
|
|
|
for(cnt=0, c=m->first; c; c=c->next, cnt++)
|
|
|
|
;
|
|
|
|
debug("(chunk=%d threshold=%d count=%d total=%d)\n",
|
|
|
|
m->chunk_size,
|
|
|
|
m->threshold,
|
|
|
|
cnt,
|
|
|
|
m->total);
|
|
|
|
}
|