Home | History | Annotate | Line # | Download | only in isc
mem.c revision 1.1.1.1
      1 /*	$NetBSD: mem.c,v 1.1.1.1 2018/08/12 12:08:23 christos Exp $	*/
      2 
      3 /*
      4  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5  *
      6  * This Source Code Form is subject to the terms of the Mozilla Public
      7  * License, v. 2.0. If a copy of the MPL was not distributed with this
      8  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
      9  *
     10  * See the COPYRIGHT file distributed with this work for additional
     11  * information regarding copyright ownership.
     12  */
     13 
     14 /*! \file */
     15 
     16 #include <config.h>
     17 
     18 #include <stdio.h>
     19 #include <stdlib.h>
     20 #include <stddef.h>
     21 
     22 #include <limits.h>
     23 
     24 #include <isc/bind9.h>
     25 #include <isc/json.h>
     26 #include <isc/magic.h>
     27 #include <isc/hash.h>
     28 #include <isc/mem.h>
     29 #include <isc/msgs.h>
     30 #include <isc/once.h>
     31 #include <isc/ondestroy.h>
     32 #include <isc/string.h>
     33 #include <isc/mutex.h>
     34 #include <isc/print.h>
     35 #include <isc/util.h>
     36 #include <isc/xml.h>
     37 
     38 #define MCTXLOCK(m, l) if (((m)->flags & ISC_MEMFLAG_NOLOCK) == 0) LOCK(l)
     39 #define MCTXUNLOCK(m, l) if (((m)->flags & ISC_MEMFLAG_NOLOCK) == 0) UNLOCK(l)
     40 
     41 #ifndef ISC_MEM_DEBUGGING
     42 #define ISC_MEM_DEBUGGING 0
     43 #endif
     44 LIBISC_EXTERNAL_DATA unsigned int isc_mem_debugging = ISC_MEM_DEBUGGING;
     45 LIBISC_EXTERNAL_DATA unsigned int isc_mem_defaultflags = ISC_MEMFLAG_DEFAULT;
     46 
     47 /*
     48  * Constants.
     49  */
     50 
     51 #define DEF_MAX_SIZE		1100
     52 #define DEF_MEM_TARGET		4096
     53 #define ALIGNMENT_SIZE		8U		/*%< must be a power of 2 */
     54 #define NUM_BASIC_BLOCKS	64		/*%< must be > 1 */
     55 #define TABLE_INCREMENT		1024
     56 #define DEBUG_TABLE_COUNT	512U
     57 
     58 /*
     59  * Types.
     60  */
     61 typedef struct isc__mem isc__mem_t;
     62 typedef struct isc__mempool isc__mempool_t;
     63 
     64 #if ISC_MEM_TRACKLINES
     65 typedef struct debuglink debuglink_t;
     66 struct debuglink {
     67 	ISC_LINK(debuglink_t)	link;
     68 	const void	       *ptr;
     69 	size_t			size;
     70 	const char	       *file;
     71 	unsigned int		line;
     72 };
     73 
     74 typedef ISC_LIST(debuglink_t)	debuglist_t;
     75 
     76 #define FLARG_PASS	, file, line
     77 #define FLARG		, const char *file, unsigned int line
     78 #else
     79 #define FLARG_PASS
     80 #define FLARG
     81 #endif
     82 
     83 typedef struct element element;
     84 struct element {
     85 	element *		next;
     86 };
     87 
     88 typedef struct {
     89 	/*!
     90 	 * This structure must be ALIGNMENT_SIZE bytes.
     91 	 */
     92 	union {
     93 		size_t		size;
     94 		isc__mem_t	*ctx;
     95 		char		bytes[ALIGNMENT_SIZE];
     96 	} u;
     97 } size_info;
     98 
     99 struct stats {
    100 	unsigned long		gets;
    101 	unsigned long		totalgets;
    102 	unsigned long		blocks;
    103 	unsigned long		freefrags;
    104 };
    105 
    106 #define MEM_MAGIC		ISC_MAGIC('M', 'e', 'm', 'C')
    107 #define VALID_CONTEXT(c)	ISC_MAGIC_VALID(c, MEM_MAGIC)
    108 
    109 /* List of all active memory contexts. */
    110 
    111 static ISC_LIST(isc__mem_t)	contexts;
    112 
    113 static isc_once_t		once = ISC_ONCE_INIT;
    114 static isc_mutex_t		contextslock;
    115 static isc_mutex_t 		createlock;
    116 
    117 /*%
    118  * Total size of lost memory due to a bug of external library.
    119  * Locked by the global lock.
    120  */
    121 static isc_uint64_t		totallost;
    122 
    123 struct isc__mem {
    124 	isc_mem_t		common;
    125 	isc_ondestroy_t		ondestroy;
    126 	unsigned int		flags;
    127 	isc_mutex_t		lock;
    128 	isc_memalloc_t		memalloc;
    129 	isc_memfree_t		memfree;
    130 	void *			arg;
    131 	size_t			max_size;
    132 	isc_boolean_t		checkfree;
    133 	struct stats *		stats;
    134 	unsigned int		references;
    135 	char			name[16];
    136 	void *			tag;
    137 	size_t			quota;
    138 	size_t			total;
    139 	size_t			inuse;
    140 	size_t			maxinuse;
    141 	size_t			malloced;
    142 	size_t			maxmalloced;
    143 	size_t			hi_water;
    144 	size_t			lo_water;
    145 	isc_boolean_t		hi_called;
    146 	isc_boolean_t		is_overmem;
    147 	isc_mem_water_t		water;
    148 	void *			water_arg;
    149 	ISC_LIST(isc__mempool_t) pools;
    150 	unsigned int		poolcnt;
    151 
    152 	/*  ISC_MEMFLAG_INTERNAL */
    153 	size_t			mem_target;
    154 	element **		freelists;
    155 	element *		basic_blocks;
    156 	unsigned char **	basic_table;
    157 	unsigned int		basic_table_count;
    158 	unsigned int		basic_table_size;
    159 	unsigned char *		lowest;
    160 	unsigned char *		highest;
    161 
    162 #if ISC_MEM_TRACKLINES
    163 	debuglist_t *	 	debuglist;
    164 	size_t			debuglistcnt;
    165 #endif
    166 
    167 	unsigned int		memalloc_failures;
    168 	ISC_LINK(isc__mem_t)	link;
    169 };
    170 
    171 #define MEMPOOL_MAGIC		ISC_MAGIC('M', 'E', 'M', 'p')
    172 #define VALID_MEMPOOL(c)	ISC_MAGIC_VALID(c, MEMPOOL_MAGIC)
    173 
    174 struct isc__mempool {
    175 	/* always unlocked */
    176 	isc_mempool_t	common;		/*%< common header of mempool's */
    177 	isc_mutex_t    *lock;		/*%< optional lock */
    178 	isc__mem_t      *mctx;		/*%< our memory context */
    179 	/*%< locked via the memory context's lock */
    180 	ISC_LINK(isc__mempool_t)	link;	/*%< next pool in this mem context */
    181 	/*%< optionally locked from here down */
    182 	element	       *items;		/*%< low water item list */
    183 	size_t		size;		/*%< size of each item on this pool */
    184 	unsigned int	maxalloc;	/*%< max number of items allowed */
    185 	unsigned int	allocated;	/*%< # of items currently given out */
    186 	unsigned int	freecount;	/*%< # of items on reserved list */
    187 	unsigned int	freemax;	/*%< # of items allowed on free list */
    188 	unsigned int	fillcount;	/*%< # of items to fetch on each fill */
    189 	/*%< Stats only. */
    190 	unsigned int	gets;		/*%< # of requests to this pool */
    191 	/*%< Debugging only. */
    192 #if ISC_MEMPOOL_NAMES
    193 	char		name[16];	/*%< printed name in stats reports */
    194 #endif
    195 };
    196 
    197 /*
    198  * Private Inline-able.
    199  */
    200 
    201 #if ! ISC_MEM_TRACKLINES
    202 #define ADD_TRACE(a, b, c, d, e)
    203 #define DELETE_TRACE(a, b, c, d, e)
    204 #define ISC_MEMFUNC_SCOPE
    205 #else
    206 #define TRACE_OR_RECORD (ISC_MEM_DEBUGTRACE|ISC_MEM_DEBUGRECORD)
    207 #define ADD_TRACE(a, b, c, d, e) \
    208 	do { \
    209 		if (ISC_UNLIKELY((isc_mem_debugging & TRACE_OR_RECORD) != 0 && \
    210 				 b != NULL))				\
    211 			add_trace_entry(a, b, c, d, e);			\
    212 	} while (0)
    213 #define DELETE_TRACE(a, b, c, d, e)					\
    214 	do {								\
    215 		if (ISC_UNLIKELY((isc_mem_debugging & TRACE_OR_RECORD) != 0 && \
    216 				 b != NULL))				\
    217 			delete_trace_entry(a, b, c, d, e);		\
    218 	} while(0)
    219 
    220 static void
    221 print_active(isc__mem_t *ctx, FILE *out);
    222 
    223 #endif /* ISC_MEM_TRACKLINES */
    224 
    225 /*%
    226  * The following are intended for internal use (indicated by "isc__"
    227  * prefix) but are not declared as static, allowing direct access
    228  * from unit tests, etc.
    229  */
    230 
    231 isc_result_t
    232 isc__mem_create2(size_t init_max_size, size_t target_size,
    233 		 isc_mem_t **ctxp, unsigned int flags);
    234 void
    235 isc__mem_attach(isc_mem_t *source, isc_mem_t **targetp);
    236 void
    237 isc__mem_detach(isc_mem_t **ctxp);
    238 void
    239 isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG);
    240 void
    241 isc__mem_destroy(isc_mem_t **ctxp);
    242 isc_result_t
    243 isc__mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event);
    244 void *
    245 isc___mem_get(isc_mem_t *ctx, size_t size FLARG);
    246 void
    247 isc___mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG);
    248 void
    249 isc__mem_stats(isc_mem_t *ctx, FILE *out);
    250 void *
    251 isc___mem_allocate(isc_mem_t *ctx, size_t size FLARG);
    252 void *
    253 isc___mem_reallocate(isc_mem_t *ctx, void *ptr, size_t size FLARG);
    254 void
    255 isc___mem_free(isc_mem_t *ctx, void *ptr FLARG);
    256 char *
    257 isc___mem_strdup(isc_mem_t *mctx, const char *s FLARG);
    258 void
    259 isc__mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag);
    260 void
    261 isc__mem_setquota(isc_mem_t *ctx, size_t quota);
    262 size_t
    263 isc__mem_getquota(isc_mem_t *ctx);
    264 size_t
    265 isc__mem_inuse(isc_mem_t *ctx);
    266 size_t
    267 isc__mem_maxinuse(isc_mem_t *ctx);
    268 size_t
    269 isc__mem_total(isc_mem_t *ctx);
    270 isc_boolean_t
    271 isc__mem_isovermem(isc_mem_t *ctx);
    272 void
    273 isc__mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
    274 		  size_t hiwater, size_t lowater);
    275 void
    276 isc__mem_waterack(isc_mem_t *ctx0, int flag);
    277 void
    278 isc__mem_setname(isc_mem_t *ctx, const char *name, void *tag);
    279 const char *
    280 isc__mem_getname(isc_mem_t *ctx);
    281 void *
    282 isc__mem_gettag(isc_mem_t *ctx);
    283 isc_result_t
    284 isc__mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp);
    285 void
    286 isc__mempool_setname(isc_mempool_t *mpctx, const char *name);
    287 void
    288 isc__mempool_destroy(isc_mempool_t **mpctxp);
    289 void
    290 isc__mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock);
    291 void *
    292 isc___mempool_get(isc_mempool_t *mpctx FLARG);
    293 void
    294 isc___mempool_put(isc_mempool_t *mpctx, void *mem FLARG);
    295 void
    296 isc__mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit);
    297 unsigned int
    298 isc__mempool_getfreemax(isc_mempool_t *mpctx);
    299 unsigned int
    300 isc__mempool_getfreecount(isc_mempool_t *mpctx);
    301 void
    302 isc__mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit);
    303 unsigned int
    304 isc__mempool_getmaxalloc(isc_mempool_t *mpctx);
    305 unsigned int
    306 isc__mempool_getallocated(isc_mempool_t *mpctx);
    307 void
    308 isc__mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit);
    309 unsigned int
    310 isc__mempool_getfillcount(isc_mempool_t *mpctx);
    311 void
    312 isc__mem_printactive(isc_mem_t *ctx0, FILE *file);
    313 unsigned int
    314 isc__mem_references(isc_mem_t *ctx0);
    315 
    316 static struct isc__memmethods {
    317 	isc_memmethods_t methods;
    318 
    319 	/*%
    320 	 * The following are defined just for avoiding unused static functions.
    321 	 */
    322 	void *createx, *create, *create2, *ondestroy, *stats,
    323 	     *setquota, *getquota, *setname, *getname, *gettag;
    324 } memmethods = {
    325 	{
    326 		isc__mem_attach,
    327 		isc__mem_detach,
    328 		isc__mem_destroy,
    329 		isc___mem_get,
    330 		isc___mem_put,
    331 		isc___mem_putanddetach,
    332 		isc___mem_allocate,
    333 		isc___mem_reallocate,
    334 		isc___mem_strdup,
    335 		isc___mem_free,
    336 		isc__mem_setdestroycheck,
    337 		isc__mem_setwater,
    338 		isc__mem_waterack,
    339 		isc__mem_inuse,
    340 		isc__mem_maxinuse,
    341 		isc__mem_total,
    342 		isc__mem_isovermem,
    343 		isc__mempool_create
    344 	},
    345 	(void *)isc_mem_createx,
    346 	(void *)isc_mem_create,
    347 	(void *)isc_mem_create2,
    348 	(void *)isc_mem_ondestroy,
    349 	(void *)isc_mem_stats,
    350 	(void *)isc_mem_setquota,
    351 	(void *)isc_mem_getquota,
    352 	(void *)isc_mem_setname,
    353 	(void *)isc_mem_getname,
    354 	(void *)isc_mem_gettag
    355 };
    356 
    357 static struct isc__mempoolmethods {
    358 	isc_mempoolmethods_t methods;
    359 
    360 	/*%
    361 	 * The following are defined just for avoiding unused static functions.
    362 	 */
    363 	void *getfreemax, *getfreecount, *getmaxalloc, *getfillcount;
    364 } mempoolmethods = {
    365 	{
    366 		isc__mempool_destroy,
    367 		isc___mempool_get,
    368 		isc___mempool_put,
    369 		isc__mempool_getallocated,
    370 		isc__mempool_setmaxalloc,
    371 		isc__mempool_setfreemax,
    372 		isc__mempool_setname,
    373 		isc__mempool_associatelock,
    374 		isc__mempool_setfillcount
    375 	},
    376 	(void *)isc_mempool_getfreemax,
    377 	(void *)isc_mempool_getfreecount,
    378 	(void *)isc_mempool_getmaxalloc,
    379 	(void *)isc_mempool_getfillcount
    380 };
    381 
    382 #if ISC_MEM_TRACKLINES
    383 /*!
    384  * mctx must be locked.
    385  */
    386 static void
    387 add_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size FLARG) {
    388 	debuglink_t *dl;
    389 	isc_uint32_t hash;
    390 	isc_uint32_t idx;
    391 
    392 	if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)
    393 		fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
    394 					       ISC_MSG_ADDTRACE,
    395 					       "add %p size %u "
    396 					       "file %s line %u mctx %p\n"),
    397 			ptr, size, file, line, mctx);
    398 
    399 	if (mctx->debuglist == NULL)
    400 		return;
    401 
    402 	hash = isc_hash_function(&ptr, sizeof(ptr), ISC_TRUE, NULL);
    403 	idx = hash % DEBUG_TABLE_COUNT;
    404 
    405 	dl = malloc(sizeof(debuglink_t));
    406 	INSIST(dl != NULL);
    407 	mctx->malloced += sizeof(debuglink_t);
    408 	if (mctx->malloced > mctx->maxmalloced)
    409 		mctx->maxmalloced = mctx->malloced;
    410 
    411 	ISC_LINK_INIT(dl, link);
    412 	dl->ptr = ptr;
    413 	dl->size = size;
    414 	dl->file = file;
    415 	dl->line = line;
    416 
    417 	ISC_LIST_PREPEND(mctx->debuglist[idx], dl, link);
    418 	mctx->debuglistcnt++;
    419 }
    420 
    421 static void
    422 delete_trace_entry(isc__mem_t *mctx, const void *ptr, size_t size,
    423 		   const char *file, unsigned int line)
    424 {
    425 	debuglink_t *dl;
    426 	isc_uint32_t hash;
    427 	isc_uint32_t idx;
    428 
    429 	if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)
    430 		fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
    431 					       ISC_MSG_DELTRACE,
    432 					       "del %p size %u "
    433 					       "file %s line %u mctx %p\n"),
    434 			ptr, size, file, line, mctx);
    435 
    436 	if (mctx->debuglist == NULL)
    437 		return;
    438 
    439 	hash = isc_hash_function(&ptr, sizeof(ptr), ISC_TRUE, NULL);
    440 	idx = hash % DEBUG_TABLE_COUNT;
    441 
    442 	dl = ISC_LIST_HEAD(mctx->debuglist[idx]);
    443 	while (ISC_LIKELY(dl != NULL)) {
    444 		if (ISC_UNLIKELY(dl->ptr == ptr)) {
    445 			ISC_LIST_UNLINK(mctx->debuglist[idx], dl, link);
    446 			mctx->malloced -= sizeof(*dl);
    447 			free(dl);
    448 			return;
    449 		}
    450 		dl = ISC_LIST_NEXT(dl, link);
    451 	}
    452 
    453 	/*
    454 	 * If we get here, we didn't find the item on the list.  We're
    455 	 * screwed.
    456 	 */
    457 	INSIST(0);
    458 }
    459 #endif /* ISC_MEM_TRACKLINES */
    460 
    461 static inline size_t
    462 rmsize(size_t size) {
    463 	/*
    464 	 * round down to ALIGNMENT_SIZE
    465 	 */
    466 	return (size & (~(ALIGNMENT_SIZE - 1)));
    467 }
    468 
    469 static inline size_t
    470 quantize(size_t size) {
    471 	/*!
    472 	 * Round up the result in order to get a size big
    473 	 * enough to satisfy the request and be aligned on ALIGNMENT_SIZE
    474 	 * byte boundaries.
    475 	 */
    476 
    477 	if (size == 0U)
    478 		return (ALIGNMENT_SIZE);
    479 	return ((size + ALIGNMENT_SIZE - 1) & (~(ALIGNMENT_SIZE - 1)));
    480 }
    481 
    482 static inline isc_boolean_t
    483 more_basic_blocks(isc__mem_t *ctx) {
    484 	void *tmp;
    485 	unsigned char *curr, *next;
    486 	unsigned char *first, *last;
    487 	unsigned char **table;
    488 	unsigned int table_size;
    489 	size_t increment;
    490 	int i;
    491 
    492 	/* Require: we hold the context lock. */
    493 
    494 	/*
    495 	 * Did we hit the quota for this context?
    496 	 */
    497 	increment = NUM_BASIC_BLOCKS * ctx->mem_target;
    498 	if (ctx->quota != 0U && ctx->total + increment > ctx->quota)
    499 		return (ISC_FALSE);
    500 
    501 	INSIST(ctx->basic_table_count <= ctx->basic_table_size);
    502 	if (ctx->basic_table_count == ctx->basic_table_size) {
    503 		table_size = ctx->basic_table_size + TABLE_INCREMENT;
    504 		table = (ctx->memalloc)(ctx->arg,
    505 					table_size * sizeof(unsigned char *));
    506 		if (table == NULL) {
    507 			ctx->memalloc_failures++;
    508 			return (ISC_FALSE);
    509 		}
    510 		ctx->malloced += table_size * sizeof(unsigned char *);
    511 		if (ctx->malloced > ctx->maxmalloced)
    512 			ctx->maxmalloced = ctx->malloced;
    513 		if (ctx->basic_table_size != 0) {
    514 			memmove(table, ctx->basic_table,
    515 				ctx->basic_table_size *
    516 				  sizeof(unsigned char *));
    517 			(ctx->memfree)(ctx->arg, ctx->basic_table);
    518 			ctx->malloced -= ctx->basic_table_size *
    519 					 sizeof(unsigned char *);
    520 		}
    521 		ctx->basic_table = table;
    522 		ctx->basic_table_size = table_size;
    523 	}
    524 
    525 	tmp = (ctx->memalloc)(ctx->arg, NUM_BASIC_BLOCKS * ctx->mem_target);
    526 	if (tmp == NULL) {
    527 		ctx->memalloc_failures++;
    528 		return (ISC_FALSE);
    529 	}
    530 	ctx->total += increment;
    531 	ctx->basic_table[ctx->basic_table_count] = tmp;
    532 	ctx->basic_table_count++;
    533 	ctx->malloced += NUM_BASIC_BLOCKS * ctx->mem_target;
    534 	if (ctx->malloced > ctx->maxmalloced)
    535 			ctx->maxmalloced = ctx->malloced;
    536 
    537 	curr = tmp;
    538 	next = curr + ctx->mem_target;
    539 	for (i = 0; i < (NUM_BASIC_BLOCKS - 1); i++) {
    540 		((element *)curr)->next = (element *)next;
    541 		curr = next;
    542 		next += ctx->mem_target;
    543 	}
    544 	/*
    545 	 * curr is now pointing at the last block in the
    546 	 * array.
    547 	 */
    548 	((element *)curr)->next = NULL;
    549 	first = tmp;
    550 	last = first + NUM_BASIC_BLOCKS * ctx->mem_target - 1;
    551 	if (first < ctx->lowest || ctx->lowest == NULL)
    552 		ctx->lowest = first;
    553 	if (last > ctx->highest)
    554 		ctx->highest = last;
    555 	ctx->basic_blocks = tmp;
    556 
    557 	return (ISC_TRUE);
    558 }
    559 
    560 static inline isc_boolean_t
    561 more_frags(isc__mem_t *ctx, size_t new_size) {
    562 	int i, frags;
    563 	size_t total_size;
    564 	void *tmp;
    565 	unsigned char *curr, *next;
    566 
    567 	/*!
    568 	 * Try to get more fragments by chopping up a basic block.
    569 	 */
    570 
    571 	if (ctx->basic_blocks == NULL) {
    572 		if (!more_basic_blocks(ctx)) {
    573 			/*
    574 			 * We can't get more memory from the OS, or we've
    575 			 * hit the quota for this context.
    576 			 */
    577 			/*
    578 			 * XXXRTH  "At quota" notification here.
    579 			 */
    580 			return (ISC_FALSE);
    581 		}
    582 	}
    583 
    584 	total_size = ctx->mem_target;
    585 	tmp = ctx->basic_blocks;
    586 	ctx->basic_blocks = ctx->basic_blocks->next;
    587 	frags = (int)(total_size / new_size);
    588 	ctx->stats[new_size].blocks++;
    589 	ctx->stats[new_size].freefrags += frags;
    590 	/*
    591 	 * Set up a linked-list of blocks of size
    592 	 * "new_size".
    593 	 */
    594 	curr = tmp;
    595 	next = curr + new_size;
    596 	total_size -= new_size;
    597 	for (i = 0; i < (frags - 1); i++) {
    598 		((element *)curr)->next = (element *)next;
    599 		curr = next;
    600 		next += new_size;
    601 		total_size -= new_size;
    602 	}
    603 	/*
    604 	 * Add the remaining fragment of the basic block to a free list.
    605 	 */
    606 	total_size = rmsize(total_size);
    607 	if (total_size > 0U) {
    608 		((element *)next)->next = ctx->freelists[total_size];
    609 		ctx->freelists[total_size] = (element *)next;
    610 		ctx->stats[total_size].freefrags++;
    611 	}
    612 	/*
    613 	 * curr is now pointing at the last block in the
    614 	 * array.
    615 	 */
    616 	((element *)curr)->next = NULL;
    617 	ctx->freelists[new_size] = tmp;
    618 
    619 	return (ISC_TRUE);
    620 }
    621 
    622 static inline void *
    623 mem_getunlocked(isc__mem_t *ctx, size_t size) {
    624 	size_t new_size = quantize(size);
    625 	void *ret;
    626 
    627 	if (new_size >= ctx->max_size) {
    628 		/*
    629 		 * memget() was called on something beyond our upper limit.
    630 		 */
    631 		if (ctx->quota != 0U && ctx->total + size > ctx->quota) {
    632 			ret = NULL;
    633 			goto done;
    634 		}
    635 		ret = (ctx->memalloc)(ctx->arg, size);
    636 		if (ret == NULL) {
    637 			ctx->memalloc_failures++;
    638 			goto done;
    639 		}
    640 		ctx->total += size;
    641 		ctx->inuse += size;
    642 		ctx->stats[ctx->max_size].gets++;
    643 		ctx->stats[ctx->max_size].totalgets++;
    644 		ctx->malloced += size;
    645 		if (ctx->malloced > ctx->maxmalloced)
    646 			ctx->maxmalloced = ctx->malloced;
    647 		/*
    648 		 * If we don't set new_size to size, then the
    649 		 * ISC_MEMFLAG_FILL code might write over bytes we don't
    650 		 * own.
    651 		 */
    652 		new_size = size;
    653 		goto done;
    654 	}
    655 	/*
    656 	 * If there are no blocks in the free list for this size, get a chunk
    657 	 * of memory and then break it up into "new_size"-sized blocks, adding
    658 	 * them to the free list.
    659 	 */
    660 	if (ctx->freelists[new_size] == NULL && !more_frags(ctx, new_size))
    661 		return (NULL);
    662 
    663 	/*
    664 	 * The free list uses the "rounded-up" size "new_size".
    665 	 */
    666 
    667 	ret = ctx->freelists[new_size];
    668 	ctx->freelists[new_size] = ctx->freelists[new_size]->next;
    669 
    670 
    671 	/*
    672 	 * The stats[] uses the _actual_ "size" requested by the
    673 	 * caller, with the caveat (in the code above) that "size" >= the
    674 	 * max. size (max_size) ends up getting recorded as a call to
    675 	 * max_size.
    676 	 */
    677 	ctx->stats[size].gets++;
    678 	ctx->stats[size].totalgets++;
    679 	ctx->stats[new_size].freefrags--;
    680 	ctx->inuse += new_size;
    681 
    682  done:
    683 	if (ISC_UNLIKELY((ctx->flags & ISC_MEMFLAG_FILL) != 0) &&
    684 	    ISC_LIKELY(ret != NULL))
    685 		memset(ret, 0xbe, new_size); /* Mnemonic for "beef". */
    686 
    687 	return (ret);
    688 }
    689 
    690 #if ISC_MEM_CHECKOVERRUN
    691 static inline void
    692 check_overrun(void *mem, size_t size, size_t new_size) {
    693 	unsigned char *cp;
    694 
    695 	cp = (unsigned char *)mem;
    696 	cp += size;
    697 	while (size < new_size) {
    698 		INSIST(*cp == 0xbe);
    699 		cp++;
    700 		size++;
    701 	}
    702 }
    703 #endif
    704 
    705 /* coverity[+free : arg-1] */
    706 static inline void
    707 mem_putunlocked(isc__mem_t *ctx, void *mem, size_t size) {
    708 	size_t new_size = quantize(size);
    709 
    710 	if (new_size >= ctx->max_size) {
    711 		/*
    712 		 * memput() called on something beyond our upper limit.
    713 		 */
    714 		if (ISC_UNLIKELY((ctx->flags & ISC_MEMFLAG_FILL) != 0))
    715 			memset(mem, 0xde, size); /* Mnemonic for "dead". */
    716 
    717 		(ctx->memfree)(ctx->arg, mem);
    718 		INSIST(ctx->stats[ctx->max_size].gets != 0U);
    719 		ctx->stats[ctx->max_size].gets--;
    720 		INSIST(size <= ctx->inuse);
    721 		ctx->inuse -= size;
    722 		ctx->malloced -= size;
    723 		return;
    724 	}
    725 
    726 	if (ISC_UNLIKELY((ctx->flags & ISC_MEMFLAG_FILL) != 0)) {
    727 #if ISC_MEM_CHECKOVERRUN
    728 		check_overrun(mem, size, new_size);
    729 #endif
    730 		memset(mem, 0xde, new_size); /* Mnemonic for "dead". */
    731 	}
    732 
    733 	/*
    734 	 * The free list uses the "rounded-up" size "new_size".
    735 	 */
    736 	((element *)mem)->next = ctx->freelists[new_size];
    737 	ctx->freelists[new_size] = (element *)mem;
    738 
    739 	/*
    740 	 * The stats[] uses the _actual_ "size" requested by the
    741 	 * caller, with the caveat (in the code above) that "size" >= the
    742 	 * max. size (max_size) ends up getting recorded as a call to
    743 	 * max_size.
    744 	 */
    745 	INSIST(ctx->stats[size].gets != 0U);
    746 	ctx->stats[size].gets--;
    747 	ctx->stats[new_size].freefrags++;
    748 	ctx->inuse -= new_size;
    749 }
    750 
    751 /*!
    752  * Perform a malloc, doing memory filling and overrun detection as necessary.
    753  */
    754 static inline void *
    755 mem_get(isc__mem_t *ctx, size_t size) {
    756 	char *ret;
    757 
    758 #if ISC_MEM_CHECKOVERRUN
    759 	size += 1;
    760 #endif
    761 	ret = (ctx->memalloc)(ctx->arg, size);
    762 	if (ret == NULL)
    763 		ctx->memalloc_failures++;
    764 
    765 	if (ISC_UNLIKELY((ctx->flags & ISC_MEMFLAG_FILL) != 0)) {
    766 		if (ISC_LIKELY(ret != NULL))
    767 			memset(ret, 0xbe, size); /* Mnemonic for "beef". */
    768 	}
    769 #if ISC_MEM_CHECKOVERRUN
    770 	else {
    771 		if (ISC_LIKELY(ret != NULL))
    772 			ret[size-1] = 0xbe;
    773 	}
    774 #endif
    775 
    776 	return (ret);
    777 }
    778 
    779 /*!
    780  * Perform a free, doing memory filling and overrun detection as necessary.
    781  */
    782 /* coverity[+free : arg-1] */
    783 static inline void
    784 mem_put(isc__mem_t *ctx, void *mem, size_t size) {
    785 #if ISC_MEM_CHECKOVERRUN
    786 	INSIST(((unsigned char *)mem)[size] == 0xbe);
    787 	size += 1;
    788 #endif
    789 	if (ISC_UNLIKELY((ctx->flags & ISC_MEMFLAG_FILL) != 0))
    790 		memset(mem, 0xde, size); /* Mnemonic for "dead". */
    791 	(ctx->memfree)(ctx->arg, mem);
    792 }
    793 
    794 /*!
    795  * Update internal counters after a memory get.
    796  */
    797 static inline void
    798 mem_getstats(isc__mem_t *ctx, size_t size) {
    799 	ctx->total += size;
    800 	ctx->inuse += size;
    801 
    802 	if (size > ctx->max_size) {
    803 		ctx->stats[ctx->max_size].gets++;
    804 		ctx->stats[ctx->max_size].totalgets++;
    805 	} else {
    806 		ctx->stats[size].gets++;
    807 		ctx->stats[size].totalgets++;
    808 	}
    809 
    810 #if ISC_MEM_CHECKOVERRUN
    811 	size += 1;
    812 #endif
    813 	ctx->malloced += size;
    814 	if (ctx->malloced > ctx->maxmalloced)
    815 		ctx->maxmalloced = ctx->malloced;
    816 }
    817 
    818 /*!
    819  * Update internal counters after a memory put.
    820  */
    821 static inline void
    822 mem_putstats(isc__mem_t *ctx, void *ptr, size_t size) {
    823 	UNUSED(ptr);
    824 
    825 	INSIST(ctx->inuse >= size);
    826 	ctx->inuse -= size;
    827 
    828 	if (size > ctx->max_size) {
    829 		INSIST(ctx->stats[ctx->max_size].gets > 0U);
    830 		ctx->stats[ctx->max_size].gets--;
    831 	} else {
    832 		INSIST(ctx->stats[size].gets > 0U);
    833 		ctx->stats[size].gets--;
    834 	}
    835 #if ISC_MEM_CHECKOVERRUN
    836 	size += 1;
    837 #endif
    838 	ctx->malloced -= size;
    839 }
    840 
    841 /*
    842  * Private.
    843  */
    844 
    845 static void *
    846 default_memalloc(void *arg, size_t size) {
    847 	UNUSED(arg);
    848 	if (size == 0U)
    849 		size = 1;
    850 	return (malloc(size));
    851 }
    852 
    853 static void
    854 default_memfree(void *arg, void *ptr) {
    855 	UNUSED(arg);
    856 	free(ptr);
    857 }
    858 
    859 static void
    860 initialize_action(void) {
    861 	RUNTIME_CHECK(isc_mutex_init(&createlock) == ISC_R_SUCCESS);
    862 	RUNTIME_CHECK(isc_mutex_init(&contextslock) == ISC_R_SUCCESS);
    863 	ISC_LIST_INIT(contexts);
    864 	totallost = 0;
    865 }
    866 
    867 /*
    868  * Public.
    869  */
    870 
    871 isc_result_t
    872 isc_mem_createx(size_t init_max_size, size_t target_size,
    873 		 isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
    874 		 isc_mem_t **ctxp)
    875 {
    876 	return (isc_mem_createx2(init_max_size, target_size, memalloc, memfree,
    877 				 arg, ctxp, isc_mem_defaultflags));
    878 
    879 }
    880 
    881 isc_result_t
    882 isc_mem_createx2(size_t init_max_size, size_t target_size,
    883 		  isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
    884 		  isc_mem_t **ctxp, unsigned int flags)
    885 {
    886 	isc__mem_t *ctx;
    887 	isc_result_t result;
    888 
    889 	REQUIRE(ctxp != NULL && *ctxp == NULL);
    890 	REQUIRE(memalloc != NULL);
    891 	REQUIRE(memfree != NULL);
    892 
    893 	INSIST((ALIGNMENT_SIZE & (ALIGNMENT_SIZE - 1)) == 0);
    894 
    895 	RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
    896 
    897 	ctx = (memalloc)(arg, sizeof(*ctx));
    898 	if (ctx == NULL)
    899 		return (ISC_R_NOMEMORY);
    900 
    901 	if ((flags & ISC_MEMFLAG_NOLOCK) == 0) {
    902 		result = isc_mutex_init(&ctx->lock);
    903 		if (result != ISC_R_SUCCESS) {
    904 			(memfree)(arg, ctx);
    905 			return (result);
    906 		}
    907 	}
    908 
    909 	if (init_max_size == 0U)
    910 		ctx->max_size = DEF_MAX_SIZE;
    911 	else
    912 		ctx->max_size = init_max_size;
    913 	ctx->flags = flags;
    914 	ctx->references = 1;
    915 	memset(ctx->name, 0, sizeof(ctx->name));
    916 	ctx->tag = NULL;
    917 	ctx->quota = 0;
    918 	ctx->total = 0;
    919 	ctx->inuse = 0;
    920 	ctx->maxinuse = 0;
    921 	ctx->malloced = sizeof(*ctx);
    922 	ctx->maxmalloced = sizeof(*ctx);
    923 	ctx->hi_water = 0;
    924 	ctx->lo_water = 0;
    925 	ctx->hi_called = ISC_FALSE;
    926 	ctx->is_overmem = ISC_FALSE;
    927 	ctx->water = NULL;
    928 	ctx->water_arg = NULL;
    929 	ctx->common.impmagic = MEM_MAGIC;
    930 	ctx->common.magic = ISCAPI_MCTX_MAGIC;
    931 	ctx->common.methods = (isc_memmethods_t *)&memmethods;
    932 	isc_ondestroy_init(&ctx->ondestroy);
    933 	ctx->memalloc = memalloc;
    934 	ctx->memfree = memfree;
    935 	ctx->arg = arg;
    936 	ctx->stats = NULL;
    937 	ctx->checkfree = ISC_TRUE;
    938 #if ISC_MEM_TRACKLINES
    939 	ctx->debuglist = NULL;
    940 	ctx->debuglistcnt = 0;
    941 #endif
    942 	ISC_LIST_INIT(ctx->pools);
    943 	ctx->poolcnt = 0;
    944 	ctx->freelists = NULL;
    945 	ctx->basic_blocks = NULL;
    946 	ctx->basic_table = NULL;
    947 	ctx->basic_table_count = 0;
    948 	ctx->basic_table_size = 0;
    949 	ctx->lowest = NULL;
    950 	ctx->highest = NULL;
    951 
    952 	ctx->stats = (memalloc)(arg,
    953 				(ctx->max_size+1) * sizeof(struct stats));
    954 	if (ctx->stats == NULL) {
    955 		result = ISC_R_NOMEMORY;
    956 		goto error;
    957 	}
    958 	memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof(struct stats));
    959 	ctx->malloced += (ctx->max_size+1) * sizeof(struct stats);
    960 	ctx->maxmalloced += (ctx->max_size+1) * sizeof(struct stats);
    961 
    962 	if ((flags & ISC_MEMFLAG_INTERNAL) != 0) {
    963 		if (target_size == 0U)
    964 			ctx->mem_target = DEF_MEM_TARGET;
    965 		else
    966 			ctx->mem_target = target_size;
    967 		ctx->freelists = (memalloc)(arg, ctx->max_size *
    968 						 sizeof(element *));
    969 		if (ctx->freelists == NULL) {
    970 			result = ISC_R_NOMEMORY;
    971 			goto error;
    972 		}
    973 		memset(ctx->freelists, 0,
    974 		       ctx->max_size * sizeof(element *));
    975 		ctx->malloced += ctx->max_size * sizeof(element *);
    976 		ctx->maxmalloced += ctx->max_size * sizeof(element *);
    977 	}
    978 
    979 #if ISC_MEM_TRACKLINES
    980 	if (ISC_UNLIKELY((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0)) {
    981 		unsigned int i;
    982 
    983 		ctx->debuglist = (memalloc)(arg, (DEBUG_TABLE_COUNT *
    984 						  sizeof(debuglist_t)));
    985 		if (ctx->debuglist == NULL) {
    986 			result = ISC_R_NOMEMORY;
    987 			goto error;
    988 		}
    989 		for (i = 0; i < DEBUG_TABLE_COUNT; i++)
    990 			ISC_LIST_INIT(ctx->debuglist[i]);
    991 		ctx->malloced += DEBUG_TABLE_COUNT * sizeof(debuglist_t);
    992 		ctx->maxmalloced += DEBUG_TABLE_COUNT * sizeof(debuglist_t);
    993 	}
    994 #endif
    995 
    996 	ctx->memalloc_failures = 0;
    997 
    998 	LOCK(&contextslock);
    999 	ISC_LIST_INITANDAPPEND(contexts, ctx, link);
   1000 	UNLOCK(&contextslock);
   1001 
   1002 	*ctxp = (isc_mem_t *)ctx;
   1003 	return (ISC_R_SUCCESS);
   1004 
   1005   error:
   1006 	if (ctx != NULL) {
   1007 		if (ctx->stats != NULL)
   1008 			(memfree)(arg, ctx->stats);
   1009 		if (ctx->freelists != NULL)
   1010 			(memfree)(arg, ctx->freelists);
   1011 #if ISC_MEM_TRACKLINES
   1012 		if (ctx->debuglist != NULL)
   1013 			(ctx->memfree)(ctx->arg, ctx->debuglist);
   1014 #endif /* ISC_MEM_TRACKLINES */
   1015 		if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)
   1016 			DESTROYLOCK(&ctx->lock);
   1017 		(memfree)(arg, ctx);
   1018 	}
   1019 
   1020 	return (result);
   1021 }
   1022 
   1023 static void
   1024 destroy(isc__mem_t *ctx) {
   1025 	unsigned int i;
   1026 	isc_ondestroy_t ondest;
   1027 
   1028 	LOCK(&contextslock);
   1029 	ISC_LIST_UNLINK(contexts, ctx, link);
   1030 	totallost += ctx->inuse;
   1031 	UNLOCK(&contextslock);
   1032 
   1033 	ctx->common.impmagic = 0;
   1034 	ctx->common.magic = 0;
   1035 
   1036 	INSIST(ISC_LIST_EMPTY(ctx->pools));
   1037 
   1038 #if ISC_MEM_TRACKLINES
   1039 	if (ISC_UNLIKELY(ctx->debuglist != NULL)) {
   1040 		debuglink_t *dl;
   1041 		for (i = 0; i < DEBUG_TABLE_COUNT; i++)
   1042 			for (dl = ISC_LIST_HEAD(ctx->debuglist[i]);
   1043 			     dl != NULL;
   1044 			     dl = ISC_LIST_HEAD(ctx->debuglist[i])) {
   1045 				if (ctx->checkfree && dl->ptr != NULL)
   1046 					print_active(ctx, stderr);
   1047 				INSIST (!ctx->checkfree || dl->ptr == NULL);
   1048 
   1049 				ISC_LIST_UNLINK(ctx->debuglist[i],
   1050 						dl, link);
   1051 				free(dl);
   1052 				ctx->malloced -= sizeof(*dl);
   1053 			}
   1054 
   1055 		(ctx->memfree)(ctx->arg, ctx->debuglist);
   1056 		ctx->malloced -= DEBUG_TABLE_COUNT * sizeof(debuglist_t);
   1057 	}
   1058 #endif
   1059 	INSIST(ctx->references == 0);
   1060 
   1061 	if (ctx->checkfree) {
   1062 		for (i = 0; i <= ctx->max_size; i++) {
   1063 			if (ctx->stats[i].gets != 0U) {
   1064 				fprintf(stderr,
   1065 					"Failing assertion due to probable "
   1066 					"leaked memory in context %p (\"%s\") "
   1067 					"(stats[%u].gets == %lu).\n",
   1068 					ctx, ctx->name, i, ctx->stats[i].gets);
   1069 #if ISC_MEM_TRACKLINES
   1070 				print_active(ctx, stderr);
   1071 #endif
   1072 				INSIST(ctx->stats[i].gets == 0U);
   1073 			}
   1074 		}
   1075 	}
   1076 
   1077 	(ctx->memfree)(ctx->arg, ctx->stats);
   1078 	ctx->malloced -= (ctx->max_size+1) * sizeof(struct stats);
   1079 
   1080 	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
   1081 		for (i = 0; i < ctx->basic_table_count; i++) {
   1082 			(ctx->memfree)(ctx->arg, ctx->basic_table[i]);
   1083 			ctx->malloced -= NUM_BASIC_BLOCKS * ctx->mem_target;
   1084 		}
   1085 		(ctx->memfree)(ctx->arg, ctx->freelists);
   1086 		ctx->malloced -= ctx->max_size * sizeof(element *);
   1087 		if (ctx->basic_table != NULL) {
   1088 			(ctx->memfree)(ctx->arg, ctx->basic_table);
   1089 			ctx->malloced -= ctx->basic_table_size *
   1090 					 sizeof(unsigned char *);
   1091 		}
   1092 	}
   1093 
   1094 	ondest = ctx->ondestroy;
   1095 
   1096 	if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)
   1097 		DESTROYLOCK(&ctx->lock);
   1098 	ctx->malloced -= sizeof(*ctx);
   1099 	if (ctx->checkfree)
   1100 		INSIST(ctx->malloced == 0);
   1101 	(ctx->memfree)(ctx->arg, ctx);
   1102 
   1103 	isc_ondestroy_notify(&ondest, ctx);
   1104 }
   1105 
   1106 void
   1107 isc__mem_attach(isc_mem_t *source0, isc_mem_t **targetp) {
   1108 	isc__mem_t *source = (isc__mem_t *)source0;
   1109 
   1110 	REQUIRE(VALID_CONTEXT(source));
   1111 	REQUIRE(targetp != NULL && *targetp == NULL);
   1112 
   1113 	MCTXLOCK(source, &source->lock);
   1114 	source->references++;
   1115 	MCTXUNLOCK(source, &source->lock);
   1116 
   1117 	*targetp = (isc_mem_t *)source;
   1118 }
   1119 
   1120 void
   1121 isc__mem_detach(isc_mem_t **ctxp) {
   1122 	isc__mem_t *ctx;
   1123 	isc_boolean_t want_destroy = ISC_FALSE;
   1124 
   1125 	REQUIRE(ctxp != NULL);
   1126 	ctx = (isc__mem_t *)*ctxp;
   1127 	REQUIRE(VALID_CONTEXT(ctx));
   1128 
   1129 	MCTXLOCK(ctx, &ctx->lock);
   1130 	INSIST(ctx->references > 0);
   1131 	ctx->references--;
   1132 	if (ctx->references == 0)
   1133 		want_destroy = ISC_TRUE;
   1134 	MCTXUNLOCK(ctx, &ctx->lock);
   1135 
   1136 	if (want_destroy)
   1137 		destroy(ctx);
   1138 
   1139 	*ctxp = NULL;
   1140 }
   1141 
   1142 /*
   1143  * isc_mem_putanddetach() is the equivalent of:
   1144  *
   1145  * mctx = NULL;
   1146  * isc_mem_attach(ptr->mctx, &mctx);
   1147  * isc_mem_detach(&ptr->mctx);
   1148  * isc_mem_put(mctx, ptr, sizeof(*ptr);
   1149  * isc_mem_detach(&mctx);
   1150  */
   1151 
   1152 void
   1153 isc___mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
   1154 	isc__mem_t *ctx;
   1155 	isc_boolean_t want_destroy = ISC_FALSE;
   1156 	size_info *si;
   1157 	size_t oldsize;
   1158 
   1159 	REQUIRE(ctxp != NULL);
   1160 	ctx = (isc__mem_t *)*ctxp;
   1161 	REQUIRE(VALID_CONTEXT(ctx));
   1162 	REQUIRE(ptr != NULL);
   1163 
   1164 	/*
   1165 	 * Must be before mem_putunlocked() as ctxp is usually within
   1166 	 * [ptr..ptr+size).
   1167 	 */
   1168 	*ctxp = NULL;
   1169 
   1170 	if (ISC_UNLIKELY((isc_mem_debugging &
   1171 			  (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0))
   1172 	{
   1173 		if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) {
   1174 			si = &(((size_info *)ptr)[-1]);
   1175 			oldsize = si->u.size - ALIGNMENT_SIZE;
   1176 			if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
   1177 				oldsize -= ALIGNMENT_SIZE;
   1178 			INSIST(oldsize == size);
   1179 		}
   1180 		isc__mem_free((isc_mem_t *)ctx, ptr FLARG_PASS);
   1181 
   1182 		MCTXLOCK(ctx, &ctx->lock);
   1183 		ctx->references--;
   1184 		if (ctx->references == 0)
   1185 			want_destroy = ISC_TRUE;
   1186 		MCTXUNLOCK(ctx, &ctx->lock);
   1187 		if (want_destroy)
   1188 			destroy(ctx);
   1189 
   1190 		return;
   1191 	}
   1192 
   1193 	MCTXLOCK(ctx, &ctx->lock);
   1194 
   1195 	DELETE_TRACE(ctx, ptr, size, file, line);
   1196 
   1197 	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
   1198 		mem_putunlocked(ctx, ptr, size);
   1199 	} else {
   1200 		mem_putstats(ctx, ptr, size);
   1201 		mem_put(ctx, ptr, size);
   1202 	}
   1203 
   1204 	INSIST(ctx->references > 0);
   1205 	ctx->references--;
   1206 	if (ctx->references == 0)
   1207 		want_destroy = ISC_TRUE;
   1208 
   1209 	MCTXUNLOCK(ctx, &ctx->lock);
   1210 
   1211 	if (want_destroy)
   1212 		destroy(ctx);
   1213 }
   1214 
   1215 void
   1216 isc__mem_destroy(isc_mem_t **ctxp) {
   1217 	isc__mem_t *ctx;
   1218 
   1219 	/*
   1220 	 * This routine provides legacy support for callers who use mctxs
   1221 	 * without attaching/detaching.
   1222 	 */
   1223 
   1224 	REQUIRE(ctxp != NULL);
   1225 	ctx = (isc__mem_t *)*ctxp;
   1226 	REQUIRE(VALID_CONTEXT(ctx));
   1227 
   1228 	MCTXLOCK(ctx, &ctx->lock);
   1229 #if ISC_MEM_TRACKLINES
   1230 	if (ctx->references != 1)
   1231 		print_active(ctx, stderr);
   1232 #endif
   1233 	REQUIRE(ctx->references == 1);
   1234 	ctx->references--;
   1235 	MCTXUNLOCK(ctx, &ctx->lock);
   1236 
   1237 	destroy(ctx);
   1238 
   1239 	*ctxp = NULL;
   1240 }
   1241 
   1242 isc_result_t
   1243 isc_mem_ondestroy(isc_mem_t *ctx0, isc_task_t *task, isc_event_t **event) {
   1244 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1245 	isc_result_t res;
   1246 
   1247 	MCTXLOCK(ctx, &ctx->lock);
   1248 	res = isc_ondestroy_register(&ctx->ondestroy, task, event);
   1249 	MCTXUNLOCK(ctx, &ctx->lock);
   1250 
   1251 	return (res);
   1252 }
   1253 
   1254 void *
   1255 isc___mem_get(isc_mem_t *ctx0, size_t size FLARG) {
   1256 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1257 	void *ptr;
   1258 	isc_boolean_t call_water = ISC_FALSE;
   1259 
   1260 	REQUIRE(VALID_CONTEXT(ctx));
   1261 
   1262 	if (ISC_UNLIKELY((isc_mem_debugging &
   1263 			  (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0))
   1264 		return (isc__mem_allocate(ctx0, size FLARG_PASS));
   1265 
   1266 	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
   1267 		MCTXLOCK(ctx, &ctx->lock);
   1268 		ptr = mem_getunlocked(ctx, size);
   1269 	} else {
   1270 		ptr = mem_get(ctx, size);
   1271 		MCTXLOCK(ctx, &ctx->lock);
   1272 		if (ptr != NULL)
   1273 			mem_getstats(ctx, size);
   1274 	}
   1275 
   1276 	ADD_TRACE(ctx, ptr, size, file, line);
   1277 
   1278 	if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water) {
   1279 		ctx->is_overmem = ISC_TRUE;
   1280 		if (!ctx->hi_called)
   1281 			call_water = ISC_TRUE;
   1282 	}
   1283 	if (ctx->inuse > ctx->maxinuse) {
   1284 		ctx->maxinuse = ctx->inuse;
   1285 		if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&
   1286 		    (isc_mem_debugging & ISC_MEM_DEBUGUSAGE) != 0)
   1287 			fprintf(stderr, "maxinuse = %lu\n",
   1288 				(unsigned long)ctx->inuse);
   1289 	}
   1290 	MCTXUNLOCK(ctx, &ctx->lock);
   1291 
   1292 	if (call_water && (ctx->water != NULL))
   1293 		(ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
   1294 
   1295 	return (ptr);
   1296 }
   1297 
   1298 void
   1299 isc___mem_put(isc_mem_t *ctx0, void *ptr, size_t size FLARG) {
   1300 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1301 	isc_boolean_t call_water = ISC_FALSE;
   1302 	size_info *si;
   1303 	size_t oldsize;
   1304 
   1305 	REQUIRE(VALID_CONTEXT(ctx));
   1306 	REQUIRE(ptr != NULL);
   1307 
   1308 	if (ISC_UNLIKELY((isc_mem_debugging &
   1309 			  (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0))
   1310 	{
   1311 		if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) {
   1312 			si = &(((size_info *)ptr)[-1]);
   1313 			oldsize = si->u.size - ALIGNMENT_SIZE;
   1314 			if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)
   1315 				oldsize -= ALIGNMENT_SIZE;
   1316 			INSIST(oldsize == size);
   1317 		}
   1318 		isc__mem_free((isc_mem_t *)ctx, ptr FLARG_PASS);
   1319 		return;
   1320 	}
   1321 
   1322 	MCTXLOCK(ctx, &ctx->lock);
   1323 
   1324 	DELETE_TRACE(ctx, ptr, size, file, line);
   1325 
   1326 	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
   1327 		mem_putunlocked(ctx, ptr, size);
   1328 	} else {
   1329 		mem_putstats(ctx, ptr, size);
   1330 		mem_put(ctx, ptr, size);
   1331 	}
   1332 
   1333 	/*
   1334 	 * The check against ctx->lo_water == 0 is for the condition
   1335 	 * when the context was pushed over hi_water but then had
   1336 	 * isc_mem_setwater() called with 0 for hi_water and lo_water.
   1337 	 */
   1338 	if ((ctx->inuse < ctx->lo_water) || (ctx->lo_water == 0U)) {
   1339 		ctx->is_overmem = ISC_FALSE;
   1340 		if (ctx->hi_called)
   1341 			call_water = ISC_TRUE;
   1342 	}
   1343 
   1344 	MCTXUNLOCK(ctx, &ctx->lock);
   1345 
   1346 	if (call_water && (ctx->water != NULL))
   1347 		(ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
   1348 }
   1349 
   1350 void
   1351 isc__mem_waterack(isc_mem_t *ctx0, int flag) {
   1352 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1353 
   1354 	REQUIRE(VALID_CONTEXT(ctx));
   1355 
   1356 	MCTXLOCK(ctx, &ctx->lock);
   1357 	if (flag == ISC_MEM_LOWATER)
   1358 		ctx->hi_called = ISC_FALSE;
   1359 	else if (flag == ISC_MEM_HIWATER)
   1360 		ctx->hi_called = ISC_TRUE;
   1361 	MCTXUNLOCK(ctx, &ctx->lock);
   1362 }
   1363 
   1364 #if ISC_MEM_TRACKLINES
   1365 static void
   1366 print_active(isc__mem_t *mctx, FILE *out) {
   1367 	if (mctx->debuglist != NULL) {
   1368 		debuglink_t *dl;
   1369 		unsigned int i;
   1370 		const char *format;
   1371 		isc_boolean_t found;
   1372 
   1373 		fprintf(out, "%s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
   1374 					    ISC_MSG_DUMPALLOC,
   1375 					    "Dump of all outstanding "
   1376 					    "memory allocations:\n"));
   1377 		found = ISC_FALSE;
   1378 		format = isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
   1379 					ISC_MSG_PTRFILELINE,
   1380 					"\tptr %p size %u file %s line %u\n");
   1381 		for (i = 0; i < DEBUG_TABLE_COUNT; i++) {
   1382 			dl = ISC_LIST_HEAD(mctx->debuglist[i]);
   1383 
   1384 			if (dl != NULL)
   1385 				found = ISC_TRUE;
   1386 
   1387 			while (dl != NULL) {
   1388 				if (dl->ptr != NULL)
   1389 					fprintf(out, format,
   1390 						dl->ptr, dl->size,
   1391 						dl->file, dl->line);
   1392 				dl = ISC_LIST_NEXT(dl, link);
   1393 			}
   1394 		}
   1395 
   1396 		if (!found)
   1397 			fputs(isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
   1398 					     ISC_MSG_NONE, "\tNone.\n"), out);
   1399 	}
   1400 }
   1401 #endif
   1402 
   1403 /*
   1404  * Print the stats[] on the stream "out" with suitable formatting.
   1405  */
   1406 void
   1407 isc_mem_stats(isc_mem_t *ctx0, FILE *out) {
   1408 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1409 	size_t i;
   1410 	const struct stats *s;
   1411 	const isc__mempool_t *pool;
   1412 
   1413 	REQUIRE(VALID_CONTEXT(ctx));
   1414 	MCTXLOCK(ctx, &ctx->lock);
   1415 
   1416 	for (i = 0; i <= ctx->max_size; i++) {
   1417 		s = &ctx->stats[i];
   1418 
   1419 		if (s->totalgets == 0U && s->gets == 0U)
   1420 			continue;
   1421 		fprintf(out, "%s%5lu: %11lu gets, %11lu rem",
   1422 			(i == ctx->max_size) ? ">=" : "  ",
   1423 			(unsigned long) i, s->totalgets, s->gets);
   1424 		if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0 &&
   1425 		    (s->blocks != 0U || s->freefrags != 0U))
   1426 			fprintf(out, " (%lu bl, %lu ff)",
   1427 				s->blocks, s->freefrags);
   1428 		fputc('\n', out);
   1429 	}
   1430 
   1431 	/*
   1432 	 * Note that since a pool can be locked now, these stats might be
   1433 	 * somewhat off if the pool is in active use at the time the stats
   1434 	 * are dumped.  The link fields are protected by the isc_mem_t's
   1435 	 * lock, however, so walking this list and extracting integers from
   1436 	 * stats fields is always safe.
   1437 	 */
   1438 	pool = ISC_LIST_HEAD(ctx->pools);
   1439 	if (pool != NULL) {
   1440 		fprintf(out, "%s", isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
   1441 					    ISC_MSG_POOLSTATS,
   1442 					    "[Pool statistics]\n"));
   1443 		fprintf(out, "%15s %10s %10s %10s %10s %10s %10s %10s %1s\n",
   1444 			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
   1445 				       ISC_MSG_POOLNAME, "name"),
   1446 			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
   1447 				       ISC_MSG_POOLSIZE, "size"),
   1448 			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
   1449 				       ISC_MSG_POOLMAXALLOC, "maxalloc"),
   1450 			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
   1451 				       ISC_MSG_POOLALLOCATED, "allocated"),
   1452 			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
   1453 				       ISC_MSG_POOLFREECOUNT, "freecount"),
   1454 			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
   1455 				       ISC_MSG_POOLFREEMAX, "freemax"),
   1456 			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
   1457 				       ISC_MSG_POOLFILLCOUNT, "fillcount"),
   1458 			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
   1459 				       ISC_MSG_POOLGETS, "gets"),
   1460 			"L");
   1461 	}
   1462 	while (pool != NULL) {
   1463 		fprintf(out, "%15s %10lu %10u %10u %10u %10u %10u %10u %s\n",
   1464 #if ISC_MEMPOOL_NAMES
   1465 			pool->name,
   1466 #else
   1467 			"(not tracked)",
   1468 #endif
   1469 			(unsigned long) pool->size, pool->maxalloc,
   1470 			pool->allocated, pool->freecount, pool->freemax,
   1471 			pool->fillcount, pool->gets,
   1472 			(pool->lock == NULL ? "N" : "Y"));
   1473 		pool = ISC_LIST_NEXT(pool, link);
   1474 	}
   1475 
   1476 #if ISC_MEM_TRACKLINES
   1477 	print_active(ctx, out);
   1478 #endif
   1479 
   1480 	MCTXUNLOCK(ctx, &ctx->lock);
   1481 }
   1482 
   1483 /*
   1484  * Replacements for malloc() and free() -- they implicitly remember the
   1485  * size of the object allocated (with some additional overhead).
   1486  */
   1487 
   1488 static void *
   1489 mem_allocateunlocked(isc_mem_t *ctx0, size_t size) {
   1490 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1491 	size_info *si;
   1492 
   1493 	size += ALIGNMENT_SIZE;
   1494 	if (ISC_UNLIKELY((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0))
   1495 		size += ALIGNMENT_SIZE;
   1496 
   1497 	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0)
   1498 		si = mem_getunlocked(ctx, size);
   1499 	else
   1500 		si = mem_get(ctx, size);
   1501 
   1502 	if (si == NULL)
   1503 		return (NULL);
   1504 	if (ISC_UNLIKELY((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)) {
   1505 		si->u.ctx = ctx;
   1506 		si++;
   1507 	}
   1508 	si->u.size = size;
   1509 	return (&si[1]);
   1510 }
   1511 
   1512 void *
   1513 isc___mem_allocate(isc_mem_t *ctx0, size_t size FLARG) {
   1514 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1515 	size_info *si;
   1516 	isc_boolean_t call_water = ISC_FALSE;
   1517 
   1518 	REQUIRE(VALID_CONTEXT(ctx));
   1519 
   1520 	MCTXLOCK(ctx, &ctx->lock);
   1521 	si = mem_allocateunlocked((isc_mem_t *)ctx, size);
   1522 	if (((ctx->flags & ISC_MEMFLAG_INTERNAL) == 0) && (si != NULL))
   1523 		mem_getstats(ctx, si[-1].u.size);
   1524 
   1525 	ADD_TRACE(ctx, si, si[-1].u.size, file, line);
   1526 	if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&
   1527 	    !ctx->is_overmem) {
   1528 		ctx->is_overmem = ISC_TRUE;
   1529 	}
   1530 
   1531 	if (ctx->hi_water != 0U && !ctx->hi_called &&
   1532 	    ctx->inuse > ctx->hi_water) {
   1533 		ctx->hi_called = ISC_TRUE;
   1534 		call_water = ISC_TRUE;
   1535 	}
   1536 	if (ctx->inuse > ctx->maxinuse) {
   1537 		ctx->maxinuse = ctx->inuse;
   1538 		if (ISC_UNLIKELY(ctx->hi_water != 0U &&
   1539 				 ctx->inuse > ctx->hi_water &&
   1540 				 (isc_mem_debugging & ISC_MEM_DEBUGUSAGE) != 0))
   1541 			fprintf(stderr, "maxinuse = %lu\n",
   1542 				(unsigned long)ctx->inuse);
   1543 	}
   1544 	MCTXUNLOCK(ctx, &ctx->lock);
   1545 
   1546 	if (call_water)
   1547 		(ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
   1548 
   1549 	return (si);
   1550 }
   1551 
   1552 void *
   1553 isc___mem_reallocate(isc_mem_t *ctx0, void *ptr, size_t size FLARG) {
   1554 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1555 	void *new_ptr = NULL;
   1556 	size_t oldsize, copysize;
   1557 
   1558 	REQUIRE(VALID_CONTEXT(ctx));
   1559 
   1560 	/*
   1561 	 * This function emulates the realloc(3) standard library function:
   1562 	 * - if size > 0, allocate new memory; and if ptr is non NULL, copy
   1563 	 *   as much of the old contents to the new buffer and free the old one.
   1564 	 *   Note that when allocation fails the original pointer is intact;
   1565 	 *   the caller must free it.
   1566 	 * - if size is 0 and ptr is non NULL, simply free the given ptr.
   1567 	 * - this function returns:
   1568 	 *     pointer to the newly allocated memory, or
   1569 	 *     NULL if allocation fails or doesn't happen.
   1570 	 */
   1571 	if (size > 0U) {
   1572 		new_ptr = isc__mem_allocate(ctx0, size FLARG_PASS);
   1573 		if (new_ptr != NULL && ptr != NULL) {
   1574 			oldsize = (((size_info *)ptr)[-1]).u.size;
   1575 			INSIST(oldsize >= ALIGNMENT_SIZE);
   1576 			oldsize -= ALIGNMENT_SIZE;
   1577 			if (ISC_UNLIKELY((isc_mem_debugging &
   1578 					  ISC_MEM_DEBUGCTX) != 0))
   1579 			{
   1580 				INSIST(oldsize >= ALIGNMENT_SIZE);
   1581 				oldsize -= ALIGNMENT_SIZE;
   1582 			}
   1583 			copysize = (oldsize > size) ? size : oldsize;
   1584 			memmove(new_ptr, ptr, copysize);
   1585 			isc__mem_free(ctx0, ptr FLARG_PASS);
   1586 		}
   1587 	} else if (ptr != NULL)
   1588 		isc__mem_free(ctx0, ptr FLARG_PASS);
   1589 
   1590 	return (new_ptr);
   1591 }
   1592 
   1593 void
   1594 isc___mem_free(isc_mem_t *ctx0, void *ptr FLARG) {
   1595 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1596 	size_info *si;
   1597 	size_t size;
   1598 	isc_boolean_t call_water= ISC_FALSE;
   1599 
   1600 	REQUIRE(VALID_CONTEXT(ctx));
   1601 	REQUIRE(ptr != NULL);
   1602 
   1603 	if (ISC_UNLIKELY((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)) {
   1604 		si = &(((size_info *)ptr)[-2]);
   1605 		REQUIRE(si->u.ctx == ctx);
   1606 		size = si[1].u.size;
   1607 	} else {
   1608 		si = &(((size_info *)ptr)[-1]);
   1609 		size = si->u.size;
   1610 	}
   1611 
   1612 	MCTXLOCK(ctx, &ctx->lock);
   1613 
   1614 	DELETE_TRACE(ctx, ptr, size, file, line);
   1615 
   1616 	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
   1617 		mem_putunlocked(ctx, si, size);
   1618 	} else {
   1619 		mem_putstats(ctx, si, size);
   1620 		mem_put(ctx, si, size);
   1621 	}
   1622 
   1623 	/*
   1624 	 * The check against ctx->lo_water == 0 is for the condition
   1625 	 * when the context was pushed over hi_water but then had
   1626 	 * isc_mem_setwater() called with 0 for hi_water and lo_water.
   1627 	 */
   1628 	if (ctx->is_overmem &&
   1629 	    (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
   1630 		ctx->is_overmem = ISC_FALSE;
   1631 	}
   1632 
   1633 	if (ctx->hi_called &&
   1634 	    (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {
   1635 		ctx->hi_called = ISC_FALSE;
   1636 
   1637 		if (ctx->water != NULL)
   1638 			call_water = ISC_TRUE;
   1639 	}
   1640 	MCTXUNLOCK(ctx, &ctx->lock);
   1641 
   1642 	if (call_water)
   1643 		(ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
   1644 }
   1645 
   1646 
   1647 /*
   1648  * Other useful things.
   1649  */
   1650 
   1651 char *
   1652 isc___mem_strdup(isc_mem_t *mctx0, const char *s FLARG) {
   1653 	isc__mem_t *mctx = (isc__mem_t *)mctx0;
   1654 	size_t len;
   1655 	char *ns;
   1656 
   1657 	REQUIRE(VALID_CONTEXT(mctx));
   1658 	REQUIRE(s != NULL);
   1659 
   1660 	len = strlen(s) + 1;
   1661 
   1662 	ns = isc__mem_allocate((isc_mem_t *)mctx, len FLARG_PASS);
   1663 
   1664 	if (ns != NULL)
   1665 		strlcpy(ns, s, len);
   1666 
   1667 	return (ns);
   1668 }
   1669 
   1670 void
   1671 isc__mem_setdestroycheck(isc_mem_t *ctx0, isc_boolean_t flag) {
   1672 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1673 
   1674 	REQUIRE(VALID_CONTEXT(ctx));
   1675 	MCTXLOCK(ctx, &ctx->lock);
   1676 
   1677 	ctx->checkfree = flag;
   1678 
   1679 	MCTXUNLOCK(ctx, &ctx->lock);
   1680 }
   1681 
   1682 /*
   1683  * Quotas
   1684  */
   1685 
   1686 void
   1687 isc_mem_setquota(isc_mem_t *ctx0, size_t quota) {
   1688 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1689 
   1690 	REQUIRE(VALID_CONTEXT(ctx));
   1691 	MCTXLOCK(ctx, &ctx->lock);
   1692 
   1693 	ctx->quota = quota;
   1694 
   1695 	MCTXUNLOCK(ctx, &ctx->lock);
   1696 }
   1697 
   1698 size_t
   1699 isc_mem_getquota(isc_mem_t *ctx0) {
   1700 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1701 	size_t quota;
   1702 
   1703 	REQUIRE(VALID_CONTEXT(ctx));
   1704 	MCTXLOCK(ctx, &ctx->lock);
   1705 
   1706 	quota = ctx->quota;
   1707 
   1708 	MCTXUNLOCK(ctx, &ctx->lock);
   1709 
   1710 	return (quota);
   1711 }
   1712 
   1713 size_t
   1714 isc__mem_inuse(isc_mem_t *ctx0) {
   1715 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1716 	size_t inuse;
   1717 
   1718 	REQUIRE(VALID_CONTEXT(ctx));
   1719 	MCTXLOCK(ctx, &ctx->lock);
   1720 
   1721 	inuse = ctx->inuse;
   1722 
   1723 	MCTXUNLOCK(ctx, &ctx->lock);
   1724 
   1725 	return (inuse);
   1726 }
   1727 
   1728 size_t
   1729 isc__mem_maxinuse(isc_mem_t *ctx0) {
   1730 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1731 	size_t maxinuse;
   1732 
   1733 	REQUIRE(VALID_CONTEXT(ctx));
   1734 	MCTXLOCK(ctx, &ctx->lock);
   1735 
   1736 	maxinuse = ctx->maxinuse;
   1737 
   1738 	MCTXUNLOCK(ctx, &ctx->lock);
   1739 
   1740 	return (maxinuse);
   1741 }
   1742 
   1743 size_t
   1744 isc__mem_total(isc_mem_t *ctx0) {
   1745 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1746 	size_t total;
   1747 
   1748 	REQUIRE(VALID_CONTEXT(ctx));
   1749 	MCTXLOCK(ctx, &ctx->lock);
   1750 
   1751 	total = ctx->total;
   1752 
   1753 	MCTXUNLOCK(ctx, &ctx->lock);
   1754 
   1755 	return (total);
   1756 }
   1757 
   1758 void
   1759 isc__mem_setwater(isc_mem_t *ctx0, isc_mem_water_t water, void *water_arg,
   1760 		  size_t hiwater, size_t lowater)
   1761 {
   1762 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1763 	isc_boolean_t callwater = ISC_FALSE;
   1764 	isc_mem_water_t oldwater;
   1765 	void *oldwater_arg;
   1766 
   1767 	REQUIRE(VALID_CONTEXT(ctx));
   1768 	REQUIRE(hiwater >= lowater);
   1769 
   1770 	MCTXLOCK(ctx, &ctx->lock);
   1771 	oldwater = ctx->water;
   1772 	oldwater_arg = ctx->water_arg;
   1773 	if (water == NULL) {
   1774 		callwater = ctx->hi_called;
   1775 		ctx->water = NULL;
   1776 		ctx->water_arg = NULL;
   1777 		ctx->hi_water = 0;
   1778 		ctx->lo_water = 0;
   1779 	} else {
   1780 		if (ctx->hi_called &&
   1781 		    (ctx->water != water || ctx->water_arg != water_arg ||
   1782 		     ctx->inuse < lowater || lowater == 0U))
   1783 			callwater = ISC_TRUE;
   1784 		ctx->water = water;
   1785 		ctx->water_arg = water_arg;
   1786 		ctx->hi_water = hiwater;
   1787 		ctx->lo_water = lowater;
   1788 	}
   1789 	MCTXUNLOCK(ctx, &ctx->lock);
   1790 
   1791 	if (callwater && oldwater != NULL)
   1792 		(oldwater)(oldwater_arg, ISC_MEM_LOWATER);
   1793 }
   1794 
   1795 isc_boolean_t
   1796 isc__mem_isovermem(isc_mem_t *ctx0) {
   1797 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1798 
   1799 	REQUIRE(VALID_CONTEXT(ctx));
   1800 
   1801 	/*
   1802 	 * We don't bother to lock the context because 100% accuracy isn't
   1803 	 * necessary (and even if we locked the context the returned value
   1804 	 * could be different from the actual state when it's used anyway)
   1805 	 */
   1806 	return (ctx->is_overmem);
   1807 }
   1808 
   1809 void
   1810 isc_mem_setname(isc_mem_t *ctx0, const char *name, void *tag) {
   1811 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1812 
   1813 	REQUIRE(VALID_CONTEXT(ctx));
   1814 
   1815 	LOCK(&ctx->lock);
   1816 	strlcpy(ctx->name, name, sizeof(ctx->name));
   1817 	ctx->tag = tag;
   1818 	UNLOCK(&ctx->lock);
   1819 }
   1820 
   1821 const char *
   1822 isc_mem_getname(isc_mem_t *ctx0) {
   1823 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1824 
   1825 	REQUIRE(VALID_CONTEXT(ctx));
   1826 
   1827 	if (ctx->name[0] == 0)
   1828 		return ("");
   1829 
   1830 	return (ctx->name);
   1831 }
   1832 
   1833 void *
   1834 isc_mem_gettag(isc_mem_t *ctx0) {
   1835 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   1836 
   1837 	REQUIRE(VALID_CONTEXT(ctx));
   1838 
   1839 	return (ctx->tag);
   1840 }
   1841 
   1842 /*
   1843  * Memory pool stuff
   1844  */
   1845 
   1846 isc_result_t
   1847 isc__mempool_create(isc_mem_t *mctx0, size_t size, isc_mempool_t **mpctxp) {
   1848 	isc__mem_t *mctx = (isc__mem_t *)mctx0;
   1849 	isc__mempool_t *mpctx;
   1850 
   1851 	REQUIRE(VALID_CONTEXT(mctx));
   1852 	REQUIRE(size > 0U);
   1853 	REQUIRE(mpctxp != NULL && *mpctxp == NULL);
   1854 
   1855 	/*
   1856 	 * Allocate space for this pool, initialize values, and if all works
   1857 	 * well, attach to the memory context.
   1858 	 */
   1859 	mpctx = isc_mem_get((isc_mem_t *)mctx, sizeof(isc__mempool_t));
   1860 	if (mpctx == NULL)
   1861 		return (ISC_R_NOMEMORY);
   1862 
   1863 	mpctx->common.methods = (isc_mempoolmethods_t *)&mempoolmethods;
   1864 	mpctx->common.impmagic = MEMPOOL_MAGIC;
   1865 	mpctx->common.magic = ISCAPI_MPOOL_MAGIC;
   1866 	mpctx->lock = NULL;
   1867 	mpctx->mctx = mctx;
   1868 	mpctx->size = size;
   1869 	mpctx->maxalloc = UINT_MAX;
   1870 	mpctx->allocated = 0;
   1871 	mpctx->freecount = 0;
   1872 	mpctx->freemax = 1;
   1873 	mpctx->fillcount = 1;
   1874 	mpctx->gets = 0;
   1875 #if ISC_MEMPOOL_NAMES
   1876 	mpctx->name[0] = 0;
   1877 #endif
   1878 	mpctx->items = NULL;
   1879 
   1880 	*mpctxp = (isc_mempool_t *)mpctx;
   1881 
   1882 	MCTXLOCK(mctx, &mctx->lock);
   1883 	ISC_LIST_INITANDAPPEND(mctx->pools, mpctx, link);
   1884 	mctx->poolcnt++;
   1885 	MCTXUNLOCK(mctx, &mctx->lock);
   1886 
   1887 	return (ISC_R_SUCCESS);
   1888 }
   1889 
   1890 void
   1891 isc__mempool_setname(isc_mempool_t *mpctx0, const char *name) {
   1892 	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
   1893 
   1894 	REQUIRE(name != NULL);
   1895 	REQUIRE(VALID_MEMPOOL(mpctx));
   1896 
   1897 #if ISC_MEMPOOL_NAMES
   1898 	if (mpctx->lock != NULL)
   1899 		LOCK(mpctx->lock);
   1900 
   1901 	strlcpy(mpctx->name, name, sizeof(mpctx->name));
   1902 
   1903 	if (mpctx->lock != NULL)
   1904 		UNLOCK(mpctx->lock);
   1905 #else
   1906 	UNUSED(mpctx);
   1907 	UNUSED(name);
   1908 #endif
   1909 }
   1910 
   1911 void
   1912 isc__mempool_destroy(isc_mempool_t **mpctxp) {
   1913 	isc__mempool_t *mpctx;
   1914 	isc__mem_t *mctx;
   1915 	isc_mutex_t *lock;
   1916 	element *item;
   1917 
   1918 	REQUIRE(mpctxp != NULL);
   1919 	mpctx = (isc__mempool_t *)*mpctxp;
   1920 	REQUIRE(VALID_MEMPOOL(mpctx));
   1921 #if ISC_MEMPOOL_NAMES
   1922 	if (mpctx->allocated > 0)
   1923 		UNEXPECTED_ERROR(__FILE__, __LINE__,
   1924 				 "isc__mempool_destroy(): mempool %s "
   1925 				 "leaked memory",
   1926 				 mpctx->name);
   1927 #endif
   1928 	REQUIRE(mpctx->allocated == 0);
   1929 
   1930 	mctx = mpctx->mctx;
   1931 
   1932 	lock = mpctx->lock;
   1933 
   1934 	if (lock != NULL)
   1935 		LOCK(lock);
   1936 
   1937 	/*
   1938 	 * Return any items on the free list
   1939 	 */
   1940 	MCTXLOCK(mctx, &mctx->lock);
   1941 	while (mpctx->items != NULL) {
   1942 		INSIST(mpctx->freecount > 0);
   1943 		mpctx->freecount--;
   1944 		item = mpctx->items;
   1945 		mpctx->items = item->next;
   1946 
   1947 		if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
   1948 			mem_putunlocked(mctx, item, mpctx->size);
   1949 		} else {
   1950 			mem_putstats(mctx, item, mpctx->size);
   1951 			mem_put(mctx, item, mpctx->size);
   1952 		}
   1953 	}
   1954 	MCTXUNLOCK(mctx, &mctx->lock);
   1955 
   1956 	/*
   1957 	 * Remove our linked list entry from the memory context.
   1958 	 */
   1959 	MCTXLOCK(mctx, &mctx->lock);
   1960 	ISC_LIST_UNLINK(mctx->pools, mpctx, link);
   1961 	mctx->poolcnt--;
   1962 	MCTXUNLOCK(mctx, &mctx->lock);
   1963 
   1964 	mpctx->common.impmagic = 0;
   1965 	mpctx->common.magic = 0;
   1966 
   1967 	isc_mem_put((isc_mem_t *)mpctx->mctx, mpctx, sizeof(isc__mempool_t));
   1968 
   1969 	if (lock != NULL)
   1970 		UNLOCK(lock);
   1971 
   1972 	*mpctxp = NULL;
   1973 }
   1974 
   1975 void
   1976 isc__mempool_associatelock(isc_mempool_t *mpctx0, isc_mutex_t *lock) {
   1977 	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
   1978 
   1979 	REQUIRE(VALID_MEMPOOL(mpctx));
   1980 	REQUIRE(mpctx->lock == NULL);
   1981 	REQUIRE(lock != NULL);
   1982 
   1983 	mpctx->lock = lock;
   1984 }
   1985 
   1986 void *
   1987 isc___mempool_get(isc_mempool_t *mpctx0 FLARG) {
   1988 	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
   1989 	element *item;
   1990 	isc__mem_t *mctx;
   1991 	unsigned int i;
   1992 
   1993 	REQUIRE(VALID_MEMPOOL(mpctx));
   1994 
   1995 	mctx = mpctx->mctx;
   1996 
   1997 	if (mpctx->lock != NULL)
   1998 		LOCK(mpctx->lock);
   1999 
   2000 	/*
   2001 	 * Don't let the caller go over quota
   2002 	 */
   2003 	if (ISC_UNLIKELY(mpctx->allocated >= mpctx->maxalloc)) {
   2004 		item = NULL;
   2005 		goto out;
   2006 	}
   2007 
   2008 	if (ISC_UNLIKELY(mpctx->items == NULL)) {
   2009 		/*
   2010 		 * We need to dip into the well.  Lock the memory context
   2011 		 * here and fill up our free list.
   2012 		 */
   2013 		MCTXLOCK(mctx, &mctx->lock);
   2014 		for (i = 0; i < mpctx->fillcount; i++) {
   2015 			if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
   2016 				item = mem_getunlocked(mctx, mpctx->size);
   2017 			} else {
   2018 				item = mem_get(mctx, mpctx->size);
   2019 				if (item != NULL)
   2020 					mem_getstats(mctx, mpctx->size);
   2021 			}
   2022 			if (ISC_UNLIKELY(item == NULL))
   2023 				break;
   2024 			item->next = mpctx->items;
   2025 			mpctx->items = item;
   2026 			mpctx->freecount++;
   2027 		}
   2028 		MCTXUNLOCK(mctx, &mctx->lock);
   2029 	}
   2030 
   2031 	/*
   2032 	 * If we didn't get any items, return NULL.
   2033 	 */
   2034 	item = mpctx->items;
   2035 	if (ISC_UNLIKELY(item == NULL))
   2036 		goto out;
   2037 
   2038 	mpctx->items = item->next;
   2039 	INSIST(mpctx->freecount > 0);
   2040 	mpctx->freecount--;
   2041 	mpctx->gets++;
   2042 	mpctx->allocated++;
   2043 
   2044  out:
   2045 	if (mpctx->lock != NULL)
   2046 		UNLOCK(mpctx->lock);
   2047 
   2048 #if ISC_MEM_TRACKLINES
   2049 	if (ISC_UNLIKELY(((isc_mem_debugging & TRACE_OR_RECORD) != 0) &&
   2050 			 item != NULL))
   2051 	{
   2052 		MCTXLOCK(mctx, &mctx->lock);
   2053 		ADD_TRACE(mctx, item, mpctx->size, file, line);
   2054 		MCTXUNLOCK(mctx, &mctx->lock);
   2055 	}
   2056 #endif /* ISC_MEM_TRACKLINES */
   2057 
   2058 	return (item);
   2059 }
   2060 
   2061 /* coverity[+free : arg-1] */
   2062 void
   2063 isc___mempool_put(isc_mempool_t *mpctx0, void *mem FLARG) {
   2064 	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
   2065 	isc__mem_t *mctx;
   2066 	element *item;
   2067 
   2068 	REQUIRE(VALID_MEMPOOL(mpctx));
   2069 	REQUIRE(mem != NULL);
   2070 
   2071 	mctx = mpctx->mctx;
   2072 
   2073 	if (mpctx->lock != NULL)
   2074 		LOCK(mpctx->lock);
   2075 
   2076 	INSIST(mpctx->allocated > 0);
   2077 	mpctx->allocated--;
   2078 
   2079 #if ISC_MEM_TRACKLINES
   2080 	if (ISC_UNLIKELY((isc_mem_debugging & TRACE_OR_RECORD) != 0)) {
   2081 		MCTXLOCK(mctx, &mctx->lock);
   2082 		DELETE_TRACE(mctx, mem, mpctx->size, file, line);
   2083 		MCTXUNLOCK(mctx, &mctx->lock);
   2084 	}
   2085 #endif /* ISC_MEM_TRACKLINES */
   2086 
   2087 	/*
   2088 	 * If our free list is full, return this to the mctx directly.
   2089 	 */
   2090 	if (mpctx->freecount >= mpctx->freemax) {
   2091 		MCTXLOCK(mctx, &mctx->lock);
   2092 		if ((mctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
   2093 			mem_putunlocked(mctx, mem, mpctx->size);
   2094 		} else {
   2095 			mem_putstats(mctx, mem, mpctx->size);
   2096 			mem_put(mctx, mem, mpctx->size);
   2097 		}
   2098 		MCTXUNLOCK(mctx, &mctx->lock);
   2099 		if (mpctx->lock != NULL)
   2100 			UNLOCK(mpctx->lock);
   2101 		return;
   2102 	}
   2103 
   2104 	/*
   2105 	 * Otherwise, attach it to our free list and bump the counter.
   2106 	 */
   2107 	mpctx->freecount++;
   2108 	item = (element *)mem;
   2109 	item->next = mpctx->items;
   2110 	mpctx->items = item;
   2111 
   2112 	if (mpctx->lock != NULL)
   2113 		UNLOCK(mpctx->lock);
   2114 }
   2115 
   2116 /*
   2117  * Quotas
   2118  */
   2119 
   2120 void
   2121 isc__mempool_setfreemax(isc_mempool_t *mpctx0, unsigned int limit) {
   2122 	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
   2123 
   2124 	REQUIRE(VALID_MEMPOOL(mpctx));
   2125 
   2126 	if (mpctx->lock != NULL)
   2127 		LOCK(mpctx->lock);
   2128 
   2129 	mpctx->freemax = limit;
   2130 
   2131 	if (mpctx->lock != NULL)
   2132 		UNLOCK(mpctx->lock);
   2133 }
   2134 
   2135 unsigned int
   2136 isc_mempool_getfreemax(isc_mempool_t *mpctx0) {
   2137 	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
   2138 	unsigned int freemax;
   2139 
   2140 	REQUIRE(VALID_MEMPOOL(mpctx));
   2141 
   2142 	if (mpctx->lock != NULL)
   2143 		LOCK(mpctx->lock);
   2144 
   2145 	freemax = mpctx->freemax;
   2146 
   2147 	if (mpctx->lock != NULL)
   2148 		UNLOCK(mpctx->lock);
   2149 
   2150 	return (freemax);
   2151 }
   2152 
   2153 unsigned int
   2154 isc_mempool_getfreecount(isc_mempool_t *mpctx0) {
   2155 	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
   2156 	unsigned int freecount;
   2157 
   2158 	REQUIRE(VALID_MEMPOOL(mpctx));
   2159 
   2160 	if (mpctx->lock != NULL)
   2161 		LOCK(mpctx->lock);
   2162 
   2163 	freecount = mpctx->freecount;
   2164 
   2165 	if (mpctx->lock != NULL)
   2166 		UNLOCK(mpctx->lock);
   2167 
   2168 	return (freecount);
   2169 }
   2170 
   2171 void
   2172 isc__mempool_setmaxalloc(isc_mempool_t *mpctx0, unsigned int limit) {
   2173 	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
   2174 
   2175 	REQUIRE(limit > 0);
   2176 
   2177 	REQUIRE(VALID_MEMPOOL(mpctx));
   2178 
   2179 	if (mpctx->lock != NULL)
   2180 		LOCK(mpctx->lock);
   2181 
   2182 	mpctx->maxalloc = limit;
   2183 
   2184 	if (mpctx->lock != NULL)
   2185 		UNLOCK(mpctx->lock);
   2186 }
   2187 
   2188 unsigned int
   2189 isc_mempool_getmaxalloc(isc_mempool_t *mpctx0) {
   2190 	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
   2191 	unsigned int maxalloc;
   2192 
   2193 	REQUIRE(VALID_MEMPOOL(mpctx));
   2194 
   2195 	if (mpctx->lock != NULL)
   2196 		LOCK(mpctx->lock);
   2197 
   2198 	maxalloc = mpctx->maxalloc;
   2199 
   2200 	if (mpctx->lock != NULL)
   2201 		UNLOCK(mpctx->lock);
   2202 
   2203 	return (maxalloc);
   2204 }
   2205 
   2206 unsigned int
   2207 isc__mempool_getallocated(isc_mempool_t *mpctx0) {
   2208 	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
   2209 	unsigned int allocated;
   2210 
   2211 	REQUIRE(VALID_MEMPOOL(mpctx));
   2212 
   2213 	if (mpctx->lock != NULL)
   2214 		LOCK(mpctx->lock);
   2215 
   2216 	allocated = mpctx->allocated;
   2217 
   2218 	if (mpctx->lock != NULL)
   2219 		UNLOCK(mpctx->lock);
   2220 
   2221 	return (allocated);
   2222 }
   2223 
   2224 void
   2225 isc__mempool_setfillcount(isc_mempool_t *mpctx0, unsigned int limit) {
   2226 	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
   2227 
   2228 	REQUIRE(limit > 0);
   2229 	REQUIRE(VALID_MEMPOOL(mpctx));
   2230 
   2231 	if (mpctx->lock != NULL)
   2232 		LOCK(mpctx->lock);
   2233 
   2234 	mpctx->fillcount = limit;
   2235 
   2236 	if (mpctx->lock != NULL)
   2237 		UNLOCK(mpctx->lock);
   2238 }
   2239 
   2240 unsigned int
   2241 isc_mempool_getfillcount(isc_mempool_t *mpctx0) {
   2242 	isc__mempool_t *mpctx = (isc__mempool_t *)mpctx0;
   2243 
   2244 	unsigned int fillcount;
   2245 
   2246 	REQUIRE(VALID_MEMPOOL(mpctx));
   2247 
   2248 	if (mpctx->lock != NULL)
   2249 		LOCK(mpctx->lock);
   2250 
   2251 	fillcount = mpctx->fillcount;
   2252 
   2253 	if (mpctx->lock != NULL)
   2254 		UNLOCK(mpctx->lock);
   2255 
   2256 	return (fillcount);
   2257 }
   2258 
   2259 isc_result_t
   2260 isc__mem_register(void) {
   2261 	return (isc_mem_register(isc_mem_create2));
   2262 }
   2263 
   2264 void
   2265 isc__mem_printactive(isc_mem_t *ctx0, FILE *file) {
   2266 #if ISC_MEM_TRACKLINES
   2267 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   2268 
   2269 	REQUIRE(VALID_CONTEXT(ctx));
   2270 	REQUIRE(file != NULL);
   2271 
   2272 	print_active(ctx, file);
   2273 #else
   2274 	UNUSED(ctx0);
   2275 	UNUSED(file);
   2276 #endif
   2277 }
   2278 
   2279 
   2280 /*
   2281  * Requires contextslock to be held by caller.
   2282  */
   2283 static void
   2284 print_contexts(FILE *file) {
   2285 	isc__mem_t *ctx;
   2286 
   2287 	for (ctx = ISC_LIST_HEAD(contexts);
   2288 	     ctx != NULL;
   2289 	     ctx = ISC_LIST_NEXT(ctx, link))
   2290 	{
   2291 		fprintf(file, "context: %p (%s): %u references\n",
   2292 			ctx,
   2293 			ctx->name[0] == 0 ? "<unknown>" : ctx->name,
   2294 			ctx->references);
   2295 		print_active(ctx, file);
   2296 	}
   2297 	fflush(file);
   2298 }
   2299 
   2300 void
   2301 isc_mem_printallactive(FILE *file) {
   2302 #if !ISC_MEM_TRACKLINES
   2303 	UNUSED(file);
   2304 #else
   2305 	RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
   2306 
   2307 	LOCK(&contextslock);
   2308 	print_contexts(file);
   2309 	UNLOCK(&contextslock);
   2310 #endif
   2311 }
   2312 
   2313 void
   2314 isc_mem_checkdestroyed(FILE *file) {
   2315 #if !ISC_MEM_TRACKLINES
   2316 	UNUSED(file);
   2317 #endif
   2318 
   2319 	RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
   2320 
   2321 	LOCK(&contextslock);
   2322 	if (!ISC_LIST_EMPTY(contexts)) {
   2323 #if ISC_MEM_TRACKLINES
   2324 		if (ISC_UNLIKELY((isc_mem_debugging & TRACE_OR_RECORD) != 0)) {
   2325 			print_contexts(file);
   2326 		}
   2327 #endif
   2328 		INSIST(0);
   2329 	}
   2330 	UNLOCK(&contextslock);
   2331 }
   2332 
   2333 unsigned int
   2334 isc_mem_references(isc_mem_t *ctx0) {
   2335 	isc__mem_t *ctx = (isc__mem_t *)ctx0;
   2336 	unsigned int references;
   2337 
   2338 	REQUIRE(VALID_CONTEXT(ctx));
   2339 
   2340 	MCTXLOCK(ctx, &ctx->lock);
   2341 	references = ctx->references;
   2342 	MCTXUNLOCK(ctx, &ctx->lock);
   2343 
   2344 	return (references);
   2345 }
   2346 
   2347 typedef struct summarystat {
   2348 	isc_uint64_t	total;
   2349 	isc_uint64_t	inuse;
   2350 	isc_uint64_t	malloced;
   2351 	isc_uint64_t	blocksize;
   2352 	isc_uint64_t	contextsize;
   2353 } summarystat_t;
   2354 
   2355 #ifdef HAVE_LIBXML2
   2356 #define TRY0(a) do { xmlrc = (a); if (xmlrc < 0) goto error; } while(0)
   2357 static int
   2358 xml_renderctx(isc__mem_t *ctx, summarystat_t *summary,
   2359 	      xmlTextWriterPtr writer)
   2360 {
   2361 	int xmlrc;
   2362 
   2363 	REQUIRE(VALID_CONTEXT(ctx));
   2364 
   2365 	MCTXLOCK(ctx, &ctx->lock);
   2366 
   2367 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "context"));
   2368 
   2369 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "id"));
   2370 	TRY0(xmlTextWriterWriteFormatString(writer, "%p", ctx));
   2371 	TRY0(xmlTextWriterEndElement(writer)); /* id */
   2372 
   2373 	if (ctx->name[0] != 0) {
   2374 		TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "name"));
   2375 		TRY0(xmlTextWriterWriteFormatString(writer, "%s", ctx->name));
   2376 		TRY0(xmlTextWriterEndElement(writer)); /* name */
   2377 	}
   2378 
   2379 	summary->contextsize += sizeof(*ctx) +
   2380 		(ctx->max_size + 1) * sizeof(struct stats) +
   2381 		ctx->max_size * sizeof(element *) +
   2382 		ctx->basic_table_count * sizeof(char *);
   2383 #if ISC_MEM_TRACKLINES
   2384 	if (ctx->debuglist != NULL) {
   2385 		summary->contextsize +=
   2386 			DEBUG_TABLE_COUNT * sizeof(debuglist_t) +
   2387 			ctx->debuglistcnt * sizeof(debuglink_t);
   2388 	}
   2389 #endif
   2390 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "references"));
   2391 	TRY0(xmlTextWriterWriteFormatString(writer, "%d", ctx->references));
   2392 	TRY0(xmlTextWriterEndElement(writer)); /* references */
   2393 
   2394 	summary->total += ctx->total;
   2395 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "total"));
   2396 	TRY0(xmlTextWriterWriteFormatString(writer,
   2397 					    "%" ISC_PRINT_QUADFORMAT "u",
   2398 					    (isc_uint64_t)ctx->total));
   2399 	TRY0(xmlTextWriterEndElement(writer)); /* total */
   2400 
   2401 	summary->inuse += ctx->inuse;
   2402 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "inuse"));
   2403 	TRY0(xmlTextWriterWriteFormatString(writer,
   2404 					    "%" ISC_PRINT_QUADFORMAT "u",
   2405 					    (isc_uint64_t)ctx->inuse));
   2406 	TRY0(xmlTextWriterEndElement(writer)); /* inuse */
   2407 
   2408 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "maxinuse"));
   2409 	TRY0(xmlTextWriterWriteFormatString(writer,
   2410 					    "%" ISC_PRINT_QUADFORMAT "u",
   2411 					    (isc_uint64_t)ctx->maxinuse));
   2412 	TRY0(xmlTextWriterEndElement(writer)); /* maxinuse */
   2413 
   2414 	summary->malloced += ctx->malloced;
   2415 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "malloced"));
   2416 	TRY0(xmlTextWriterWriteFormatString(writer,
   2417 					    "%" ISC_PRINT_QUADFORMAT "u",
   2418 					    (isc_uint64_t)ctx->malloced));
   2419 	TRY0(xmlTextWriterEndElement(writer)); /* malloced */
   2420 
   2421 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "maxmalloced"));
   2422 	TRY0(xmlTextWriterWriteFormatString(writer,
   2423 					    "%" ISC_PRINT_QUADFORMAT "u",
   2424 					    (isc_uint64_t)ctx->maxmalloced));
   2425 	TRY0(xmlTextWriterEndElement(writer)); /* maxmalloced */
   2426 
   2427 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "blocksize"));
   2428 	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
   2429 		summary->blocksize += ctx->basic_table_count *
   2430 			NUM_BASIC_BLOCKS * ctx->mem_target;
   2431 		TRY0(xmlTextWriterWriteFormatString(writer,
   2432 					       "%" ISC_PRINT_QUADFORMAT "u",
   2433 					       (isc_uint64_t)
   2434 					       ctx->basic_table_count *
   2435 					       NUM_BASIC_BLOCKS *
   2436 					       ctx->mem_target));
   2437 	} else
   2438 		TRY0(xmlTextWriterWriteFormatString(writer, "%s", "-"));
   2439 	TRY0(xmlTextWriterEndElement(writer)); /* blocksize */
   2440 
   2441 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "pools"));
   2442 	TRY0(xmlTextWriterWriteFormatString(writer, "%u", ctx->poolcnt));
   2443 	TRY0(xmlTextWriterEndElement(writer)); /* pools */
   2444 	summary->contextsize += ctx->poolcnt * sizeof(isc_mempool_t);
   2445 
   2446 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "hiwater"));
   2447 	TRY0(xmlTextWriterWriteFormatString(writer,
   2448 					    "%" ISC_PRINT_QUADFORMAT "u",
   2449 					    (isc_uint64_t)ctx->hi_water));
   2450 	TRY0(xmlTextWriterEndElement(writer)); /* hiwater */
   2451 
   2452 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "lowater"));
   2453 	TRY0(xmlTextWriterWriteFormatString(writer,
   2454 					    "%" ISC_PRINT_QUADFORMAT "u",
   2455 					    (isc_uint64_t)ctx->lo_water));
   2456 	TRY0(xmlTextWriterEndElement(writer)); /* lowater */
   2457 
   2458 	TRY0(xmlTextWriterEndElement(writer)); /* context */
   2459 
   2460  error:
   2461 	MCTXUNLOCK(ctx, &ctx->lock);
   2462 
   2463 	return (xmlrc);
   2464 }
   2465 
   2466 int
   2467 isc_mem_renderxml(xmlTextWriterPtr writer) {
   2468 	isc__mem_t *ctx;
   2469 	summarystat_t summary;
   2470 	isc_uint64_t lost;
   2471 	int xmlrc;
   2472 
   2473 	memset(&summary, 0, sizeof(summary));
   2474 
   2475 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "contexts"));
   2476 
   2477 	RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
   2478 
   2479 	LOCK(&contextslock);
   2480 	lost = totallost;
   2481 	for (ctx = ISC_LIST_HEAD(contexts);
   2482 	     ctx != NULL;
   2483 	     ctx = ISC_LIST_NEXT(ctx, link)) {
   2484 		xmlrc = xml_renderctx(ctx, &summary, writer);
   2485 		if (xmlrc < 0) {
   2486 			UNLOCK(&contextslock);
   2487 			goto error;
   2488 		}
   2489 	}
   2490 	UNLOCK(&contextslock);
   2491 
   2492 	TRY0(xmlTextWriterEndElement(writer)); /* contexts */
   2493 
   2494 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "summary"));
   2495 
   2496 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "TotalUse"));
   2497 	TRY0(xmlTextWriterWriteFormatString(writer,
   2498 					    "%" ISC_PRINT_QUADFORMAT "u",
   2499 					    summary.total));
   2500 	TRY0(xmlTextWriterEndElement(writer)); /* TotalUse */
   2501 
   2502 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "InUse"));
   2503 	TRY0(xmlTextWriterWriteFormatString(writer,
   2504 					    "%" ISC_PRINT_QUADFORMAT "u",
   2505 					    summary.inuse));
   2506 	TRY0(xmlTextWriterEndElement(writer)); /* InUse */
   2507 
   2508 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "Malloced"));
   2509 	TRY0(xmlTextWriterWriteFormatString(writer,
   2510 					    "%" ISC_PRINT_QUADFORMAT "u",
   2511 					    summary.malloced));
   2512 	TRY0(xmlTextWriterEndElement(writer)); /* InUse */
   2513 
   2514 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "BlockSize"));
   2515 	TRY0(xmlTextWriterWriteFormatString(writer,
   2516 					    "%" ISC_PRINT_QUADFORMAT "u",
   2517 					    summary.blocksize));
   2518 	TRY0(xmlTextWriterEndElement(writer)); /* BlockSize */
   2519 
   2520 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "ContextSize"));
   2521 	TRY0(xmlTextWriterWriteFormatString(writer,
   2522 					    "%" ISC_PRINT_QUADFORMAT "u",
   2523 					    summary.contextsize));
   2524 	TRY0(xmlTextWriterEndElement(writer)); /* ContextSize */
   2525 
   2526 	TRY0(xmlTextWriterStartElement(writer, ISC_XMLCHAR "Lost"));
   2527 	TRY0(xmlTextWriterWriteFormatString(writer,
   2528 					    "%" ISC_PRINT_QUADFORMAT "u",
   2529 					    lost));
   2530 	TRY0(xmlTextWriterEndElement(writer)); /* Lost */
   2531 
   2532 	TRY0(xmlTextWriterEndElement(writer)); /* summary */
   2533  error:
   2534 	return (xmlrc);
   2535 }
   2536 
   2537 #endif /* HAVE_LIBXML2 */
   2538 
   2539 #ifdef HAVE_JSON
   2540 #define CHECKMEM(m) do { \
   2541 	if (m == NULL) { \
   2542 		result = ISC_R_NOMEMORY;\
   2543 		goto error;\
   2544 	} \
   2545 } while(0)
   2546 
   2547 static isc_result_t
   2548 json_renderctx(isc__mem_t *ctx, summarystat_t *summary, json_object *array) {
   2549 	isc_result_t result = ISC_R_FAILURE;
   2550 	json_object *ctxobj, *obj;
   2551 	char buf[1024];
   2552 
   2553 	REQUIRE(VALID_CONTEXT(ctx));
   2554 	REQUIRE(summary != NULL);
   2555 	REQUIRE(array != NULL);
   2556 
   2557 	MCTXLOCK(ctx, &ctx->lock);
   2558 
   2559 	summary->contextsize += sizeof(*ctx) +
   2560 		(ctx->max_size + 1) * sizeof(struct stats) +
   2561 		ctx->max_size * sizeof(element *) +
   2562 		ctx->basic_table_count * sizeof(char *);
   2563 	summary->total += ctx->total;
   2564 	summary->inuse += ctx->inuse;
   2565 	summary->malloced += ctx->malloced;
   2566 	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0)
   2567 		summary->blocksize += ctx->basic_table_count *
   2568 			NUM_BASIC_BLOCKS * ctx->mem_target;
   2569 #if ISC_MEM_TRACKLINES
   2570 	if (ctx->debuglist != NULL) {
   2571 		summary->contextsize +=
   2572 			DEBUG_TABLE_COUNT * sizeof(debuglist_t) +
   2573 			ctx->debuglistcnt * sizeof(debuglink_t);
   2574 	}
   2575 #endif
   2576 
   2577 	ctxobj = json_object_new_object();
   2578 	CHECKMEM(ctxobj);
   2579 
   2580 	snprintf(buf, sizeof(buf), "%p", ctx);
   2581 	obj = json_object_new_string(buf);
   2582 	CHECKMEM(obj);
   2583 	json_object_object_add(ctxobj, "id", obj);
   2584 
   2585 	if (ctx->name[0] != 0) {
   2586 		obj = json_object_new_string(ctx->name);
   2587 		CHECKMEM(obj);
   2588 		json_object_object_add(ctxobj, "name", obj);
   2589 	}
   2590 
   2591 	obj = json_object_new_int64(ctx->references);
   2592 	CHECKMEM(obj);
   2593 	json_object_object_add(ctxobj, "references", obj);
   2594 
   2595 	obj = json_object_new_int64(ctx->total);
   2596 	CHECKMEM(obj);
   2597 	json_object_object_add(ctxobj, "total", obj);
   2598 
   2599 	obj = json_object_new_int64(ctx->inuse);
   2600 	CHECKMEM(obj);
   2601 	json_object_object_add(ctxobj, "inuse", obj);
   2602 
   2603 	obj = json_object_new_int64(ctx->maxinuse);
   2604 	CHECKMEM(obj);
   2605 	json_object_object_add(ctxobj, "maxinuse", obj);
   2606 
   2607 	obj = json_object_new_int64(ctx->malloced);
   2608 	CHECKMEM(obj);
   2609 	json_object_object_add(ctxobj, "malloced", obj);
   2610 
   2611 	obj = json_object_new_int64(ctx->maxmalloced);
   2612 	CHECKMEM(obj);
   2613 	json_object_object_add(ctxobj, "maxmalloced", obj);
   2614 
   2615 	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {
   2616 		isc_uint64_t blocksize;
   2617 		blocksize = ctx->basic_table_count * NUM_BASIC_BLOCKS *
   2618 			ctx->mem_target;
   2619 		obj = json_object_new_int64(blocksize);
   2620 		CHECKMEM(obj);
   2621 		json_object_object_add(ctxobj, "blocksize", obj);
   2622 	}
   2623 
   2624 	obj = json_object_new_int64(ctx->poolcnt);
   2625 	CHECKMEM(obj);
   2626 	json_object_object_add(ctxobj, "pools", obj);
   2627 
   2628 	summary->contextsize += ctx->poolcnt * sizeof(isc_mempool_t);
   2629 
   2630 	obj = json_object_new_int64(ctx->hi_water);
   2631 	CHECKMEM(obj);
   2632 	json_object_object_add(ctxobj, "hiwater", obj);
   2633 
   2634 	obj = json_object_new_int64(ctx->lo_water);
   2635 	CHECKMEM(obj);
   2636 	json_object_object_add(ctxobj, "lowater", obj);
   2637 
   2638 	MCTXUNLOCK(ctx, &ctx->lock);
   2639 	json_object_array_add(array, ctxobj);
   2640 	return (ISC_R_SUCCESS);
   2641 
   2642  error:
   2643 	MCTXUNLOCK(ctx, &ctx->lock);
   2644 	if (ctxobj != NULL)
   2645 		json_object_put(ctxobj);
   2646 	return (result);
   2647 }
   2648 
   2649 isc_result_t
   2650 isc_mem_renderjson(json_object *memobj) {
   2651 	isc_result_t result = ISC_R_SUCCESS;
   2652 	isc__mem_t *ctx;
   2653 	summarystat_t summary;
   2654 	isc_uint64_t lost;
   2655 	json_object *ctxarray, *obj;
   2656 
   2657 	memset(&summary, 0, sizeof(summary));
   2658 	RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
   2659 
   2660 	ctxarray = json_object_new_array();
   2661 	CHECKMEM(ctxarray);
   2662 
   2663 	LOCK(&contextslock);
   2664 	lost = totallost;
   2665 	for (ctx = ISC_LIST_HEAD(contexts);
   2666 	     ctx != NULL;
   2667 	     ctx = ISC_LIST_NEXT(ctx, link)) {
   2668 		result = json_renderctx(ctx, &summary, ctxarray);
   2669 		if (result != ISC_R_SUCCESS) {
   2670 			UNLOCK(&contextslock);
   2671 			goto error;
   2672 		}
   2673 	}
   2674 	UNLOCK(&contextslock);
   2675 
   2676 	obj = json_object_new_int64(summary.total);
   2677 	CHECKMEM(obj);
   2678 	json_object_object_add(memobj, "TotalUse", obj);
   2679 
   2680 	obj = json_object_new_int64(summary.inuse);
   2681 	CHECKMEM(obj);
   2682 	json_object_object_add(memobj, "InUse", obj);
   2683 
   2684 	obj = json_object_new_int64(summary.malloced);
   2685 	CHECKMEM(obj);
   2686 	json_object_object_add(memobj, "Malloced", obj);
   2687 
   2688 	obj = json_object_new_int64(summary.blocksize);
   2689 	CHECKMEM(obj);
   2690 	json_object_object_add(memobj, "BlockSize", obj);
   2691 
   2692 	obj = json_object_new_int64(summary.contextsize);
   2693 	CHECKMEM(obj);
   2694 	json_object_object_add(memobj, "ContextSize", obj);
   2695 
   2696 	obj = json_object_new_int64(lost);
   2697 	CHECKMEM(obj);
   2698 	json_object_object_add(memobj, "Lost", obj);
   2699 
   2700 	json_object_object_add(memobj, "contexts", ctxarray);
   2701 	return (ISC_R_SUCCESS);
   2702 
   2703  error:
   2704 	if (ctxarray != NULL)
   2705 		json_object_put(ctxarray);
   2706 	return (result);
   2707 }
   2708 #endif /* HAVE_JSON */
   2709 
   2710 static isc_memcreatefunc_t mem_createfunc = NULL;
   2711 
   2712 isc_result_t
   2713 isc_mem_register(isc_memcreatefunc_t createfunc) {
   2714 	isc_result_t result = ISC_R_SUCCESS;
   2715 
   2716 	RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);
   2717 
   2718 	LOCK(&createlock);
   2719 	if (mem_createfunc == NULL)
   2720 		mem_createfunc = createfunc;
   2721 	else
   2722 		result = ISC_R_EXISTS;
   2723 	UNLOCK(&createlock);
   2724 
   2725 	return (result);
   2726 }
   2727 
   2728 
   2729 isc_result_t
   2730 isc__mem_create2(size_t init_max_size, size_t target_size, isc_mem_t **mctxp,
   2731 		 unsigned int flags)
   2732 {
   2733 	isc_result_t result;
   2734 
   2735 	LOCK(&createlock);
   2736 
   2737 	REQUIRE(mem_createfunc != NULL);
   2738 	result = (*mem_createfunc)(init_max_size, target_size, mctxp, flags);
   2739 
   2740 	UNLOCK(&createlock);
   2741 
   2742 	return (result);
   2743 }
   2744 
   2745 isc_result_t
   2746 isc_mem_create(size_t init_max_size, size_t target_size, isc_mem_t **mctxp) {
   2747 	isc_result_t result;
   2748 
   2749 	if (isc_bind9)
   2750 		return (isc_mem_createx2(init_max_size, target_size,
   2751 					 default_memalloc, default_memfree,
   2752 					 NULL, mctxp, isc_mem_defaultflags));
   2753 	LOCK(&createlock);
   2754 
   2755 	REQUIRE(mem_createfunc != NULL);
   2756 	result = (*mem_createfunc)(init_max_size, target_size, mctxp,
   2757 				   isc_mem_defaultflags);
   2758 
   2759 	UNLOCK(&createlock);
   2760 
   2761 	return (result);
   2762 }
   2763 
   2764 isc_result_t
   2765 isc_mem_create2(size_t init_max_size, size_t target_size, isc_mem_t **mctxp,
   2766 		 unsigned int flags)
   2767 {
   2768 	if (isc_bind9)
   2769 		return (isc_mem_createx2(init_max_size, target_size,
   2770 					 default_memalloc, default_memfree,
   2771 					 NULL, mctxp, flags));
   2772 
   2773 	return (isc_mem_createx2(init_max_size, target_size,
   2774 				 default_memalloc, default_memfree,
   2775 				 NULL, mctxp, flags));
   2776 }
   2777 
   2778 void
   2779 isc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
   2780 	REQUIRE(ISCAPI_MCTX_VALID(source));
   2781 	REQUIRE(targetp != NULL && *targetp == NULL);
   2782 
   2783 	if (isc_bind9)
   2784 		isc__mem_attach(source, targetp);
   2785 	else
   2786 		source->methods->attach(source, targetp);
   2787 
   2788 	ENSURE(*targetp == source);
   2789 }
   2790 
   2791 void
   2792 isc_mem_detach(isc_mem_t **mctxp) {
   2793 	REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
   2794 
   2795 	if (isc_bind9)
   2796 		isc__mem_detach(mctxp);
   2797 	else
   2798 		(*mctxp)->methods->detach(mctxp);
   2799 
   2800 	ENSURE(*mctxp == NULL);
   2801 }
   2802 
   2803 void
   2804 isc_mem_destroy(isc_mem_t **mctxp) {
   2805 	REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
   2806 
   2807 	if (isc_bind9)
   2808 		isc__mem_destroy(mctxp);
   2809 	else
   2810 		(*mctxp)->methods->destroy(mctxp);
   2811 
   2812 	ENSURE(*mctxp == NULL);
   2813 }
   2814 
   2815 void
   2816 isc_mem_setdestroycheck(isc_mem_t *mctx, isc_boolean_t flag) {
   2817 	REQUIRE(ISCAPI_MCTX_VALID(mctx));
   2818 
   2819 	mctx->methods->setdestroycheck(mctx, flag);
   2820 }
   2821 
   2822 void
   2823 isc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
   2824 		 size_t hiwater, size_t lowater)
   2825 {
   2826 	REQUIRE(ISCAPI_MCTX_VALID(ctx));
   2827 
   2828 	if (isc_bind9)
   2829 		isc__mem_setwater(ctx, water, water_arg, hiwater, lowater);
   2830 	else
   2831 		ctx->methods->setwater(ctx, water, water_arg, hiwater, lowater);
   2832 }
   2833 
   2834 void
   2835 isc_mem_waterack(isc_mem_t *ctx, int flag) {
   2836 	REQUIRE(ISCAPI_MCTX_VALID(ctx));
   2837 
   2838 	if (isc_bind9)
   2839 		isc__mem_waterack(ctx, flag);
   2840 	else
   2841 		ctx->methods->waterack(ctx, flag);
   2842 }
   2843 
   2844 size_t
   2845 isc_mem_inuse(isc_mem_t *mctx) {
   2846 	REQUIRE(ISCAPI_MCTX_VALID(mctx));
   2847 
   2848 	if (isc_bind9)
   2849 		return (isc__mem_inuse(mctx));
   2850 
   2851 	return (mctx->methods->inuse(mctx));
   2852 }
   2853 
   2854 size_t
   2855 isc_mem_maxinuse(isc_mem_t *mctx) {
   2856 	REQUIRE(ISCAPI_MCTX_VALID(mctx));
   2857 
   2858 	if (isc_bind9)
   2859 		return (isc__mem_maxinuse(mctx));
   2860 
   2861 	return (mctx->methods->maxinuse(mctx));
   2862 }
   2863 
   2864 size_t
   2865 isc_mem_total(isc_mem_t *mctx) {
   2866 	REQUIRE(ISCAPI_MCTX_VALID(mctx));
   2867 
   2868 	if (isc_bind9)
   2869 		return (isc__mem_total(mctx));
   2870 
   2871 	return (mctx->methods->total(mctx));
   2872 }
   2873 
   2874 isc_boolean_t
   2875 isc_mem_isovermem(isc_mem_t *mctx) {
   2876 	REQUIRE(ISCAPI_MCTX_VALID(mctx));
   2877 
   2878 	if (isc_bind9)
   2879 		return (isc__mem_isovermem(mctx));
   2880 
   2881 	return (mctx->methods->isovermem(mctx));
   2882 }
   2883 
   2884 
   2885 isc_result_t
   2886 isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
   2887 	REQUIRE(ISCAPI_MCTX_VALID(mctx));
   2888 
   2889 	return (mctx->methods->mpcreate(mctx, size, mpctxp));
   2890 }
   2891 
   2892 void
   2893 isc_mempool_destroy(isc_mempool_t **mpctxp) {
   2894 	REQUIRE(mpctxp != NULL && ISCAPI_MPOOL_VALID(*mpctxp));
   2895 
   2896 	if (isc_bind9)
   2897 		isc__mempool_destroy(mpctxp);
   2898 	else
   2899 		(*mpctxp)->methods->destroy(mpctxp);
   2900 
   2901 	ENSURE(*mpctxp == NULL);
   2902 }
   2903 
   2904 unsigned int
   2905 isc_mempool_getallocated(isc_mempool_t *mpctx) {
   2906 	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
   2907 
   2908 	if (isc_bind9)
   2909 		return (isc__mempool_getallocated(mpctx));
   2910 
   2911 	return (mpctx->methods->getallocated(mpctx));
   2912 }
   2913 
   2914 void
   2915 isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) {
   2916 	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
   2917 
   2918 	if (isc_bind9)
   2919 		isc__mempool_setmaxalloc(mpctx, limit);
   2920 	else
   2921 		mpctx->methods->setmaxalloc(mpctx, limit);
   2922 }
   2923 
   2924 void
   2925 isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) {
   2926 	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
   2927 
   2928 	if (isc_bind9)
   2929 		isc__mempool_setfreemax(mpctx, limit);
   2930 	else
   2931 		mpctx->methods->setfreemax(mpctx, limit);
   2932 }
   2933 
   2934 void
   2935 isc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
   2936 	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
   2937 
   2938 	if (isc_bind9)
   2939 		isc__mempool_setname(mpctx, name);
   2940 	else
   2941 		mpctx->methods->setname(mpctx, name);
   2942 }
   2943 
   2944 void
   2945 isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) {
   2946 	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
   2947 
   2948 	if (isc_bind9)
   2949 		isc__mempool_associatelock(mpctx, lock);
   2950 	else
   2951 		mpctx->methods->associatelock(mpctx, lock);
   2952 }
   2953 
   2954 void
   2955 isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) {
   2956 	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
   2957 
   2958 	if (isc_bind9)
   2959 		isc__mempool_setfillcount(mpctx, limit);
   2960 	else
   2961 		mpctx->methods->setfillcount(mpctx, limit);
   2962 }
   2963 
   2964 void *
   2965 isc__mem_get(isc_mem_t *mctx, size_t size FLARG) {
   2966 	REQUIRE(ISCAPI_MCTX_VALID(mctx));
   2967 
   2968 	if (isc_bind9)
   2969 		return (isc___mem_get(mctx, size FLARG_PASS));
   2970 
   2971 	return (mctx->methods->memget(mctx, size FLARG_PASS));
   2972 
   2973 }
   2974 
   2975 void
   2976 isc__mem_put(isc_mem_t *mctx, void *ptr, size_t size FLARG) {
   2977 	REQUIRE(ISCAPI_MCTX_VALID(mctx));
   2978 
   2979 	if (isc_bind9)
   2980 		isc___mem_put(mctx, ptr, size FLARG_PASS);
   2981 	else
   2982 		mctx->methods->memput(mctx, ptr, size FLARG_PASS);
   2983 }
   2984 
   2985 void
   2986 isc__mem_putanddetach(isc_mem_t **mctxp, void *ptr, size_t size FLARG) {
   2987 	REQUIRE(mctxp != NULL && ISCAPI_MCTX_VALID(*mctxp));
   2988 
   2989 	if (isc_bind9)
   2990 		isc___mem_putanddetach(mctxp, ptr, size FLARG_PASS);
   2991 	else
   2992 		(*mctxp)->methods->memputanddetach(mctxp, ptr, size FLARG_PASS);
   2993 
   2994 	/*
   2995 	 * XXX: We cannot always ensure *mctxp == NULL here
   2996 	 * (see lib/isc/mem.c).
   2997 	 */
   2998 }
   2999 
   3000 void *
   3001 isc__mem_allocate(isc_mem_t *mctx, size_t size FLARG) {
   3002 	REQUIRE(ISCAPI_MCTX_VALID(mctx));
   3003 
   3004 	if (isc_bind9)
   3005 		return (isc___mem_allocate(mctx, size FLARG_PASS));
   3006 
   3007 	return (mctx->methods->memallocate(mctx, size FLARG_PASS));
   3008 }
   3009 
   3010 void *
   3011 isc__mem_reallocate(isc_mem_t *mctx, void *ptr, size_t size FLARG) {
   3012 	REQUIRE(ISCAPI_MCTX_VALID(mctx));
   3013 
   3014 	if (isc_bind9)
   3015 		return (isc___mem_reallocate(mctx, ptr, size FLARG_PASS));
   3016 
   3017 	return (mctx->methods->memreallocate(mctx, ptr, size FLARG_PASS));
   3018 }
   3019 
   3020 char *
   3021 isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
   3022 	REQUIRE(ISCAPI_MCTX_VALID(mctx));
   3023 
   3024 	if (isc_bind9)
   3025 		return (isc___mem_strdup(mctx, s FLARG_PASS));
   3026 
   3027 	return (mctx->methods->memstrdup(mctx, s FLARG_PASS));
   3028 }
   3029 
   3030 void
   3031 isc__mem_free(isc_mem_t *mctx, void *ptr FLARG) {
   3032 	REQUIRE(ISCAPI_MCTX_VALID(mctx));
   3033 
   3034 	if (isc_bind9)
   3035 		isc___mem_free(mctx, ptr FLARG_PASS);
   3036 	else
   3037 		mctx->methods->memfree(mctx, ptr FLARG_PASS);
   3038 }
   3039 
   3040 void *
   3041 isc__mempool_get(isc_mempool_t *mpctx FLARG) {
   3042 	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
   3043 
   3044 	if (isc_bind9)
   3045 		return (isc___mempool_get(mpctx FLARG_PASS));
   3046 
   3047 	return (mpctx->methods->get(mpctx FLARG_PASS));
   3048 }
   3049 
   3050 void
   3051 isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
   3052 	REQUIRE(ISCAPI_MPOOL_VALID(mpctx));
   3053 
   3054 	if (isc_bind9)
   3055 		isc___mempool_put(mpctx, mem FLARG_PASS);
   3056 	else
   3057 		mpctx->methods->put(mpctx, mem FLARG_PASS);
   3058 }
   3059