]> git.ipfire.org Git - thirdparty/bird.git/blobdiff - lib/mempool.c
Merge branch 'bmp'
[thirdparty/bird.git] / lib / mempool.c
index 169826d4c59cf4d4a191f7430ba69b301e700695..9d4404f7cab4c567c01e625324400ad35385f89b 100644 (file)
 
 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;
   struct lp_chunk *first, *current;            /* Normal (reusable) chunks */
   struct lp_chunk *first_large;                        /* Large chunks */
-  uint chunk_size, threshold, total, total_large;
+  uint total, total_large;
 };
 
 _Thread_local linpool *tmp_linpool;
@@ -61,19 +60,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->chunk_size = blk;
-  m->threshold = 3*blk/4;
-  return m;
+  return ralloc(p, &lp_class);
 }
 
 /**
@@ -104,14 +98,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
        {
@@ -123,10 +116,10 @@ lp_alloc(linpool *m, uint size)
          else
            {
              /* Need to allocate a new chunk */
-             c = xmalloc(sizeof(struct lp_chunk) + m->chunk_size);
-             m->total += m->chunk_size;
+             c = alloc_page();
+
+             m->total += LP_DATA_SIZE;
              c->next = NULL;
-             c->size = m->chunk_size;
 
              if (m->current)
                m->current->next = c;
@@ -135,7 +128,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;
     }
@@ -194,10 +187,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)
     {
@@ -220,6 +220,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;
 }
 
@@ -239,14 +240,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);
     }
 }
@@ -260,7 +261,7 @@ lp_free(resource *r)
   for(d=m->first; d; d = c)
     {
       c = d->next;
-      xfree(d);
+      free_page(d);
     }
   for(d=m->first_large; d; d = c)
     {
@@ -280,9 +281,7 @@ lp_dump(resource *r)
     ;
   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,
@@ -293,19 +292,22 @@ 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;
 }
 
 
@@ -316,10 +318,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;
 }