summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/lib/isc/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind9/lib/isc/mem.c')
-rw-r--r--contrib/bind9/lib/isc/mem.c601
1 files changed, 389 insertions, 212 deletions
diff --git a/contrib/bind9/lib/isc/mem.c b/contrib/bind9/lib/isc/mem.c
index f5069fb..35918dc 100644
--- a/contrib/bind9/lib/isc/mem.c
+++ b/contrib/bind9/lib/isc/mem.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1997-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
@@ -15,7 +15,9 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mem.c,v 1.98.2.7.2.7 2005/03/17 03:58:32 marka Exp $ */
+/* $Id: mem.c,v 1.116.18.12 2006/12/08 05:07:59 marka Exp $ */
+
+/*! \file */
#include <config.h>
@@ -28,35 +30,29 @@
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/msgs.h>
+#include <isc/once.h>
#include <isc/ondestroy.h>
#include <isc/string.h>
#include <isc/mutex.h>
#include <isc/util.h>
+#define MCTXLOCK(m, l) if (((m)->flags & ISC_MEMFLAG_NOLOCK) == 0) LOCK(l)
+#define MCTXUNLOCK(m, l) if (((m)->flags & ISC_MEMFLAG_NOLOCK) == 0) UNLOCK(l)
+
#ifndef ISC_MEM_DEBUGGING
#define ISC_MEM_DEBUGGING 0
#endif
LIBISC_EXTERNAL_DATA unsigned int isc_mem_debugging = ISC_MEM_DEBUGGING;
/*
- * Define ISC_MEM_USE_INTERNAL_MALLOC=1 to use the internal malloc()
- * implementation in preference to the system one. The internal malloc()
- * is very space-efficient, and quite fast on uniprocessor systems. It
- * performs poorly on multiprocessor machines.
- */
-#ifndef ISC_MEM_USE_INTERNAL_MALLOC
-#define ISC_MEM_USE_INTERNAL_MALLOC 0
-#endif
-
-/*
* Constants.
*/
#define DEF_MAX_SIZE 1100
#define DEF_MEM_TARGET 4096
-#define ALIGNMENT_SIZE 8 /* must be a power of 2 */
-#define NUM_BASIC_BLOCKS 64 /* must be > 1 */
+#define ALIGNMENT_SIZE 8 /*%< must be a power of 2 */
+#define NUM_BASIC_BLOCKS 64 /*%< must be > 1 */
#define TABLE_INCREMENT 1024
#define DEBUGLIST_COUNT 1024
@@ -87,11 +83,12 @@ struct element {
};
typedef struct {
- /*
+ /*!
* This structure must be ALIGNMENT_SIZE bytes.
*/
union {
size_t size;
+ isc_mem_t *ctx;
char bytes[ALIGNMENT_SIZE];
} u;
} size_info;
@@ -99,10 +96,8 @@ typedef struct {
struct stats {
unsigned long gets;
unsigned long totalgets;
-#if ISC_MEM_USE_INTERNAL_MALLOC
unsigned long blocks;
unsigned long freefrags;
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
};
#define MEM_MAGIC ISC_MAGIC('M', 'e', 'm', 'C')
@@ -112,9 +107,16 @@ struct stats {
typedef ISC_LIST(debuglink_t) debuglist_t;
#endif
+/* List of all active memory contexts. */
+
+static ISC_LIST(isc_mem_t) contexts;
+static isc_once_t once = ISC_ONCE_INIT;
+static isc_mutex_t lock;
+
struct isc_mem {
unsigned int magic;
isc_ondestroy_t ondestroy;
+ unsigned int flags;
isc_mutex_t lock;
isc_memalloc_t memalloc;
isc_memfree_t memfree;
@@ -134,7 +136,7 @@ struct isc_mem {
void * water_arg;
ISC_LIST(isc_mempool_t) pools;
-#if ISC_MEM_USE_INTERNAL_MALLOC
+ /* ISC_MEMFLAG_INTERNAL */
size_t mem_target;
element ** freelists;
element * basic_blocks;
@@ -143,13 +145,13 @@ struct isc_mem {
unsigned int basic_table_size;
unsigned char * lowest;
unsigned char * highest;
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
#if ISC_MEM_TRACKLINES
debuglist_t * debuglist;
#endif
unsigned int memalloc_failures;
+ ISC_LINK(isc_mem_t) link;
};
#define MEMPOOL_MAGIC ISC_MAGIC('M', 'E', 'M', 'p')
@@ -157,24 +159,24 @@ struct isc_mem {
struct isc_mempool {
/* always unlocked */
- unsigned int magic; /* magic number */
- isc_mutex_t *lock; /* optional lock */
- isc_mem_t *mctx; /* our memory context */
- /* locked via the memory context's lock */
- ISC_LINK(isc_mempool_t) link; /* next pool in this mem context */
- /* optionally locked from here down */
- element *items; /* low water item list */
- size_t size; /* size of each item on this pool */
- unsigned int maxalloc; /* max number of items allowed */
- unsigned int allocated; /* # of items currently given out */
- unsigned int freecount; /* # of items on reserved list */
- unsigned int freemax; /* # of items allowed on free list */
- unsigned int fillcount; /* # of items to fetch on each fill */
- /* Stats only. */
- unsigned int gets; /* # of requests to this pool */
- /* Debugging only. */
+ unsigned int magic; /*%< magic number */
+ isc_mutex_t *lock; /*%< optional lock */
+ isc_mem_t *mctx; /*%< our memory context */
+ /*%< locked via the memory context's lock */
+ ISC_LINK(isc_mempool_t) link; /*%< next pool in this mem context */
+ /*%< optionally locked from here down */
+ element *items; /*%< low water item list */
+ size_t size; /*%< size of each item on this pool */
+ unsigned int maxalloc; /*%< max number of items allowed */
+ unsigned int allocated; /*%< # of items currently given out */
+ unsigned int freecount; /*%< # of items on reserved list */
+ unsigned int freemax; /*%< # of items allowed on free list */
+ unsigned int fillcount; /*%< # of items to fetch on each fill */
+ /*%< Stats only. */
+ unsigned int gets; /*%< # of requests to this pool */
+ /*%< Debugging only. */
#if ISC_MEMPOOL_NAMES
- char name[16]; /* printed name in stats reports */
+ char name[16]; /*%< printed name in stats reports */
#endif
};
@@ -198,7 +200,7 @@ struct isc_mempool {
static void
print_active(isc_mem_t *ctx, FILE *out);
-/*
+/*!
* mctx must be locked.
*/
static inline void
@@ -309,7 +311,6 @@ delete_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size,
}
#endif /* ISC_MEM_TRACKLINES */
-#if ISC_MEM_USE_INTERNAL_MALLOC
static inline size_t
rmsize(size_t size) {
/*
@@ -320,13 +321,13 @@ rmsize(size_t size) {
static inline size_t
quantize(size_t size) {
- /*
+ /*!
* Round up the result in order to get a size big
* enough to satisfy the request and be aligned on ALIGNMENT_SIZE
* byte boundaries.
*/
- if (size == 0)
+ if (size == 0U)
return (ALIGNMENT_SIZE);
return ((size + ALIGNMENT_SIZE - 1) & (~(ALIGNMENT_SIZE - 1)));
}
@@ -347,7 +348,7 @@ more_basic_blocks(isc_mem_t *ctx) {
* Did we hit the quota for this context?
*/
increment = NUM_BASIC_BLOCKS * ctx->mem_target;
- if (ctx->quota != 0 && ctx->total + increment > ctx->quota)
+ if (ctx->quota != 0U && ctx->total + increment > ctx->quota)
return (ISC_FALSE);
INSIST(ctx->basic_table_count <= ctx->basic_table_size);
@@ -408,7 +409,7 @@ more_frags(isc_mem_t *ctx, size_t new_size) {
void *new;
unsigned char *curr, *next;
- /*
+ /*!
* Try to get more fragments by chopping up a basic block.
*/
@@ -448,7 +449,7 @@ more_frags(isc_mem_t *ctx, size_t new_size) {
* Add the remaining fragment of the basic block to a free list.
*/
total_size = rmsize(total_size);
- if (total_size > 0) {
+ if (total_size > 0U) {
((element *)next)->next = ctx->freelists[total_size];
ctx->freelists[total_size] = (element *)next;
ctx->stats[total_size].freefrags++;
@@ -472,7 +473,7 @@ mem_getunlocked(isc_mem_t *ctx, size_t size) {
/*
* memget() was called on something beyond our upper limit.
*/
- if (ctx->quota != 0 && ctx->total + size > ctx->quota) {
+ if (ctx->quota != 0U && ctx->total + size > ctx->quota) {
ret = NULL;
goto done;
}
@@ -556,7 +557,7 @@ mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) {
memset(mem, 0xde, size); /* Mnemonic for "dead". */
#endif
(ctx->memfree)(ctx->arg, mem);
- INSIST(ctx->stats[ctx->max_size].gets != 0);
+ INSIST(ctx->stats[ctx->max_size].gets != 0U);
ctx->stats[ctx->max_size].gets--;
INSIST(size <= ctx->total);
ctx->inuse -= size;
@@ -583,15 +584,13 @@ mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) {
* max. size (max_size) ends up getting recorded as a call to
* max_size.
*/
- INSIST(ctx->stats[size].gets != 0);
+ INSIST(ctx->stats[size].gets != 0U);
ctx->stats[size].gets--;
ctx->stats[new_size].freefrags++;
ctx->inuse -= new_size;
}
-#else /* ISC_MEM_USE_INTERNAL_MALLOC */
-
-/*
+/*!
* Perform a malloc, doing memory filling and overrun detection as necessary.
*/
static inline void *
@@ -619,7 +618,7 @@ mem_get(isc_mem_t *ctx, size_t size) {
return (ret);
}
-/*
+/*!
* Perform a free, doing memory filling and overrun detection as necessary.
*/
static inline void
@@ -635,7 +634,7 @@ mem_put(isc_mem_t *ctx, void *mem, size_t size) {
(ctx->memfree)(ctx->arg, mem);
}
-/*
+/*!
* Update internal counters after a memory get.
*/
static inline void
@@ -652,7 +651,7 @@ mem_getstats(isc_mem_t *ctx, size_t size) {
}
}
-/*
+/*!
* Update internal counters after a memory put.
*/
static inline void
@@ -671,8 +670,6 @@ mem_putstats(isc_mem_t *ctx, void *ptr, size_t size) {
}
}
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
-
/*
* Private.
*/
@@ -691,6 +688,11 @@ default_memfree(void *arg, void *ptr) {
free(ptr);
}
+static void
+initialize_action(void) {
+ RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS);
+}
+
/*
* Public.
*/
@@ -700,6 +702,16 @@ isc_mem_createx(size_t init_max_size, size_t target_size,
isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
isc_mem_t **ctxp)
{
+ return (isc_mem_createx2(init_max_size, target_size, memalloc, memfree,
+ arg, ctxp, ISC_MEMFLAG_DEFAULT));
+
+}
+
+isc_result_t
+isc_mem_createx2(size_t init_max_size, size_t target_size,
+ isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
+ isc_mem_t **ctxp, unsigned int flags)
+{
isc_mem_t *ctx;
isc_result_t result;
@@ -709,27 +721,25 @@ isc_mem_createx(size_t init_max_size, size_t target_size,
INSIST((ALIGNMENT_SIZE & (ALIGNMENT_SIZE - 1)) == 0);
-#if !ISC_MEM_USE_INTERNAL_MALLOC
- UNUSED(target_size);
-#endif
+ RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
ctx = (memalloc)(arg, sizeof(*ctx));
if (ctx == NULL)
return (ISC_R_NOMEMORY);
- if (isc_mutex_init(&ctx->lock) != ISC_R_SUCCESS) {
- UNEXPECTED_ERROR(__FILE__, __LINE__,
- "isc_mutex_init() %s",
- isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
- ISC_MSG_FAILED, "failed"));
- (memfree)(arg, ctx);
- return (ISC_R_UNEXPECTED);
+ if ((flags & ISC_MEMFLAG_NOLOCK) == 0) {
+ result = isc_mutex_init(&ctx->lock);
+ if (result != ISC_R_SUCCESS) {
+ (memfree)(arg, ctx);
+ return (result);
+ }
}
if (init_max_size == 0U)
ctx->max_size = DEF_MAX_SIZE;
else
ctx->max_size = init_max_size;
+ ctx->flags = flags;
ctx->references = 1;
ctx->quota = 0;
ctx->total = 0;
@@ -751,10 +761,13 @@ isc_mem_createx(size_t init_max_size, size_t target_size,
ctx->debuglist = NULL;
#endif
ISC_LIST_INIT(ctx->pools);
-
-#if ISC_MEM_USE_INTERNAL_MALLOC
ctx->freelists = NULL;
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
+ ctx->basic_blocks = NULL;
+ ctx->basic_table = NULL;
+ ctx->basic_table_count = 0;
+ ctx->basic_table_size = 0;
+ ctx->lowest = NULL;
+ ctx->highest = NULL;
ctx->stats = (memalloc)(arg,
(ctx->max_size+1) * sizeof(struct stats));
@@ -764,25 +777,20 @@ isc_mem_createx(size_t init_max_size, size_t target_size,
}
memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof(struct stats));
-#if ISC_MEM_USE_INTERNAL_MALLOC
- if (target_size == 0)
- ctx->mem_target = DEF_MEM_TARGET;
- else
- ctx->mem_target = target_size;
- ctx->freelists = (memalloc)(arg, ctx->max_size * sizeof(element *));
- if (ctx->freelists == NULL) {
- result = ISC_R_NOMEMORY;
- goto error;
+ if ((flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ if (target_size == 0U)
+ ctx->mem_target = DEF_MEM_TARGET;
+ else
+ ctx->mem_target = target_size;
+ ctx->freelists = (memalloc)(arg, ctx->max_size *
+ sizeof(element *));
+ if (ctx->freelists == NULL) {
+ result = ISC_R_NOMEMORY;
+ goto error;
+ }
+ memset(ctx->freelists, 0,
+ ctx->max_size * sizeof(element *));
}
- memset(ctx->freelists, 0,
- ctx->max_size * sizeof(element *));
- ctx->basic_blocks = NULL;
- ctx->basic_table = NULL;
- ctx->basic_table_count = 0;
- ctx->basic_table_size = 0;
- ctx->lowest = NULL;
- ctx->highest = NULL;
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
#if ISC_MEM_TRACKLINES
if ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0) {
@@ -801,6 +809,10 @@ isc_mem_createx(size_t init_max_size, size_t target_size,
ctx->memalloc_failures = 0;
+ LOCK(&lock);
+ ISC_LIST_INITANDAPPEND(contexts, ctx, link);
+ UNLOCK(&lock);
+
*ctxp = ctx;
return (ISC_R_SUCCESS);
@@ -808,15 +820,14 @@ isc_mem_createx(size_t init_max_size, size_t target_size,
if (ctx != NULL) {
if (ctx->stats != NULL)
(memfree)(arg, ctx->stats);
-#if ISC_MEM_USE_INTERNAL_MALLOC
if (ctx->freelists != NULL)
(memfree)(arg, ctx->freelists);
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
#if ISC_MEM_TRACKLINES
if (ctx->debuglist != NULL)
(ctx->memfree)(ctx->arg, ctx->debuglist);
#endif /* ISC_MEM_TRACKLINES */
- DESTROYLOCK(&ctx->lock);
+ if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)
+ DESTROYLOCK(&ctx->lock);
(memfree)(arg, ctx);
}
@@ -827,9 +838,18 @@ isc_result_t
isc_mem_create(size_t init_max_size, size_t target_size,
isc_mem_t **ctxp)
{
- return (isc_mem_createx(init_max_size, target_size,
- default_memalloc, default_memfree, NULL,
- ctxp));
+ return (isc_mem_createx2(init_max_size, target_size,
+ default_memalloc, default_memfree, NULL,
+ ctxp, ISC_MEMFLAG_DEFAULT));
+}
+
+isc_result_t
+isc_mem_create2(size_t init_max_size, size_t target_size,
+ isc_mem_t **ctxp, unsigned int flags)
+{
+ return (isc_mem_createx2(init_max_size, target_size,
+ default_memalloc, default_memfree, NULL,
+ ctxp, flags));
}
static void
@@ -839,9 +859,11 @@ destroy(isc_mem_t *ctx) {
ctx->magic = 0;
-#if ISC_MEM_USE_INTERNAL_MALLOC
+ LOCK(&lock);
+ ISC_LIST_UNLINK(contexts, ctx, link);
+ UNLOCK(&lock);
+
INSIST(ISC_LIST_EMPTY(ctx->pools));
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
#if ISC_MEM_TRACKLINES
if (ctx->debuglist != NULL) {
@@ -880,16 +902,17 @@ destroy(isc_mem_t *ctx) {
(ctx->memfree)(ctx->arg, ctx->stats);
-#if ISC_MEM_USE_INTERNAL_MALLOC
- for (i = 0; i < ctx->basic_table_count; i++)
- (ctx->memfree)(ctx->arg, ctx->basic_table[i]);
- (ctx->memfree)(ctx->arg, ctx->freelists);
- (ctx->memfree)(ctx->arg, ctx->basic_table);
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ for (i = 0; i < ctx->basic_table_count; i++)
+ (ctx->memfree)(ctx->arg, ctx->basic_table[i]);
+ (ctx->memfree)(ctx->arg, ctx->freelists);
+ (ctx->memfree)(ctx->arg, ctx->basic_table);
+ }
ondest = ctx->ondestroy;
- DESTROYLOCK(&ctx->lock);
+ if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)
+ DESTROYLOCK(&ctx->lock);
(ctx->memfree)(ctx->arg, ctx);
isc_ondestroy_notify(&ondest, ctx);
@@ -900,9 +923,9 @@ isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
REQUIRE(VALID_CONTEXT(source));
REQUIRE(targetp != NULL && *targetp == NULL);
- LOCK(&source->lock);
+ MCTXLOCK(source, &source->lock);
source->references++;
- UNLOCK(&source->lock);
+ MCTXUNLOCK(source, &source->lock);
*targetp = source;
}
@@ -916,12 +939,12 @@ isc_mem_detach(isc_mem_t **ctxp) {
ctx = *ctxp;
REQUIRE(VALID_CONTEXT(ctx));
- LOCK(&ctx->lock);
+ MCTXLOCK(ctx, &ctx->lock);
INSIST(ctx->references > 0);
ctx->references--;
if (ctx->references == 0)
want_destroy = ISC_TRUE;
- UNLOCK(&ctx->lock);
+ MCTXUNLOCK(ctx, &ctx->lock);
if (want_destroy)
destroy(ctx);
@@ -943,6 +966,8 @@ void
isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
isc_mem_t *ctx;
isc_boolean_t want_destroy = ISC_FALSE;
+ size_info *si;
+ size_t oldsize;
REQUIRE(ctxp != NULL);
ctx = *ctxp;
@@ -955,14 +980,35 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
*/
*ctxp = NULL;
-#if ISC_MEM_USE_INTERNAL_MALLOC
- LOCK(&ctx->lock);
- mem_putunlocked(ctx, ptr, size);
-#else /* ISC_MEM_USE_INTERNAL_MALLOC */
- mem_put(ctx, ptr, size);
- LOCK(&ctx->lock);
- mem_putstats(ctx, ptr, size);
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
+ if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) {
+ if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) {
+ si = &(((size_info *)ptr)[-1]);
+ oldsize = si->u.size - ALIGNMENT_SIZE;
+ if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
+ oldsize -= ALIGNMENT_SIZE;
+ INSIST(oldsize == size);
+ }
+ isc__mem_free(ctx, ptr FLARG_PASS);
+
+ MCTXLOCK(ctx, &ctx->lock);
+ ctx->references--;
+ if (ctx->references == 0)
+ want_destroy = ISC_TRUE;
+ MCTXUNLOCK(ctx, &ctx->lock);
+ if (want_destroy)
+ destroy(ctx);
+
+ return;
+ }
+
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ MCTXLOCK(ctx, &ctx->lock);
+ mem_putunlocked(ctx, ptr, size);
+ } else {
+ mem_put(ctx, ptr, size);
+ MCTXLOCK(ctx, &ctx->lock);
+ mem_putstats(ctx, ptr, size);
+ }
DELETE_TRACE(ctx, ptr, size, file, line);
INSIST(ctx->references > 0);
@@ -970,7 +1016,7 @@ isc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
if (ctx->references == 0)
want_destroy = ISC_TRUE;
- UNLOCK(&ctx->lock);
+ MCTXUNLOCK(ctx, &ctx->lock);
if (want_destroy)
destroy(ctx);
@@ -989,14 +1035,14 @@ isc_mem_destroy(isc_mem_t **ctxp) {
ctx = *ctxp;
REQUIRE(VALID_CONTEXT(ctx));
- LOCK(&ctx->lock);
+ MCTXLOCK(ctx, &ctx->lock);
#if ISC_MEM_TRACKLINES
if (ctx->references != 1)
print_active(ctx, stderr);
#endif
REQUIRE(ctx->references == 1);
ctx->references--;
- UNLOCK(&ctx->lock);
+ MCTXUNLOCK(ctx, &ctx->lock);
destroy(ctx);
@@ -1007,9 +1053,9 @@ isc_result_t
isc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) {
isc_result_t res;
- LOCK(&ctx->lock);
+ MCTXLOCK(ctx, &ctx->lock);
res = isc_ondestroy_register(&ctx->ondestroy, task, event);
- UNLOCK(&ctx->lock);
+ MCTXUNLOCK(ctx, &ctx->lock);
return (res);
}
@@ -1022,15 +1068,18 @@ isc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
REQUIRE(VALID_CONTEXT(ctx));
-#if ISC_MEM_USE_INTERNAL_MALLOC
- LOCK(&ctx->lock);
- ptr = mem_getunlocked(ctx, size);
-#else /* ISC_MEM_USE_INTERNAL_MALLOC */
- ptr = mem_get(ctx, size);
- LOCK(&ctx->lock);
- if (ptr != NULL)
- mem_getstats(ctx, size);
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
+ if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0)
+ return (isc__mem_allocate(ctx, size FLARG_PASS));
+
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ MCTXLOCK(ctx, &ctx->lock);
+ ptr = mem_getunlocked(ctx, size);
+ } else {
+ ptr = mem_get(ctx, size);
+ MCTXLOCK(ctx, &ctx->lock);
+ if (ptr != NULL)
+ mem_getstats(ctx, size);
+ }
ADD_TRACE(ctx, ptr, size, file, line);
if (ctx->hi_water != 0U && !ctx->hi_called &&
@@ -1045,7 +1094,7 @@ isc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
fprintf(stderr, "maxinuse = %lu\n",
(unsigned long)ctx->inuse);
}
- UNLOCK(&ctx->lock);
+ MCTXUNLOCK(ctx, &ctx->lock);
if (call_water)
(ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
@@ -1057,18 +1106,32 @@ void
isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
{
isc_boolean_t call_water = ISC_FALSE;
+ size_info *si;
+ size_t oldsize;
REQUIRE(VALID_CONTEXT(ctx));
REQUIRE(ptr != NULL);
-#if ISC_MEM_USE_INTERNAL_MALLOC
- LOCK(&ctx->lock);
- mem_putunlocked(ctx, ptr, size);
-#else /* ISC_MEM_USE_INTERNAL_MALLOC */
- mem_put(ctx, ptr, size);
- LOCK(&ctx->lock);
- mem_putstats(ctx, ptr, size);
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
+ if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) {
+ if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) {
+ si = &(((size_info *)ptr)[-1]);
+ oldsize = si->u.size - ALIGNMENT_SIZE;
+ if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
+ oldsize -= ALIGNMENT_SIZE;
+ INSIST(oldsize == size);
+ }
+ isc__mem_free(ctx, ptr FLARG_PASS);
+ return;
+ }
+
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ MCTXLOCK(ctx, &ctx->lock);
+ mem_putunlocked(ctx, ptr, size);
+ } else {
+ mem_put(ctx, ptr, size);
+ MCTXLOCK(ctx, &ctx->lock);
+ mem_putstats(ctx, ptr, size);
+ }
DELETE_TRACE(ctx, ptr, size, file, line);
@@ -1084,7 +1147,7 @@ isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
if (ctx->water != NULL)
call_water = ISC_TRUE;
}
- UNLOCK(&ctx->lock);
+ MCTXUNLOCK(ctx, &ctx->lock);
if (call_water)
(ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
@@ -1141,7 +1204,7 @@ isc_mem_stats(isc_mem_t *ctx, FILE *out) {
const isc_mempool_t *pool;
REQUIRE(VALID_CONTEXT(ctx));
- LOCK(&ctx->lock);
+ MCTXLOCK(ctx, &ctx->lock);
for (i = 0; i <= ctx->max_size; i++) {
s = &ctx->stats[i];
@@ -1151,11 +1214,10 @@ isc_mem_stats(isc_mem_t *ctx, FILE *out) {
fprintf(out, "%s%5lu: %11lu gets, %11lu rem",
(i == ctx->max_size) ? ">=" : " ",
(unsigned long) i, s->totalgets, s->gets);
-#if ISC_MEM_USE_INTERNAL_MALLOC
- if (s->blocks != 0 || s->freefrags != 0)
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0 &&
+ (s->blocks != 0U || s->freefrags != 0U))
fprintf(out, " (%lu bl, %lu ff)",
s->blocks, s->freefrags);
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
fputc('\n', out);
}
@@ -1203,7 +1265,7 @@ isc_mem_stats(isc_mem_t *ctx, FILE *out) {
print_active(ctx, out);
#endif
- UNLOCK(&ctx->lock);
+ MCTXUNLOCK(ctx, &ctx->lock);
}
/*
@@ -1216,13 +1278,20 @@ isc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) {
size_info *si;
size += ALIGNMENT_SIZE;
-#if ISC_MEM_USE_INTERNAL_MALLOC
- si = mem_getunlocked(ctx, size);
-#else /* ISC_MEM_USE_INTERNAL_MALLOC */
- si = mem_get(ctx, size);
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
+ if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
+ size += ALIGNMENT_SIZE;
+
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0)
+ si = mem_getunlocked(ctx, size);
+ else
+ si = mem_get(ctx, size);
+
if (si == NULL)
return (NULL);
+ if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) {
+ si->u.ctx = ctx;
+ si++;
+ }
si->u.size = size;
return (&si[1]);
}
@@ -1230,24 +1299,39 @@ isc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) {
void *
isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
size_info *si;
+ isc_boolean_t call_water = ISC_FALSE;
REQUIRE(VALID_CONTEXT(ctx));
-#if ISC_MEM_USE_INTERNAL_MALLOC
- LOCK(&ctx->lock);
- si = isc__mem_allocateunlocked(ctx, size);
-#else /* ISC_MEM_USE_INTERNAL_MALLOC */
- si = isc__mem_allocateunlocked(ctx, size);
- LOCK(&ctx->lock);
- if (si != NULL)
- mem_getstats(ctx, si[-1].u.size);
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ MCTXLOCK(ctx, &ctx->lock);
+ si = isc__mem_allocateunlocked(ctx, size);
+ } else {
+ si = isc__mem_allocateunlocked(ctx, size);
+ MCTXLOCK(ctx, &ctx->lock);
+ if (si != NULL)
+ mem_getstats(ctx, si[-1].u.size);
+ }
#if ISC_MEM_TRACKLINES
ADD_TRACE(ctx, si, si[-1].u.size, file, line);
#endif
+ if (ctx->hi_water != 0U && !ctx->hi_called &&
+ ctx->inuse > ctx->hi_water) {
+ ctx->hi_called = ISC_TRUE;
+ call_water = ISC_TRUE;
+ }
+ if (ctx->inuse > ctx->maxinuse) {
+ ctx->maxinuse = ctx->inuse;
+ if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&
+ (isc_mem_debugging & ISC_MEM_DEBUGUSAGE) != 0)
+ fprintf(stderr, "maxinuse = %lu\n",
+ (unsigned long)ctx->inuse);
+ }
+ MCTXUNLOCK(ctx, &ctx->lock);
- UNLOCK(&ctx->lock);
+ if (call_water)
+ (ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
return (si);
}
@@ -1256,25 +1340,47 @@ void
isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) {
size_info *si;
size_t size;
+ isc_boolean_t call_water= ISC_FALSE;
REQUIRE(VALID_CONTEXT(ctx));
REQUIRE(ptr != NULL);
- si = &(((size_info *)ptr)[-1]);
- size = si->u.size;
+ if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) {
+ si = &(((size_info *)ptr)[-2]);
+ REQUIRE(si->u.ctx == ctx);
+ size = si[1].u.size;
+ } else {
+ si = &(((size_info *)ptr)[-1]);
+ size = si->u.size;
+ }
-#if ISC_MEM_USE_INTERNAL_MALLOC
- LOCK(&ctx->lock);
- mem_putunlocked(ctx, si, size);
-#else /* ISC_MEM_USE_INTERNAL_MALLOC */
- mem_put(ctx, si, size);
- LOCK(&ctx->lock);
- mem_putstats(ctx, si, size);
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
+ if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ MCTXLOCK(ctx, &ctx->lock);
+ mem_putunlocked(ctx, si, size);
+ } else {
+ mem_put(ctx, si, size);
+ MCTXLOCK(ctx, &ctx->lock);
+ mem_putstats(ctx, si, size);
+ }
DELETE_TRACE(ctx, ptr, size, file, line);
- UNLOCK(&ctx->lock);
+ /*
+ * The check against ctx->lo_water == 0 is for the condition
+ * when the context was pushed over hi_water but then had
+ * isc_mem_setwater() called with 0 for hi_water and lo_water.
+ */
+ if (ctx->hi_called &&
+ (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
+ ctx->hi_called = ISC_FALSE;
+
+ if (ctx->water != NULL)
+ call_water = ISC_TRUE;
+ }
+ MCTXUNLOCK(ctx, &ctx->lock);
+
+ if (call_water)
+ (ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
}
@@ -1303,11 +1409,11 @@ isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
void
isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) {
REQUIRE(VALID_CONTEXT(ctx));
- LOCK(&ctx->lock);
+ MCTXLOCK(ctx, &ctx->lock);
ctx->checkfree = flag;
- UNLOCK(&ctx->lock);
+ MCTXUNLOCK(ctx, &ctx->lock);
}
/*
@@ -1317,11 +1423,11 @@ isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) {
void
isc_mem_setquota(isc_mem_t *ctx, size_t quota) {
REQUIRE(VALID_CONTEXT(ctx));
- LOCK(&ctx->lock);
+ MCTXLOCK(ctx, &ctx->lock);
ctx->quota = quota;
- UNLOCK(&ctx->lock);
+ MCTXUNLOCK(ctx, &ctx->lock);
}
size_t
@@ -1329,11 +1435,11 @@ isc_mem_getquota(isc_mem_t *ctx) {
size_t quota;
REQUIRE(VALID_CONTEXT(ctx));
- LOCK(&ctx->lock);
+ MCTXLOCK(ctx, &ctx->lock);
quota = ctx->quota;
- UNLOCK(&ctx->lock);
+ MCTXUNLOCK(ctx, &ctx->lock);
return (quota);
}
@@ -1343,11 +1449,11 @@ isc_mem_inuse(isc_mem_t *ctx) {
size_t inuse;
REQUIRE(VALID_CONTEXT(ctx));
- LOCK(&ctx->lock);
+ MCTXLOCK(ctx, &ctx->lock);
inuse = ctx->inuse;
- UNLOCK(&ctx->lock);
+ MCTXUNLOCK(ctx, &ctx->lock);
return (inuse);
}
@@ -1356,24 +1462,38 @@ void
isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
size_t hiwater, size_t lowater)
{
+ isc_boolean_t callwater = ISC_FALSE;
+ isc_mem_water_t oldwater;
+ void *oldwater_arg;
+
REQUIRE(VALID_CONTEXT(ctx));
REQUIRE(hiwater >= lowater);
- LOCK(&ctx->lock);
+ MCTXLOCK(ctx, &ctx->lock);
+ oldwater = ctx->water;
+ oldwater_arg = ctx->water_arg;
if (water == NULL) {
+ callwater = ctx->hi_called;
ctx->water = NULL;
ctx->water_arg = NULL;
ctx->hi_water = 0;
ctx->lo_water = 0;
ctx->hi_called = ISC_FALSE;
} else {
+ if (ctx->hi_called &&
+ (ctx->water != water || ctx->water_arg != water_arg ||
+ ctx->inuse < lowater || lowater == 0U))
+ callwater = ISC_TRUE;
ctx->water = water;
ctx->water_arg = water_arg;
ctx->hi_water = hiwater;
ctx->lo_water = lowater;
ctx->hi_called = ISC_FALSE;
}
- UNLOCK(&ctx->lock);
+ MCTXUNLOCK(ctx, &ctx->lock);
+
+ if (callwater && oldwater != NULL)
+ (oldwater)(oldwater_arg, ISC_MEM_LOWATER);
}
/*
@@ -1413,9 +1533,9 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
*mpctxp = mpctx;
- LOCK(&mctx->lock);
+ MCTXLOCK(mctx, &mctx->lock);
ISC_LIST_INITANDAPPEND(mctx->pools, mpctx, link);
- UNLOCK(&mctx->lock);
+ MCTXUNLOCK(mctx, &mctx->lock);
return (ISC_R_SUCCESS);
}
@@ -1468,28 +1588,28 @@ isc_mempool_destroy(isc_mempool_t **mpctxp) {
/*
* Return any items on the free list
*/
- LOCK(&mctx->lock);
+ MCTXLOCK(mctx, &mctx->lock);
while (mpctx->items != NULL) {
INSIST(mpctx->freecount > 0);
mpctx->freecount--;
item = mpctx->items;
mpctx->items = item->next;
-#if ISC_MEM_USE_INTERNAL_MALLOC
- mem_putunlocked(mctx, item, mpctx->size);
-#else /* ISC_MEM_USE_INTERNAL_MALLOC */
- mem_put(mctx, item, mpctx->size);
- mem_putstats(mctx, item, mpctx->size);
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
+ if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ mem_putunlocked(mctx, item, mpctx->size);
+ } else {
+ mem_put(mctx, item, mpctx->size);
+ mem_putstats(mctx, item, mpctx->size);
+ }
}
- UNLOCK(&mctx->lock);
+ MCTXUNLOCK(mctx, &mctx->lock);
/*
* Remove our linked list entry from the memory context.
*/
- LOCK(&mctx->lock);
+ MCTXLOCK(mctx, &mctx->lock);
ISC_LIST_UNLINK(mctx->pools, mpctx, link);
- UNLOCK(&mctx->lock);
+ MCTXUNLOCK(mctx, &mctx->lock);
mpctx->magic = 0;
@@ -1548,22 +1668,22 @@ isc__mempool_get(isc_mempool_t *mpctx FLARG) {
* We need to dip into the well. Lock the memory context here and
* fill up our free list.
*/
- LOCK(&mctx->lock);
+ MCTXLOCK(mctx, &mctx->lock);
for (i = 0; i < mpctx->fillcount; i++) {
-#if ISC_MEM_USE_INTERNAL_MALLOC
- item = mem_getunlocked(mctx, mpctx->size);
-#else /* ISC_MEM_USE_INTERNAL_MALLOC */
- item = mem_get(mctx, mpctx->size);
- if (item != NULL)
- mem_getstats(mctx, mpctx->size);
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
+ if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ item = mem_getunlocked(mctx, mpctx->size);
+ } else {
+ item = mem_get(mctx, mpctx->size);
+ if (item != NULL)
+ mem_getstats(mctx, mpctx->size);
+ }
if (item == NULL)
break;
item->next = mpctx->items;
mpctx->items = item;
mpctx->freecount++;
}
- UNLOCK(&mctx->lock);
+ MCTXUNLOCK(mctx, &mctx->lock);
/*
* If we didn't get any items, return NULL.
@@ -1583,9 +1703,9 @@ isc__mempool_get(isc_mempool_t *mpctx FLARG) {
#if ISC_MEM_TRACKLINES
if (item != NULL) {
- LOCK(&mctx->lock);
+ MCTXLOCK(mctx, &mctx->lock);
ADD_TRACE(mctx, item, mpctx->size, file, line);
- UNLOCK(&mctx->lock);
+ MCTXUNLOCK(mctx, &mctx->lock);
}
#endif /* ISC_MEM_TRACKLINES */
@@ -1609,25 +1729,25 @@ isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
mpctx->allocated--;
#if ISC_MEM_TRACKLINES
- LOCK(&mctx->lock);
+ MCTXLOCK(mctx, &mctx->lock);
DELETE_TRACE(mctx, mem, mpctx->size, file, line);
- UNLOCK(&mctx->lock);
+ MCTXUNLOCK(mctx, &mctx->lock);
#endif /* ISC_MEM_TRACKLINES */
/*
* If our free list is full, return this to the mctx directly.
*/
if (mpctx->freecount >= mpctx->freemax) {
-#if ISC_MEM_USE_INTERNAL_MALLOC
- LOCK(&mctx->lock);
- mem_putunlocked(mctx, mem, mpctx->size);
- UNLOCK(&mctx->lock);
-#else /* ISC_MEM_USE_INTERNAL_MALLOC */
- mem_put(mctx, mem, mpctx->size);
- LOCK(&mctx->lock);
- mem_putstats(mctx, mem, mpctx->size);
- UNLOCK(&mctx->lock);
-#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
+ if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
+ MCTXLOCK(mctx, &mctx->lock);
+ mem_putunlocked(mctx, mem, mpctx->size);
+ MCTXUNLOCK(mctx, &mctx->lock);
+ } else {
+ mem_put(mctx, mem, mpctx->size);
+ MCTXLOCK(mctx, &mctx->lock);
+ mem_putstats(mctx, mem, mpctx->size);
+ MCTXUNLOCK(mctx, &mctx->lock);
+ }
if (mpctx->lock != NULL)
UNLOCK(mpctx->lock);
return;
@@ -1775,3 +1895,60 @@ isc_mempool_getfillcount(isc_mempool_t *mpctx) {
return (fillcount);
}
+
+void
+isc_mem_printactive(isc_mem_t *ctx, FILE *file) {
+
+ REQUIRE(VALID_CONTEXT(ctx));
+ REQUIRE(file != NULL);
+
+#if !ISC_MEM_TRACKLINES
+ UNUSED(ctx);
+ UNUSED(file);
+#else
+ print_active(ctx, file);
+#endif
+}
+
+void
+isc_mem_printallactive(FILE *file) {
+#if !ISC_MEM_TRACKLINES
+ UNUSED(file);
+#else
+ isc_mem_t *ctx;
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+
+ LOCK(&lock);
+ for (ctx = ISC_LIST_HEAD(contexts);
+ ctx != NULL;
+ ctx = ISC_LIST_NEXT(ctx, link)) {
+ fprintf(file, "context: %p\n", ctx);
+ print_active(ctx, file);
+ }
+ UNLOCK(&lock);
+#endif
+}
+
+void
+isc_mem_checkdestroyed(FILE *file) {
+
+ RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
+
+ LOCK(&lock);
+ if (!ISC_LIST_EMPTY(contexts)) {
+#if ISC_MEM_TRACKLINES
+ isc_mem_t *ctx;
+
+ for (ctx = ISC_LIST_HEAD(contexts);
+ ctx != NULL;
+ ctx = ISC_LIST_NEXT(ctx, link)) {
+ fprintf(file, "context: %p\n", ctx);
+ print_active(ctx, file);
+ }
+ fflush(file);
+#endif
+ INSIST(1);
+ }
+ UNLOCK(&lock);
+}
OpenPOWER on IntegriCloud