summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/mempool.c51
-rw-r--r--lib/resource.h3
2 files changed, 42 insertions, 12 deletions
diff --git a/lib/mempool.c b/lib/mempool.c
index f3b84a57..49e6e900 100644
--- a/lib/mempool.c
+++ b/lib/mempool.c
@@ -1,7 +1,7 @@
/*
* BIRD Resource Manager -- Memory Pools
*
- * (c) 1998 Martin Mares <mj@ucw.cz>
+ * (c) 1998--1999 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
@@ -20,8 +20,9 @@ struct lp_chunk {
struct linpool {
resource r;
byte *ptr, *end;
- struct lp_chunk *first, **plast;
- unsigned chunk_size, threshold, total;
+ struct lp_chunk *first, *current, **plast; /* Normal (reusable) chunks */
+ struct lp_chunk *first_large; /* Large chunks */
+ unsigned chunk_size, threshold, total, total_large;
};
void lp_free(resource *);
@@ -39,11 +40,12 @@ linpool
{
linpool *m = ralloc(p, &lp_class);
m->ptr = m->end = NULL;
- m->first = NULL;
+ m->first = m->current = NULL;
m->plast = &m->first;
+ m->first_large = NULL;
m->chunk_size = blk;
m->threshold = 3*blk/4;
- m->total = 0;
+ m->total = m->total_large = 0;
return m;
}
@@ -63,19 +65,30 @@ lp_alloc(linpool *m, unsigned size)
struct lp_chunk *c;
if (size >= m->threshold)
{
+ /* Too large => allocate large chunk */
c = xmalloc(sizeof(struct lp_chunk) + size);
- m->total += size;
+ m->total_large += size;
+ c->next = m->first_large;
+ m->first_large = c->next;
}
else
{
- c = xmalloc(sizeof(struct lp_chunk) + m->chunk_size);
+ if (m->current && m->current->next)
+ /* Still have free chunks from previous incarnation (before lp_flush()) */
+ c = m->current->next;
+ else
+ {
+ /* Need to allocate a new chunk */
+ c = xmalloc(sizeof(struct lp_chunk) + m->chunk_size);
+ m->total += m->chunk_size;
+ *m->plast = c;
+ m->plast = &c->next;
+ c->next = NULL;
+ }
+ m->current = c;
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;
}
}
@@ -104,6 +117,22 @@ lp_allocz(linpool *m, unsigned size)
}
void
+lp_flush(linpool *m)
+{
+ struct lp_chunk *c;
+
+ /* Relink all normal chunks to free list and free all large chunks */
+ m->ptr = m->end = NULL;
+ m->current = m->first;
+ while (c = m->first_large)
+ {
+ m->first_large = c->next;
+ xfree(c);
+ }
+ m->total_large = 0;
+}
+
+void
lp_free(resource *r)
{
linpool *m = (linpool *) r;
diff --git a/lib/resource.h b/lib/resource.h
index 1d83b07f..1a993978 100644
--- a/lib/resource.h
+++ b/lib/resource.h
@@ -1,7 +1,7 @@
/*
* BIRD Resource Manager
*
- * (c) 1998 Martin Mares <mj@ucw.cz>
+ * (c) 1998--1999 Martin Mares <mj@ucw.cz>
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
@@ -54,6 +54,7 @@ linpool *lp_new(pool *, unsigned blk);
void *lp_alloc(linpool *, unsigned size); /* Aligned */
void *lp_allocu(linpool *, unsigned size); /* Unaligned */
void *lp_allocz(linpool *, unsigned size); /* With clear */
+void lp_flush(linpool *); /* Free everything, but leave linpool */
/* Slabs */