summaryrefslogtreecommitdiff
path: root/contrib/bind/lib/isc/memcluster.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind/lib/isc/memcluster.c')
-rw-r--r--contrib/bind/lib/isc/memcluster.c213
1 files changed, 204 insertions, 9 deletions
diff --git a/contrib/bind/lib/isc/memcluster.c b/contrib/bind/lib/isc/memcluster.c
index 761fe98f82ff..b775fa7aa84c 100644
--- a/contrib/bind/lib/isc/memcluster.c
+++ b/contrib/bind/lib/isc/memcluster.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 by Internet Software Consortium.
+ * Copyright (c) 1997,1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -15,8 +15,15 @@
* SOFTWARE.
*/
+
+/* When this symbol is defined allocations via memget are made slightly
+ bigger and some debugging info stuck before and after the region given
+ back to the caller. */
+/* #define DEBUGGING_MEMCLUSTER */
+
+
#if !defined(LINT) && !defined(CODECENTER)
-static char rcsid[] = "$Id: memcluster.c,v 8.10 1998/05/05 19:00:52 halley Exp $";
+static const char rcsid[] = "$Id: memcluster.c,v 8.19 1999/10/13 17:11:22 vixie Exp $";
#endif /* not lint */
#include "port_before.h"
@@ -41,15 +48,34 @@ static char rcsid[] = "$Id: memcluster.c,v 8.10 1998/05/05 19:00:52 halley Exp $
#include "port_after.h"
+#ifdef MEMCLUSTER_RECORD
+#ifndef DEBUGGING_MEMCLUSTER
+#define DEBUGGING_MEMCLUSTER
+#endif
+#endif
+
#define DEF_MAX_SIZE 1100
#define DEF_MEM_TARGET 4096
+typedef u_int32_t fence_t;
+
typedef struct {
void * next;
+#if defined(DEBUGGING_MEMCLUSTER)
+#if defined(MEMCLUSTER_RECORD)
+ const char * file;
+ int line;
+#endif
+ int size;
+ fence_t fencepost;
+#endif
} memcluster_element;
#define SMALL_SIZE_LIMIT sizeof(memcluster_element)
#define P_SIZE sizeof(void *)
+#define FRONT_FENCEPOST 0xfebafeba
+#define BACK_FENCEPOST 0xabefabef
+#define FENCEPOST_SIZE 4
#ifndef MEMCLUSTER_LITTLE_MALLOC
#define MEMCLUSTER_BIG_MALLOC 1
@@ -70,6 +96,9 @@ static size_t mem_target;
static size_t mem_target_half;
static size_t mem_target_fudge;
static memcluster_element ** freelists;
+#ifdef MEMCLUSTER_RECORD
+static memcluster_element ** activelists;
+#endif
#ifdef MEMCLUSTER_BIG_MALLOC
static memcluster_element * basic_blocks;
#endif
@@ -78,13 +107,18 @@ static struct stats * stats;
/* Forward. */
static size_t quantize(size_t);
+#if defined(DEBUGGING_MEMCLUSTER)
+static void check(unsigned char *, int, size_t);
+#endif
/* Public. */
int
meminit(size_t init_max_size, size_t target_size) {
- int i;
+#if defined(DEBUGGING_MEMCLUSTER)
+ INSIST(sizeof(fence_t) == FENCEPOST_SIZE);
+#endif
if (freelists != NULL) {
errno = EEXIST;
return (-1);
@@ -108,6 +142,15 @@ meminit(size_t init_max_size, size_t target_size) {
memset(freelists, 0,
max_size * sizeof (memcluster_element *));
memset(stats, 0, (max_size + 1) * sizeof (struct stats));
+#ifdef MEMCLUSTER_RECORD
+ activelists = malloc((max_size + 1) * sizeof (memcluster_element *));
+ if (activelists == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ memset(activelists, 0,
+ (max_size + 1) * sizeof (memcluster_element *));
+#endif
#ifdef MEMCLUSTER_BIG_MALLOC
basic_blocks = NULL;
#endif
@@ -116,7 +159,17 @@ meminit(size_t init_max_size, size_t target_size) {
void *
__memget(size_t size) {
+ return (__memget_record(size, NULL, 0));
+}
+
+void *
+__memget_record(size_t size, const char *file, int line) {
size_t new_size = quantize(size);
+#if defined(DEBUGGING_MEMCLUSTER)
+ memcluster_element *e;
+ char *p;
+ fence_t fp = BACK_FENCEPOST;
+#endif
void *ret;
if (freelists == NULL)
@@ -130,7 +183,27 @@ __memget(size_t size) {
/* memget() was called on something beyond our upper limit. */
stats[max_size].gets++;
stats[max_size].totalgets++;
+#if defined(DEBUGGING_MEMCLUSTER)
+ e = malloc(new_size);
+ if (e == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ e->next = NULL;
+ e->size = size;
+#ifdef MEMCLUSTER_RECORD
+ e->file = file;
+ e->line = line;
+ e->next = activelists[max_size];
+ activelists[max_size] = e;
+#endif
+ e->fencepost = FRONT_FENCEPOST;
+ p = (char *)e + sizeof *e + size;
+ memcpy(p, &fp, sizeof fp);
+ return ((char *)e + sizeof *e);
+#else
return (malloc(size));
+#endif
}
/*
@@ -186,18 +259,50 @@ __memget(size_t size) {
curr = new;
next = curr + new_size;
for (i = 0; i < (frags - 1); i++) {
+#if defined (DEBUGGING_MEMCLUSTER)
+ memset(curr, 0xa5, new_size);
+#endif
((memcluster_element *)curr)->next = next;
curr = next;
next += new_size;
}
/* curr is now pointing at the last block in the array. */
+#if defined (DEBUGGING_MEMCLUSTER)
+ memset(curr, 0xa5, new_size);
+#endif
((memcluster_element *)curr)->next = freelists[new_size];
freelists[new_size] = new;
}
- /* The free list uses the "rounded-up" size "new_size": */
+ /* The free list uses the "rounded-up" size "new_size". */
+#if defined (DEBUGGING_MEMCLUSTER)
+ e = freelists[new_size];
+ ret = (char *)e + sizeof *e;
+ /*
+ * Check to see if this buffer has been written to while on free list.
+ */
+ check(ret, 0xa5, new_size - sizeof *e);
+ /*
+ * Mark memory we are returning.
+ */
+ memset(ret, 0xe5, size);
+#else
ret = freelists[new_size];
+#endif
freelists[new_size] = freelists[new_size]->next;
+#if defined(DEBUGGING_MEMCLUSTER)
+ e->next = NULL;
+ e->size = size;
+ e->fencepost = FRONT_FENCEPOST;
+#ifdef MEMCLUSTER_RECORD
+ e->file = file;
+ e->line = line;
+ e->next = activelists[size];
+ activelists[size] = e;
+#endif
+ p = (char *)e + sizeof *e + size;
+ memcpy(p, &fp, sizeof fp);
+#endif
/*
* The stats[] uses the _actual_ "size" requested by the
@@ -208,7 +313,11 @@ __memget(size_t size) {
stats[size].gets++;
stats[size].totalgets++;
stats[new_size].freefrags--;
+#if defined(DEBUGGING_MEMCLUSTER)
+ return ((char *)e + sizeof *e);
+#else
return (ret);
+#endif
}
/*
@@ -217,25 +326,83 @@ __memget(size_t size) {
*/
void
__memput(void *mem, size_t size) {
- size_t new_size = quantize(size);
+ __memput_record(mem, size, NULL, 0);
+}
+void
+__memput_record(void *mem, size_t size, const char *file, int line) {
+ size_t new_size = quantize(size);
+#if defined (DEBUGGING_MEMCLUSTER)
+ memcluster_element *e;
+#ifdef MEMCLUSTER_RECORD
+ memcluster_element *prev, *el;
+#endif
+ int fp;
+ char *p;
+#endif
REQUIRE(freelists != NULL);
if (size == 0) {
errno = EINVAL;
return;
}
+
+#if defined (DEBUGGING_MEMCLUSTER)
+ e = (memcluster_element *) ((char *)mem - sizeof *e);
+ INSIST(e->fencepost == FRONT_FENCEPOST);
+ INSIST(e->size == size);
+ p = (char *)e + sizeof *e + size;
+ memcpy(&fp, p, sizeof fp);
+ INSIST(fp == BACK_FENCEPOST);
+ INSIST(((int)mem % 4) == 0);
+#ifdef MEMCLUSTER_RECORD
+ prev = NULL;
+ if (size == max_size || new_size >= max_size)
+ el = activelists[max_size];
+ else
+ el = activelists[size];
+ while (el != NULL && el != e) {
+ prev = el;
+ el = el->next;
+ }
+ INSIST(el != NULL); /* double free */
+ if (prev == NULL) {
+ if (size == max_size || new_size >= max_size)
+ activelists[max_size] = el->next;
+ else
+ activelists[size] = el->next;
+ } else
+ prev->next = el->next;
+#endif
+#endif
+
if (size == max_size || new_size >= max_size) {
/* memput() called on something beyond our upper limit */
+#if defined(DEBUGGING_MEMCLUSTER)
+ free(e);
+#else
free(mem);
+#endif
+
INSIST(stats[max_size].gets != 0);
stats[max_size].gets--;
return;
}
/* The free list uses the "rounded-up" size "new_size": */
+#if defined(DEBUGGING_MEMCLUSTER)
+ memset(mem, 0xa5, new_size - sizeof *e); /* catch write after free */
+ e->size = 0; /* catch double memput() */
+#ifdef MEMCLUSTER_RECORD
+ e->file = file;
+ e->line = line;
+#endif
+ e->next = freelists[new_size];
+ freelists[new_size] = (void *)e;
+#else
((memcluster_element *)mem)->next = freelists[new_size];
freelists[new_size] = (memcluster_element *)mem;
+#endif
/*
* The stats[] uses the _actual_ "size" requested by the
@@ -251,7 +418,7 @@ __memput(void *mem, size_t size) {
void *
__memget_debug(size_t size, const char *file, int line) {
void *ptr;
- ptr = __memget(size);
+ ptr = __memget_record(size, file, line);
fprintf(stderr, "%s:%d: memget(%lu) -> %p\n", file, line,
(u_long)size, ptr);
return (ptr);
@@ -261,7 +428,7 @@ void
__memput_debug(void *ptr, size_t size, const char *file, int line) {
fprintf(stderr, "%s:%d: memput(%p, %lu)\n", file, line, ptr,
(u_long)size);
- __memput(ptr, size);
+ __memput_record(ptr, size, file, line);
}
/*
@@ -270,6 +437,9 @@ __memput_debug(void *ptr, size_t size, const char *file, int line) {
void
memstats(FILE *out) {
size_t i;
+#ifdef MEMCLUSTER_RECORD
+ memcluster_element *e;
+#endif
if (freelists == NULL)
return;
@@ -286,6 +456,19 @@ memstats(FILE *out) {
s->blocks, s->freefrags);
fputc('\n', out);
}
+#ifdef MEMCLUSTER_RECORD
+ fprintf(out, "Active Memory:\n");
+ for (i = 1; i <= max_size; i++) {
+ if ((e = activelists[i]) != NULL)
+ while (e != NULL) {
+ fprintf(out, "%s:%d %#p:%d\n",
+ e->file != NULL ? e->file :
+ "<UNKNOWN>", e->line,
+ (char *)e + sizeof *e, e->size);
+ e = e->next;
+ }
+ }
+#endif
}
/* Private. */
@@ -295,7 +478,7 @@ memstats(FILE *out) {
* block is at least sizeof void *, and that we won't violate alignment
* restrictions, both of which are needed to make lists of blocks.
*/
-static size_t
+static size_t
quantize(size_t size) {
int remainder;
/*
@@ -309,7 +492,19 @@ quantize(size_t size) {
*/
remainder = size % P_SIZE;
if (remainder != 0)
- size += P_SIZE - remainder;
+ size += P_SIZE - remainder;
+#if defined(DEBUGGING_MEMCLUSTER)
+ return (size + SMALL_SIZE_LIMIT + sizeof (int));
+#else
return (size);
+#endif
}
+#if defined(DEBUGGING_MEMCLUSTER)
+static void
+check(unsigned char *a, int value, size_t len) {
+ int i;
+ for (i = 0; i < len; i++)
+ INSIST(a[i] == value);
+}
+#endif