1998-05-04 00:43:39 +08: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"
|
|
|
|
|
1998-12-06 19:59:18 +08:00
|
|
|
struct lp_chunk {
|
|
|
|
struct lp_chunk *next;
|
1998-05-04 00:43:39 +08:00
|
|
|
byte data[0];
|
|
|
|
};
|
|
|
|
|
1998-12-06 19:59:18 +08:00
|
|
|
struct linpool {
|
1998-05-04 00:43:39 +08:00
|
|
|
resource r;
|
|
|
|
byte *ptr, *end;
|
1998-12-06 19:59:18 +08:00
|
|
|
struct lp_chunk *first, **plast;
|
1998-05-04 00:43:39 +08:00
|
|
|
unsigned chunk_size, threshold, total;
|
|
|
|
};
|
|
|
|
|
1998-12-06 19:59:18 +08:00
|
|
|
void lp_free(resource *);
|
|
|
|
void lp_dump(resource *);
|
1998-05-04 00:43:39 +08:00
|
|
|
|
1998-12-06 19:59:18 +08:00
|
|
|
static struct resclass lp_class = {
|
|
|
|
"LinPool",
|
|
|
|
sizeof(struct linpool),
|
|
|
|
lp_free,
|
|
|
|
lp_dump
|
1998-05-04 00:43:39 +08:00
|
|
|
};
|
|
|
|
|
1998-12-06 19:59:18 +08:00
|
|
|
linpool
|
|
|
|
*lp_new(pool *p, unsigned blk)
|
1998-05-04 00:43:39 +08:00
|
|
|
{
|
1998-12-06 19:59:18 +08:00
|
|
|
linpool *m = ralloc(p, &lp_class);
|
1998-05-04 00:43:39 +08:00
|
|
|
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 *
|
1998-12-06 19:59:18 +08:00
|
|
|
lp_alloc(linpool *m, unsigned size)
|
1998-05-04 00:43:39 +08:00
|
|
|
{
|
|
|
|
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
|
|
|
|
{
|
1998-12-06 19:59:18 +08:00
|
|
|
struct lp_chunk *c;
|
1998-05-04 00:43:39 +08:00
|
|
|
if (size >= m->threshold)
|
|
|
|
{
|
1998-12-06 19:59:18 +08:00
|
|
|
c = xmalloc(sizeof(struct lp_chunk) + size);
|
1998-05-04 00:43:39 +08:00
|
|
|
m->total += size;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
1998-12-06 19:59:18 +08:00
|
|
|
c = xmalloc(sizeof(struct lp_chunk) + m->chunk_size);
|
1998-05-04 00:43:39 +08:00
|
|
|
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 *
|
1998-12-06 19:59:18 +08:00
|
|
|
lp_allocu(linpool *m, unsigned size)
|
1998-05-04 00:43:39 +08:00
|
|
|
{
|
|
|
|
byte *a = m->ptr;
|
|
|
|
byte *e = a + size;
|
|
|
|
|
|
|
|
if (e <= m->end)
|
|
|
|
{
|
|
|
|
m->ptr = e;
|
|
|
|
return a;
|
|
|
|
}
|
1998-12-06 19:59:18 +08:00
|
|
|
return lp_alloc(m, size);
|
1998-05-04 00:43:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
1998-12-06 19:59:18 +08:00
|
|
|
lp_allocz(linpool *m, unsigned size)
|
1998-05-04 00:43:39 +08:00
|
|
|
{
|
1998-12-06 19:59:18 +08:00
|
|
|
void *z = lp_alloc(m, size);
|
1998-05-04 00:43:39 +08:00
|
|
|
|
|
|
|
bzero(z, size);
|
|
|
|
return z;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-12-06 19:59:18 +08:00
|
|
|
lp_free(resource *r)
|
1998-05-04 00:43:39 +08:00
|
|
|
{
|
1998-12-06 19:59:18 +08:00
|
|
|
linpool *m = (linpool *) r;
|
|
|
|
struct lp_chunk *c, *d;
|
1998-05-04 00:43:39 +08:00
|
|
|
|
|
|
|
for(d=m->first; d; d = c)
|
|
|
|
{
|
|
|
|
c = d->next;
|
|
|
|
xfree(d);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-12-06 19:59:18 +08:00
|
|
|
lp_dump(resource *r)
|
1998-05-04 00:43:39 +08:00
|
|
|
{
|
1998-12-06 19:59:18 +08:00
|
|
|
linpool *m = (linpool *) r;
|
|
|
|
struct lp_chunk *c;
|
1998-05-04 00:43:39 +08:00
|
|
|
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);
|
|
|
|
}
|