/*----- 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@ --- *
* 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 --- *
*
* 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;
}
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 --- */
*/
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@ --- *
*
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);
}
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
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);
}
* 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;
}