summaryrefslogtreecommitdiff
path: root/lib/mempool.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/mempool.c')
-rw-r--r--lib/mempool.c111
1 files changed, 52 insertions, 59 deletions
diff --git a/lib/mempool.c b/lib/mempool.c
index 6d157e5c..be98de51 100644
--- a/lib/mempool.c
+++ b/lib/mempool.c
@@ -27,24 +27,22 @@
struct lp_chunk {
struct lp_chunk *next;
- uint size;
uintptr_t data_align[0];
byte data[0];
};
-const int lp_chunk_size = sizeof(struct lp_chunk);
+#define LP_DATA_SIZE (page_size - OFFSETOF(struct lp_chunk, data))
struct linpool {
resource r;
byte *ptr, *end;
- pool *p;
struct lp_chunk *first, *current; /* Normal (reusable) chunks */
struct lp_chunk *first_large; /* Large chunks */
- uint chunk_size, threshold, total:31, use_pages:1, total_large;
+ uint total, total_large;
};
static void lp_free(resource *);
-static void lp_dump(resource *);
+static void lp_dump(resource *, unsigned);
static resource *lp_lookup(resource *, unsigned long);
static struct resmem lp_memsize(resource *r);
@@ -60,26 +58,14 @@ static struct resclass lp_class = {
/**
* lp_new - create a new linear memory pool
* @p: pool
- * @blk: block size
*
* lp_new() creates a new linear memory pool resource inside the pool @p.
- * The linear pool consists of a list of memory chunks of size at least
- * @blk.
+ * The linear pool consists of a list of memory chunks of page size.
*/
linpool
-*lp_new(pool *p, uint blk)
+*lp_new(pool *p)
{
- linpool *m = ralloc(p, &lp_class);
- m->p = p;
- if (!blk)
- {
- m->use_pages = 1;
- blk = page_size - lp_chunk_size;
- }
-
- m->chunk_size = blk;
- m->threshold = 3*blk/4;
- return m;
+ return ralloc(p, &lp_class);
}
/**
@@ -110,14 +96,13 @@ lp_alloc(linpool *m, uint size)
else
{
struct lp_chunk *c;
- if (size >= m->threshold)
+ if (size > LP_DATA_SIZE)
{
/* Too large => allocate large chunk */
c = xmalloc(sizeof(struct lp_chunk) + size);
m->total_large += size;
c->next = m->first_large;
m->first_large = c;
- c->size = size;
}
else
{
@@ -129,14 +114,10 @@ lp_alloc(linpool *m, uint size)
else
{
/* Need to allocate a new chunk */
- if (m->use_pages)
- c = alloc_page();
- else
- c = xmalloc(sizeof(struct lp_chunk) + m->chunk_size);
+ c = alloc_page();
- m->total += m->chunk_size;
+ m->total += LP_DATA_SIZE;
c->next = NULL;
- c->size = m->chunk_size;
if (m->current)
m->current->next = c;
@@ -145,7 +126,7 @@ lp_alloc(linpool *m, uint size)
}
m->current = c;
m->ptr = c->data + size;
- m->end = c->data + m->chunk_size;
+ m->end = c->data + LP_DATA_SIZE;
}
return c->data;
}
@@ -204,10 +185,17 @@ lp_flush(linpool *m)
{
struct lp_chunk *c;
- /* Move ptr to the first chunk and free all large chunks */
+ /* Move ptr to the first chunk and free all other chunks */
m->current = c = m->first;
m->ptr = c ? c->data : NULL;
- m->end = c ? c->data + m->chunk_size : NULL;
+ m->end = c ? c->data + LP_DATA_SIZE : NULL;
+
+ while (c && c->next)
+ {
+ struct lp_chunk *d = c->next;
+ c->next = d->next;
+ free_page(d);
+ }
while (c = m->first_large)
{
@@ -230,6 +218,7 @@ lp_save(linpool *m, lp_state *p)
{
p->current = m->current;
p->large = m->first_large;
+ p->total_large = m->total_large;
p->ptr = m->ptr;
}
@@ -249,14 +238,14 @@ lp_restore(linpool *m, lp_state *p)
struct lp_chunk *c;
/* Move ptr to the saved pos and free all newer large chunks */
- m->current = c = p->current;
- m->ptr = p->ptr;
- m->end = c ? c->data + m->chunk_size : NULL;
+ m->current = c = p->current ?: m->first;
+ m->ptr = p->ptr ?: (c ? c->data : NULL);
+ m->end = c ? (c->data + LP_DATA_SIZE) : NULL;
+ m->total_large = p->total_large;
while ((c = m->first_large) && (c != p->large))
{
m->first_large = c->next;
- m->total_large -= c->size;
xfree(c);
}
}
@@ -270,10 +259,7 @@ lp_free(resource *r)
for(d=m->first; d; d = c)
{
c = d->next;
- if (m->use_pages)
- free_page(d);
- else
- xfree(d);
+ free_page(d);
}
for(d=m->first_large; d; d = c)
{
@@ -283,42 +269,52 @@ lp_free(resource *r)
}
static void
-lp_dump(resource *r)
+lp_dump(resource *r, unsigned indent)
{
linpool *m = (linpool *) r;
struct lp_chunk *c;
int cnt, cntl;
+ char x[32];
for(cnt=0, c=m->first; c; c=c->next, cnt++)
;
for(cntl=0, c=m->first_large; c; c=c->next, cntl++)
;
- debug("(chunk=%d threshold=%d count=%d+%d total=%d+%d)\n",
- m->chunk_size,
- m->threshold,
+ debug("(count=%d+%d total=%d+%d)\n",
cnt,
cntl,
m->total,
m->total_large);
+
+ bsprintf(x, "%%%dschunk %%p\n", indent + 2);
+ for (c=m->first; c; c=c->next)
+ debug(x, "", c);
+
+ bsprintf(x, "%%%dslarge %%p\n", indent + 2);
+ for (c=m->first_large; c; c=c->next)
+ debug(x, "", c);
}
static struct resmem
lp_memsize(resource *r)
{
linpool *m = (linpool *) r;
- struct lp_chunk *c;
- int cnt = 0;
-
- for(c=m->first; c; c=c->next)
- cnt++;
- for(c=m->first_large; c; c=c->next)
- cnt++;
-
- return (struct resmem) {
- .effective = m->total + m->total_large,
- .overhead = ALLOC_OVERHEAD + sizeof(struct linpool) +
- cnt * (ALLOC_OVERHEAD + sizeof(struct lp_chunk)),
+ struct resmem sz = {
+ .overhead = sizeof(struct linpool) + ALLOC_OVERHEAD,
+ .effective = m->total_large,
};
+
+ for (struct lp_chunk *c = m->first_large; c; c = c->next)
+ sz.overhead += sizeof(struct lp_chunk) + ALLOC_OVERHEAD;
+
+ uint regular = 0;
+ for (struct lp_chunk *c = m->first; c; c = c->next)
+ regular++;
+
+ sz.effective += LP_DATA_SIZE * regular;
+ sz.overhead += (sizeof(struct lp_chunk) + ALLOC_OVERHEAD) * regular;
+
+ return sz;
}
@@ -329,10 +325,7 @@ lp_lookup(resource *r, unsigned long a)
struct lp_chunk *c;
for(c=m->first; c; c=c->next)
- if ((unsigned long) c->data <= a && (unsigned long) c->data + c->size > a)
- return r;
- for(c=m->first_large; c; c=c->next)
- if ((unsigned long) c->data <= a && (unsigned long) c->data + c->size > a)
+ if ((unsigned long) c->data <= a && (unsigned long) c->data + LP_DATA_SIZE > a)
return r;
return NULL;
}