]> mj.ucw.cz Git - netgrind.git/commitdiff
Added pools.
authorMartin Mares <mj@ucw.cz>
Sun, 8 Jun 2003 12:31:21 +0000 (12:31 +0000)
committerMartin Mares <mj@ucw.cz>
Sun, 8 Jun 2003 12:31:21 +0000 (12:31 +0000)
lib/Makefile
lib/pools.c [new file with mode: 0644]
lib/pools.h [new file with mode: 0644]

index 1bf3eb8d2c2277db85bd709bcb4048cefb7dfb9b..bbac10198d18b0cc2e91a02f4f744f45103280f0 100644 (file)
@@ -1,7 +1,7 @@
 DIRS+=lib
 
 LIBSH=obj/lib/libsh.a
-LIBSH_MODS=alloc assert prime
+LIBSH_MODS=alloc assert prime pools
 LIBSH_MOD_PATHS=$(addprefix obj/lib/,$(LIBSH_MODS))
 
 $(LIBSH): $(addsuffix .o,$(LIBSH_MOD_PATHS))
diff --git a/lib/pools.c b/lib/pools.c
new file mode 100644 (file)
index 0000000..8b7c372
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ *     Sherlock Library -- Memory Pools (One-Time Allocation)
+ *
+ *     (c) 1997--2001 Martin Mares <mj@ucw.cz>
+ *
+ *     This software may be freely distributed and used according to the terms
+ *     of the GNU Lesser General Public License.
+ */
+
+#include "lib/lib.h"
+#include "lib/pools.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+struct memchunk {
+  struct memchunk *next;
+  byte data[0];
+};
+
+struct mempool *
+mp_new(uns size)
+{
+  struct mempool *p = xmalloc(sizeof(struct mempool));
+
+  size -= sizeof(struct memchunk);
+  p->free = p->last = NULL;
+  p->first = p->current = p->first_large = NULL;
+  p->plast = &p->first;
+  p->chunk_size = size;
+  p->threshold = size / 3;
+  return p;
+}
+
+void
+mp_delete(struct mempool *p)
+{
+  struct memchunk *c, *d;
+
+  for(d=p->first; d; d = c)
+    {
+      c = d->next;
+      xfree(d);
+    }
+  for(d=p->first_large; d; d = c)
+    {
+      c = d->next;
+      xfree(d);
+    }
+  xfree(p);
+}
+
+void
+mp_flush(struct mempool *p)
+{
+  struct memchunk *c;
+
+  p->free = p->last = NULL;
+  p->current = p->first;
+  while (c = p->first_large)
+    {
+      p->first_large = c->next;
+      xfree(c);
+    }
+}
+
+void *
+mp_alloc(struct mempool *p, uns s)
+{
+  if (s <= p->threshold)
+    {
+      byte *x = (byte *)(((uns) p->free + POOL_ALIGN - 1) & ~(POOL_ALIGN - 1));
+      if (x + s > p->last)
+       {
+         struct memchunk *c;
+
+         if (p->current)
+           {
+             /* Still have free chunks from previous incarnation */
+             c = p->current;
+             p->current = c->next;
+           }
+         else
+           {
+             c = xmalloc(sizeof(struct memchunk) + p->chunk_size);
+             *p->plast = c;
+             p->plast = &c->next;
+             c->next = NULL;
+           }
+         x = c->data;
+         p->last = x + p->chunk_size;
+       }
+      p->free = x + s;
+      return x;
+    }
+  else
+    {
+      struct memchunk *c = xmalloc(sizeof(struct memchunk) + s);
+      c->next = p->first_large;
+      p->first_large = c;
+      return c->data;
+    }
+}
+
+void *
+mp_alloc_zero(struct mempool *p, uns s)
+{
+  void *x = mp_alloc(p, s);
+  bzero(x, s);
+  return x;
+}
diff --git a/lib/pools.h b/lib/pools.h
new file mode 100644 (file)
index 0000000..a055ef2
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ *     Sherlock Library -- Memory Pools
+ *
+ *     (c) 1997--2003 Martin Mares <mj@ucw.cz>
+ *
+ *     This software may be freely distributed and used according to the terms
+ *     of the GNU Lesser General Public License.
+ */
+
+#ifndef _SHERLOCK_POOLS_H
+#define _SHERLOCK_POOLS_H
+
+#ifndef POOL_ALIGN
+#define POOL_ALIGN CPU_STRUCT_ALIGN
+#endif
+
+struct mempool {
+  byte *free, *last;
+  struct memchunk *first, *current, **plast;
+  struct memchunk *first_large;
+  uns chunk_size, threshold;
+};
+
+struct mempool *mp_new(uns);
+void mp_delete(struct mempool *);
+void mp_flush(struct mempool *);
+void *mp_alloc(struct mempool *, uns);
+void *mp_alloc_zero(struct mempool *, uns);
+
+static inline void *mp_alloc_fast(struct mempool *p, uns l)
+{
+  byte *f = (void *) (((uns) p->free + POOL_ALIGN - 1) & ~(POOL_ALIGN - 1));
+  byte *ee = f + l;
+  if (ee > p->last)
+    return mp_alloc(p, l);
+  p->free = ee;
+  return f;
+}
+
+static inline void *mp_alloc_fast_noalign(struct mempool *p, uns l)
+{
+  byte *f = p->free;
+  byte *ee = f + l;
+  if (ee > p->last)
+    return mp_alloc(p, l);
+  p->free = ee;
+  return f;
+}
+
+static inline void *
+mp_start_string(struct mempool *p, uns l)
+{
+  ASSERT(l <= p->chunk_size);
+  return mp_alloc(p, l);
+}
+
+static inline void
+mp_end_string(struct mempool *p, void *stop)
+{
+  p->free = stop;
+}
+
+#endif