* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: main.c,v 1.146 2005/04/29 00:36:15 marka Exp $ */
+/* $Id: main.c,v 1.147 2005/06/10 07:00:19 marka Exp $ */
/*! \file */
" [-f|-g] [-n number_of_cpus] [-p port] "
"[-P listen-port] [-s]\n"
" [-t chrootdir] [-u username] [-i pidfile]\n"
- " [-m {usage|trace|record}]\n");
+ " [-m {usage|trace|record|size|mctx}]\n");
}
static void
"usage: named [-4|-6] [-c conffile] [-d debuglevel] "
"[-f|-g] [-n number_of_cpus]\n"
" [-p port] [-s] [-t chrootdir] [-u username]\n"
- " [-m {usage|trace|record}]\n");
+ " [-m {usage|trace|record|size|mctx}]\n");
}
static void
{ "trace", ISC_MEM_DEBUGTRACE },
{ "record", ISC_MEM_DEBUGRECORD },
{ "usage", ISC_MEM_DEBUGUSAGE },
+ { "size", ISC_MEM_DEBUGSIZE },
+ { "mctx", ISC_MEM_DEBUGCTX },
{ NULL, 0 }
};
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mem.h,v 1.63 2005/06/04 05:32:48 jinmei Exp $ */
+/* $Id: mem.h,v 1.64 2005/06/10 07:00:20 marka Exp $ */
#ifndef ISC_MEM_H
#define ISC_MEM_H 1
#define ISC_MEM_DEBUGTRACE 0x00000001U
#define ISC_MEM_DEBUGRECORD 0x00000002U
#define ISC_MEM_DEBUGUSAGE 0x00000004U
+#define ISC_MEM_DEBUGSIZE 0x00000008U
+#define ISC_MEM_DEBUGCTX 0x00000010U
+#define ISC_MEM_DEBUGALL 0x0000001FU
/*!<
* The variable isc_mem_debugging holds a set of flags for
* turning certain memory debugging options on or off at
* \li #ISC_MEM_DEBUGUSAGE
* If a hi_water mark is set, print the maximium inuse memory
* every time it is raised once it exceeds the hi_water mark.
+ *
+ * \li #ISC_MEM_DEBUGSIZE
+ * Check the size arguement being passed to isc_mem_put() matches
+ * that passed to isc_mem_get().
+ *
+ * \li #ISC_MEM_DEBUGCTX
+ * Check the mctx arguement being passed to isc_mem_put() matches
+ * that passed to isc_mem_get().
*/
/*@}*/
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: mem.c,v 1.120 2005/06/04 05:32:48 jinmei Exp $ */
+/* $Id: mem.c,v 1.121 2005/06/10 07:00:19 marka Exp $ */
/*! \file */
*/
union {
size_t size;
+ isc_mem_t *ctx;
char bytes[ALIGNMENT_SIZE];
} u;
} size_info;
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;
*/
*ctxp = NULL;
+ 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 ISC_MEM_USE_INTERNAL_MALLOC
MCTXLOCK(ctx, &ctx->lock);
mem_putunlocked(ctx, ptr, size);
REQUIRE(VALID_CONTEXT(ctx));
+ if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0)
+ return (isc__mem_allocate(ctx, size FLARG_PASS));
#if ISC_MEM_USE_INTERNAL_MALLOC
MCTXLOCK(ctx, &ctx->lock);
ptr = mem_getunlocked(ctx, size);
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_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 ISC_MEM_USE_INTERNAL_MALLOC
MCTXLOCK(ctx, &ctx->lock);
mem_putunlocked(ctx, ptr, size);
size_info *si;
size += ALIGNMENT_SIZE;
+ if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
+ size += ALIGNMENT_SIZE;
#if ISC_MEM_USE_INTERNAL_MALLOC
si = mem_getunlocked(ctx, size);
#else /* ISC_MEM_USE_INTERNAL_MALLOC */
#endif /* ISC_MEM_USE_INTERNAL_MALLOC */
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]);
}
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_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);
+ if (call_water)
+ (ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
+
return (si);
}
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
MCTXLOCK(ctx, &ctx->lock);
DELETE_TRACE(ctx, ptr, size, file, line);
+ /*
+ * 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);
}