diff options
Diffstat (limited to 'lib/mempool.c')
-rw-r--r-- | lib/mempool.c | 111 |
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; } |