@@@ fltfmt mess
[mLib] / mem / pool.c
index 69e852d..8d124d4 100644 (file)
 
 /*----- Header files ------------------------------------------------------*/
 
+#include "config.h"
+
 #include <string.h>
 
+#ifdef HAVE_VALGRIND_VALGRIND_H
+#  include <valgrind/valgrind.h>
+#  include <valgrind/memcheck.h>
+#  define VG(x) x
+#else
+#  define VG(x)
+#endif
+
 #include "align.h"
 #include "alloc.h"
 #include "arena.h"
 #include "pool.h"
 
+/*----- Constants ---------------------------------------------------------*/
+
+#define REDZONE_SIZE (2*ALIGNOF(union align))
+
 /*----- Main code ---------------------------------------------------------*/
 
 /* --- @doalloc@ --- *
@@ -41,6 +55,7 @@
  * Arguments:  @arena *a@ = pointer to arena to allocate memory from
  *             @pool_chunk **cc@ = pointer to chunk list
  *             @size_t sz@ = size of memory wanted
+ *             @unsigned f@ = flags (@PF_...@)
  *
  * Returns:    Pointer to the allocated block.
  *
  *             during pool creation, hence the slightly bizarre interface.
  */
 
-static void *doalloc(arena *a, pool_chunk **cc, size_t sz)
+static void *doalloc(arena *a, pool_chunk **cc, size_t sz, unsigned f)
 {
   pool_chunk *c;
   void *p;
   size_t csz, ssz;
+  size_t redsz = VG( f&PF_VALGRIND ? REDZONE_SIZE : ) 0;
+  VG( size_t sz0 = sz; )
 
   /* --- See if there's enough space --- *
    *
@@ -60,12 +77,11 @@ static void *doalloc(arena *a, pool_chunk **cc, size_t sz)
    * in the first chunk there isn't enough space anywhere.
    */
 
-  ALIGN(sz);
+  ALIGN(sz); sz += redsz;
   c = *cc;
   if (c && c->left >= sz) {
-    p = c->p;
-    c->p += sz;
-    c->left -= sz;
+    p = c->p; VG( if (f&PF_VALGRIND) VALGRIND_MEMPOOL_ALLOC(c, p, sz0); )
+    c->p += sz; c->left -= sz;
     *cc = c->next;
   }
 
@@ -77,19 +93,21 @@ static void *doalloc(arena *a, pool_chunk **cc, size_t sz)
   else {
     ssz = sizeof(pool_chunk);
     ALIGN(ssz);
-    csz = (ssz + sz + POOL_CHUNKSZ - 1); csz -= csz % POOL_CHUNKSZ;
+    csz = (ssz + redsz + sz + POOL_CHUNKSZ - 1); csz -= csz % POOL_CHUNKSZ;
     c = x_alloc(a, csz);
-    p = (char *)c + ssz;
-    c->p = (char *)p + sz;
-    c->left = csz - ssz - sz;
+    p = (unsigned char *)c + ssz + redsz;
+    VG( if (f&PF_VALGRIND) {
+         VALGRIND_CREATE_MEMPOOL(c, REDZONE_SIZE, 0);
+         VALGRIND_MEMPOOL_ALLOC(c, p, sz0);
+       } )
+    c->p = (unsigned char *)p + sz;
+    c->left = csz - ssz - redsz - sz;
   }
 
   /* --- Move this chunk in the list so that it's sorted --- */
 
-  while (*cc && (*cc)->left > c->left)
-    cc = &(*cc)->next;
-  c->next = *cc;
-  *cc = c;
+  while (*cc && (*cc)->left > c->left) cc = &(*cc)->next;
+  c->next = *cc; *cc = c;
 
   /* --- Done --- */
 
@@ -108,9 +126,7 @@ static void *doalloc(arena *a, pool_chunk **cc, size_t sz)
  */
 
 void *pool_alloc(pool *p, size_t sz)
-{
-  return (doalloc(p->pa, &p->c, sz));
-}
+  { return (doalloc(p->pa, &p->c, sz, p->f)); }
 
 /* --- @pool_strdup@ --- *
  *
@@ -125,7 +141,8 @@ void *pool_alloc(pool *p, size_t sz)
 char *pool_strdup(pool *p, const char *s)
 {
   size_t sz = strlen(s) + 1;
-  char *pp = doalloc(p->pa, &p->c, sz);
+  char *pp = doalloc(p->pa, &p->c, sz, p->f);
+
   memcpy(pp, s, sz);
   return (pp);
 }
@@ -135,32 +152,14 @@ char *pool_strdup(pool *p, const char *s)
 static void *palloc(arena *a, size_t sz)
 {
   pool *p = (pool *)a;
-  return (doalloc(p->pa, &p->c, sz));
+
+  return (doalloc(p->pa, &p->c, sz, p->f));
 }
 
 static void pfree(arena *a, void *p) { return; } /* Trivial */
 
 static arena_ops pool_ops = { palloc, arena_fakerealloc, pfree, 0 };
 
-/* --- @pool_init@ --- *
- *
- * Arguments:  @pool *p@ = pointer to the pool structure to initialize
- *             @arena *a@ = pointer to an arena to allocate memory from
- *
- * Returns:    ---
- *
- * Use:                Initializes a chunk of memory as a resource pool which is not
- *             a child of any other resource pool.
- */
-
-void pool_init(pool *p, arena *a)
-{
-  p->a.ops = &pool_ops;
-  p->c = 0;
-  p->r = 0;
-  p->pa = a;
-}
-
 /* --- @pool_create@ --- *
  *
  * Arguments:  @arena *a@ = pointer to an arena to allocate memory from
@@ -174,9 +173,13 @@ void pool_init(pool *p, arena *a)
 pool *pool_create(arena *a)
 {
   pool_chunk *c = 0;
-  pool *p = doalloc(a, &c, sizeof(pool));
-  pool_init(p, a);
-  p->c = c;
+  pool *p;
+  unsigned f = 0;
+
+  VG( if (RUNNING_ON_VALGRIND) f |= PF_VALGRIND; )
+  p = doalloc(a, &c, sizeof(pool), f);
+  p->c = c; p->r = 0; p->pa = a; p->f = f;
+  p->a.ops = &pool_ops;
   return (p);
 }
 
@@ -216,11 +219,10 @@ void pool_destroy(pool *p)
    * the pool block itself will be left around.
    */
 
-  a = p->pa;
-  c = p->c;
-  p->c = 0;
+  a = p->pa; c = p->c; p->c = 0;
   while (c) {
     cc = c->next;
+    VG( if (p->f&PF_VALGRIND) VALGRIND_DESTROY_MEMPOOL(c); )
     x_free(a, c);
     c = cc;
   }