mem.c 23.5 KB
Newer Older
Bob Halley's avatar
base  
Bob Halley committed
1
/*
Bob Halley's avatar
Bob Halley committed
2
 * Copyright (C) 1997, 1998, 1999  Internet Software Consortium.
Bob Halley's avatar
Bob Halley committed
3
 * 
Bob Halley's avatar
base  
Bob Halley committed
4 5 6
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
Bob Halley's avatar
Bob Halley committed
7
 * 
Bob Halley's avatar
base  
Bob Halley committed
8 9 10 11 12 13 14 15 16 17
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */

Bob Halley's avatar
Bob Halley committed
18
#include <config.h>
Bob Halley's avatar
base  
Bob Halley committed
19 20 21

#include <stdio.h>
#include <stdlib.h>
Bob Halley's avatar
Bob Halley committed
22
#include <stddef.h>
Bob Halley's avatar
base  
Bob Halley committed
23 24
#include <string.h>

Michael Graff's avatar
Michael Graff committed
25 26
#include <limits.h>

Bob Halley's avatar
base  
Bob Halley committed
27
#include <isc/assertions.h>
28
#include <isc/error.h>
Bob Halley's avatar
Bob Halley committed
29
#include <isc/mem.h>
Bob Halley's avatar
Bob Halley committed
30

31
#ifndef ISC_SINGLETHREADED
Bob Halley's avatar
update  
Bob Halley committed
32
#include <isc/mutex.h>
Bob Halley's avatar
Bob Halley committed
33 34
#include "util.h"
#else
Bob Halley's avatar
Bob Halley committed
35 36
#define LOCK(l)
#define UNLOCK(l)
Bob Halley's avatar
update  
Bob Halley committed
37 38
#endif

Bob Halley's avatar
Bob Halley committed
39
#ifndef ISC_MEM_FILL
40 41
	/*
	 * XXXMPA
Bob Halley's avatar
Bob Halley committed
42
	 * We want this on during development to catch:
43 44 45 46 47 48
	 * 1. some reference after free bugs.
	 * 2. some failure to initalise bugs.
	 */
#define ISC_MEM_FILL 1
#endif

Bob Halley's avatar
base  
Bob Halley committed
49 50 51 52
/*
 * Types.
 */

Bob Halley's avatar
Bob Halley committed
53
typedef struct {
Bob Halley's avatar
base  
Bob Halley committed
54
	void *			next;
Bob Halley's avatar
Bob Halley committed
55
} element;
Bob Halley's avatar
base  
Bob Halley committed
56 57 58 59 60 61

typedef struct {
	size_t			size;
	/*
	 * This structure must be ALIGNMENT_SIZE bytes.
	 */
Bob Halley's avatar
Bob Halley committed
62
} size_info;
Bob Halley's avatar
base  
Bob Halley committed
63 64

struct stats {
Bob Halley's avatar
Bob Halley committed
65 66 67 68
	unsigned long		gets;
	unsigned long		totalgets;
	unsigned long		blocks;
	unsigned long		freefrags;
Bob Halley's avatar
base  
Bob Halley committed
69 70
};

71 72
#define MEM_MAGIC		0x4D656d43U	/* MemC. */
#define VALID_CONTEXT(c)	((c) != NULL && (c)->magic == MEM_MAGIC)
Bob Halley's avatar
Bob Halley committed
73

74
struct isc_mem {
Bob Halley's avatar
Bob Halley committed
75 76
	unsigned int		magic;
	isc_mutex_t		lock;
77 78 79
	isc_memalloc_t		memalloc;
	isc_memfree_t		memfree;
	void *			arg;
Bob Halley's avatar
base  
Bob Halley committed
80 81
	size_t			max_size;
	size_t			mem_target;
Bob Halley's avatar
Bob Halley committed
82 83
	element **		freelists;
	element *		basic_blocks;
84 85 86
	unsigned char **	basic_table;
	unsigned int		basic_table_count;
	unsigned int		basic_table_size;
Bob Halley's avatar
Bob Halley committed
87 88
	unsigned char *		lowest;
	unsigned char *		highest;
Bob Halley's avatar
base  
Bob Halley committed
89
	struct stats *		stats;
90
	size_t			quota;
Bob Halley's avatar
Bob Halley committed
91
	size_t			total;
Michael Graff's avatar
Michael Graff committed
92 93 94 95 96 97 98
	ISC_LIST(isc_mempool_t)	pools;
};

#define MEMPOOL_MAGIC		0x4D454d70U	/* MEMp. */
#define VALID_MEMPOOL(c)	((c) != NULL && (c)->magic == MEMPOOL_MAGIC)

struct isc_mempool {
Michael Graff's avatar
Michael Graff committed
99
	/* always unlocked */
Michael Graff's avatar
Michael Graff committed
100
	unsigned int	magic;		/* magic number */
Michael Graff's avatar
Michael Graff committed
101
	isc_mutex_t    *lock;		/* optional lock */
Michael Graff's avatar
Michael Graff committed
102
	isc_mem_t      *mctx;		/* our memory context */
Michael Graff's avatar
Michael Graff committed
103 104 105
	/* locked via the memory context's lock */
	ISC_LINK(isc_mempool_t)	link;	/* next pool in this mem context */
	/* optionally locked from here down */
Michael Graff's avatar
Michael Graff committed
106 107 108 109 110 111 112 113 114
	element	       *items;		/* low water item list */
	size_t		size;		/* size of each item on this pool */
	unsigned int	maxalloc;	/* max number of items allowed */
	unsigned int	allocated;	/* # of items currently given out */
	unsigned int	freecount;	/* # of items on reserved list */
	unsigned int	freemax;	/* # of items allowed on free list */
	unsigned int	fillcount;	/* # of items to fetch on each fill */
	/* Stats only. */
	unsigned int	gets;		/* # of requests to this pool */
Bob Halley's avatar
base  
Bob Halley committed
115 116 117 118
};

/* Forward. */

Michael Graff's avatar
Michael Graff committed
119
static inline size_t		quantize(size_t);
Bob Halley's avatar
Bob Halley committed
120 121
static inline void		mem_putunlocked(isc_mem_t *, void *, size_t);
static inline void *		mem_getunlocked(isc_mem_t *, size_t);
Bob Halley's avatar
base  
Bob Halley committed
122

Bob Halley's avatar
Bob Halley committed
123
/* Constants. */
Bob Halley's avatar
base  
Bob Halley committed
124 125 126 127 128

#define DEF_MAX_SIZE		1100
#define DEF_MEM_TARGET		4096
#define ALIGNMENT_SIZE		sizeof (void *)
#define NUM_BASIC_BLOCKS	64			/* must be > 1 */
129
#define TABLE_INCREMENT		1024
Bob Halley's avatar
base  
Bob Halley committed
130 131 132

/* Private Inline-able. */

133
static inline size_t
Bob Halley's avatar
base  
Bob Halley committed
134
quantize(size_t size) {
135
	int temp;
Bob Halley's avatar
base  
Bob Halley committed
136 137

	/*
138
	 * Round up the result in order to get a size big
Bob Halley's avatar
base  
Bob Halley committed
139 140 141
	 * enough to satisfy the request and be aligned on ALIGNMENT_SIZE
	 * byte boundaries.
	 */
142 143 144

	temp = size + (ALIGNMENT_SIZE - 1);
	return (temp - temp % ALIGNMENT_SIZE); 
Bob Halley's avatar
base  
Bob Halley committed
145 146
}

147 148 149 150 151 152 153 154 155 156 157
/* Private. */

static void *
default_memalloc(void *arg, size_t size) {
	(void)arg;
	return (malloc(size));
}

static void
default_memfree(void *arg, void *ptr) {
	(void)arg;
James Brister's avatar
James Brister committed
158
	free(ptr);
159 160
}

Bob Halley's avatar
base  
Bob Halley committed
161 162
/* Public. */

Bob Halley's avatar
Bob Halley committed
163
isc_result_t
164 165 166
isc_mem_createx(size_t init_max_size, size_t target_size,
		isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
		isc_mem_t **ctxp)
Bob Halley's avatar
Bob Halley committed
167
{
168
	isc_mem_t *ctx;
Bob Halley's avatar
Bob Halley committed
169 170

	REQUIRE(ctxp != NULL && *ctxp == NULL);
171 172
	REQUIRE(memalloc != NULL);
	REQUIRE(memfree != NULL);
Bob Halley's avatar
base  
Bob Halley committed
173

174
	ctx = (memalloc)(arg, sizeof *ctx);
Michael Graff's avatar
Michael Graff committed
175 176 177
	if (ctx == NULL)
		return (ISC_R_NOMEMORY);

Bob Halley's avatar
base  
Bob Halley committed
178 179 180 181 182 183 184 185
	if (init_max_size == 0)
		ctx->max_size = DEF_MAX_SIZE;
	else
		ctx->max_size = init_max_size;
	if (target_size == 0)
		ctx->mem_target = DEF_MEM_TARGET;
	else
		ctx->mem_target = target_size;
186 187 188 189
	ctx->memalloc = memalloc;
	ctx->memfree = memfree;
	ctx->arg = arg;
	ctx->freelists = (memalloc)(arg, ctx->max_size * sizeof (element *));
Bob Halley's avatar
base  
Bob Halley committed
190
	if (ctx->freelists == NULL) {
191
		(memfree)(arg, ctx);
Bob Halley's avatar
Bob Halley committed
192
		return (ISC_R_NOMEMORY);
Bob Halley's avatar
base  
Bob Halley committed
193
	}
Bob Halley's avatar
Bob Halley committed
194 195
	memset(ctx->freelists, 0,
	       ctx->max_size * sizeof (element *));
196 197
	ctx->stats = (memalloc)(arg,
				(ctx->max_size+1) * sizeof (struct stats));
Bob Halley's avatar
base  
Bob Halley committed
198
	if (ctx->stats == NULL) {
199 200
		(memfree)(arg, ctx->freelists);
		(memfree)(arg, ctx);
Bob Halley's avatar
Bob Halley committed
201
		return (ISC_R_NOMEMORY);
Bob Halley's avatar
base  
Bob Halley committed
202 203 204
	}
	memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof (struct stats));
	ctx->basic_blocks = NULL;
205 206 207
	ctx->basic_table = NULL;
	ctx->basic_table_count = 0;
	ctx->basic_table_size = 0;
Bob Halley's avatar
base  
Bob Halley committed
208 209
	ctx->lowest = NULL;
	ctx->highest = NULL;
Bob Halley's avatar
Bob Halley committed
210
	if (isc_mutex_init(&ctx->lock) != ISC_R_SUCCESS) {
211 212 213
		(memfree)(arg, ctx->stats);
		(memfree)(arg, ctx->freelists);
		(memfree)(arg, ctx);
Bob Halley's avatar
Bob Halley committed
214
		UNEXPECTED_ERROR(__FILE__, __LINE__,
Bob Halley's avatar
Bob Halley committed
215
				 "isc_mutex_init() failed");
Bob Halley's avatar
Bob Halley committed
216
		return (ISC_R_UNEXPECTED);
Bob Halley's avatar
update  
Bob Halley committed
217
	}
218
	ctx->quota = 0;
Bob Halley's avatar
Bob Halley committed
219
	ctx->total = 0;
Bob Halley's avatar
Bob Halley committed
220
	ctx->magic = MEM_MAGIC;
Michael Graff's avatar
Michael Graff committed
221 222
	ISC_LIST_INIT(ctx->pools);

Bob Halley's avatar
base  
Bob Halley committed
223
	*ctxp = ctx;
Bob Halley's avatar
Bob Halley committed
224
	return (ISC_R_SUCCESS);
Bob Halley's avatar
base  
Bob Halley committed
225 226
}

227 228 229 230 231 232 233 234 235
isc_result_t
isc_mem_create(size_t init_max_size, size_t target_size,
	       isc_mem_t **ctxp)
{
	return (isc_mem_createx(init_max_size, target_size,
				default_memalloc, default_memfree, NULL,
				ctxp));
}

Bob Halley's avatar
base  
Bob Halley committed
236
void
237
isc_mem_destroy(isc_mem_t **ctxp) {
238
	unsigned int i;
239
	isc_mem_t *ctx;
240

Bob Halley's avatar
base  
Bob Halley committed
241
	REQUIRE(ctxp != NULL);
242
	ctx = *ctxp;
Bob Halley's avatar
Bob Halley committed
243 244 245
	REQUIRE(VALID_CONTEXT(ctx));

	ctx->magic = 0;
246

Michael Graff's avatar
Michael Graff committed
247 248
	INSIST(ISC_LIST_EMPTY(ctx->pools));

249 250 251 252
	for (i = 0; i <= ctx->max_size; i++)
		INSIST(ctx->stats[i].gets == 0);

	for (i = 0; i < ctx->basic_table_count; i++)
253 254 255 256
		(ctx->memfree)(ctx->arg, ctx->basic_table[i]);
	(ctx->memfree)(ctx->arg, ctx->freelists);
	(ctx->memfree)(ctx->arg, ctx->stats);
	(ctx->memfree)(ctx->arg, ctx->basic_table);
Bob Halley's avatar
Bob Halley committed
257
	(void)isc_mutex_destroy(&ctx->lock);
258
	(ctx->memfree)(ctx->arg, ctx);
Bob Halley's avatar
base  
Bob Halley committed
259 260 261 262

	*ctxp = NULL;
}

263 264 265 266 267 268 269 270 271 272 273
isc_result_t
isc_mem_restore(isc_mem_t *ctx) {
	isc_result_t result;

	result = isc_mutex_init(&ctx->lock); 
	if (result != ISC_R_SUCCESS)
		ctx->magic = 0;

	return (result);
}

274
static void
275
more_basic_blocks(isc_mem_t *ctx) {
276 277 278 279 280
	void *new;
	unsigned char *curr, *next;
	unsigned char *first, *last;
	unsigned char **table;
	unsigned int table_size;
Bob Halley's avatar
Bob Halley committed
281
	size_t increment;
282 283 284 285
	int i;

	/* Require: we hold the context lock. */

286 287 288
	/*
	 * Did we hit the quota for this context?
	 */
Bob Halley's avatar
Bob Halley committed
289 290 291
	increment = NUM_BASIC_BLOCKS * ctx->mem_target;
	if (ctx->quota != 0 && ctx->total + increment > ctx->quota)
		return;
292 293 294

	INSIST(ctx->basic_table_count <= ctx->basic_table_size);
	if (ctx->basic_table_count == ctx->basic_table_size) {
295
		table_size = ctx->basic_table_size + TABLE_INCREMENT;
296 297
		table = (ctx->memalloc)(ctx->arg,
					table_size * sizeof (unsigned char *));
298 299
		if (table == NULL)
			return;
300 301 302 303
		if (ctx->basic_table_size != 0) {
			memcpy(table, ctx->basic_table,
			       ctx->basic_table_size *
			       sizeof (unsigned char *));
304
			(ctx->memfree)(ctx->arg, ctx->basic_table);
305
		}
306 307
		ctx->basic_table = table;
		ctx->basic_table_size = table_size;
308
	}
309

310
	new = (ctx->memalloc)(ctx->arg, NUM_BASIC_BLOCKS * ctx->mem_target);
311
	if (new == NULL)
312
		return;
Bob Halley's avatar
Bob Halley committed
313
	ctx->total += increment;
314 315
	ctx->basic_table[ctx->basic_table_count] = new;
	ctx->basic_table_count++;
316

317 318 319
	curr = new;
	next = curr + ctx->mem_target;
	for (i = 0; i < (NUM_BASIC_BLOCKS - 1); i++) {
Bob Halley's avatar
Bob Halley committed
320
		((element *)curr)->next = next;
321 322 323 324 325 326 327
		curr = next;
		next += ctx->mem_target;
	}
	/*
	 * curr is now pointing at the last block in the
	 * array.
	 */
Bob Halley's avatar
Bob Halley committed
328
	((element *)curr)->next = NULL;
329 330 331 332 333 334 335 336 337
	first = new;
	last = first + NUM_BASIC_BLOCKS * ctx->mem_target - 1;
	if (first < ctx->lowest || ctx->lowest == NULL)
		ctx->lowest = first;
	if (last > ctx->highest)
		ctx->highest = last;
	ctx->basic_blocks = new;
}

Bob Halley's avatar
base  
Bob Halley committed
338
void *
Bob Halley's avatar
Bob Halley committed
339
__isc_mem_get(isc_mem_t *ctx, size_t size)
Michael Graff's avatar
Michael Graff committed
340
{
Bob Halley's avatar
base  
Bob Halley committed
341 342 343
	void *ret;

	REQUIRE(size > 0);
Bob Halley's avatar
Bob Halley committed
344
	REQUIRE(VALID_CONTEXT(ctx));
Michael Graff's avatar
Michael Graff committed
345

Bob Halley's avatar
Bob Halley committed
346
	LOCK(&ctx->lock);
Bob Halley's avatar
Bob Halley committed
347
	ret = mem_getunlocked(ctx, size);
Michael Graff's avatar
Michael Graff committed
348 349 350 351 352 353
	UNLOCK(&ctx->lock);

	return (ret);
}

static inline void *
Bob Halley's avatar
Bob Halley committed
354
mem_getunlocked(isc_mem_t *ctx, size_t size)
Michael Graff's avatar
Michael Graff committed
355 356 357
{
	size_t new_size = quantize(size);
	void *ret;
Bob Halley's avatar
base  
Bob Halley committed
358 359 360

	if (size >= ctx->max_size || new_size >= ctx->max_size) {
		/* memget() was called on something beyond our upper limit. */
Bob Halley's avatar
Bob Halley committed
361 362 363 364
		if (ctx->quota != 0 && ctx->total + size > ctx->quota) {
			ret = NULL;
			goto done;
		}
365
		ret = (ctx->memalloc)(ctx->arg, size);
Bob Halley's avatar
base  
Bob Halley committed
366
		if (ret != NULL) {
Bob Halley's avatar
Bob Halley committed
367
			ctx->total += size;
Bob Halley's avatar
base  
Bob Halley committed
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
			ctx->stats[ctx->max_size].gets++;
			ctx->stats[ctx->max_size].totalgets++;
		}
		goto done;
	}

	/* 
	 * If there are no blocks in the free list for this size, get a chunk
	 * of memory and then break it up into "new_size"-sized blocks, adding
	 * them to the free list.
	 */
	if (ctx->freelists[new_size] == NULL) {
		int i, frags;
		size_t total_size;
		void *new;
Bob Halley's avatar
Bob Halley committed
383
		unsigned char *curr, *next;
Bob Halley's avatar
base  
Bob Halley committed
384 385

		if (ctx->basic_blocks == NULL) {
386 387
			more_basic_blocks(ctx);
			if (ctx->basic_blocks == NULL) {
Bob Halley's avatar
base  
Bob Halley committed
388 389 390 391 392 393 394 395 396 397 398 399 400 401
				ret = NULL;
				goto done;
			}
		}
		total_size = ctx->mem_target;
		new = ctx->basic_blocks;
		ctx->basic_blocks = ctx->basic_blocks->next;
		frags = total_size / new_size;
		ctx->stats[new_size].blocks++;
		ctx->stats[new_size].freefrags += frags;
		/* Set up a linked-list of blocks of size "new_size". */
		curr = new;
		next = curr + new_size;
		for (i = 0; i < (frags - 1); i++) {
Bob Halley's avatar
Bob Halley committed
402
			((element *)curr)->next = next;
Bob Halley's avatar
base  
Bob Halley committed
403 404 405 406
			curr = next;
			next += new_size;
		}
		/* curr is now pointing at the last block in the array. */
Bob Halley's avatar
Bob Halley committed
407
		((element *)curr)->next = NULL;
Bob Halley's avatar
base  
Bob Halley committed
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
		ctx->freelists[new_size] = new;
	}

	/* The free list uses the "rounded-up" size "new_size": */
	ret = ctx->freelists[new_size];
	ctx->freelists[new_size] = ctx->freelists[new_size]->next;

	/* 
	 * The stats[] uses the _actual_ "size" requested by the
	 * caller, with the caveat (in the code above) that "size" >= the
	 * max. size (max_size) ends up getting recorded as a call to
	 * max_size.
	 */
	ctx->stats[size].gets++;
	ctx->stats[size].totalgets++;
	ctx->stats[new_size].freefrags--;

 done:

427 428 429 430 431
#if ISC_MEM_FILL
	if (ret != NULL)
		memset(ret, 0xbe, new_size); /* Mnemonic for "beef". */
#endif

Bob Halley's avatar
base  
Bob Halley committed
432 433 434 435
	return (ret);
}

void
Bob Halley's avatar
Bob Halley committed
436
__isc_mem_put(isc_mem_t *ctx, void *mem, size_t size)
Michael Graff's avatar
Michael Graff committed
437
{
Bob Halley's avatar
base  
Bob Halley committed
438
	REQUIRE(size > 0);
Bob Halley's avatar
Bob Halley committed
439
	REQUIRE(VALID_CONTEXT(ctx));
Michael Graff's avatar
Michael Graff committed
440

Bob Halley's avatar
Bob Halley committed
441
	LOCK(&ctx->lock);
Bob Halley's avatar
Bob Halley committed
442
	mem_putunlocked(ctx, mem, size);
Michael Graff's avatar
Michael Graff committed
443 444 445 446
	UNLOCK(&ctx->lock);
}

static inline void
Bob Halley's avatar
Bob Halley committed
447
mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size)
Michael Graff's avatar
Michael Graff committed
448 449
{
	size_t new_size = quantize(size);
Bob Halley's avatar
base  
Bob Halley committed
450

451
#if ISC_MEM_FILL
Bob Halley's avatar
Bob Halley committed
452
	memset(mem, 0xde, new_size); /* Mnemonic for "dead". */
453 454
#endif

Bob Halley's avatar
base  
Bob Halley committed
455 456
	if (size == ctx->max_size || new_size >= ctx->max_size) {
		/* memput() called on something beyond our upper limit */
457
		(ctx->memfree)(ctx->arg, mem);
Bob Halley's avatar
base  
Bob Halley committed
458 459
		INSIST(ctx->stats[ctx->max_size].gets != 0);
		ctx->stats[ctx->max_size].gets--;
Bob Halley's avatar
Bob Halley committed
460 461
		INSIST(size <= ctx->total);
		ctx->total -= size;
Michael Graff's avatar
Michael Graff committed
462
		return;
Bob Halley's avatar
base  
Bob Halley committed
463 464 465
	}

	/* The free list uses the "rounded-up" size "new_size": */
Bob Halley's avatar
Bob Halley committed
466 467
	((element *)mem)->next = ctx->freelists[new_size];
	ctx->freelists[new_size] = (element *)mem;
Bob Halley's avatar
base  
Bob Halley committed
468 469 470 471 472 473 474 475 476 477 478 479 480

	/* 
	 * The stats[] uses the _actual_ "size" requested by the
	 * caller, with the caveat (in the code above) that "size" >= the
	 * max. size (max_size) ends up getting recorded as a call to
	 * max_size.
	 */
	INSIST(ctx->stats[size].gets != 0);
	ctx->stats[size].gets--;
	ctx->stats[new_size].freefrags++;
}

void *
481
__isc_mem_getdebug(isc_mem_t *ctx, size_t size, const char *file, int line) {
Bob Halley's avatar
base  
Bob Halley committed
482
	void *ptr;
Bob Halley's avatar
Bob Halley committed
483

Bob Halley's avatar
Bob Halley committed
484
	ptr = __isc_mem_get(ctx, size);
Bob Halley's avatar
base  
Bob Halley committed
485
	fprintf(stderr, "%s:%d: mem_get(%p, %lu) -> %p\n", file, line,
Bob Halley's avatar
Bob Halley committed
486
		ctx, (unsigned long)size, ptr);
Bob Halley's avatar
base  
Bob Halley committed
487 488 489 490
	return (ptr);
}

void
491
__isc_mem_putdebug(isc_mem_t *ctx, void *ptr, size_t size, const char *file,
Bob Halley's avatar
Bob Halley committed
492
		 int line)
Bob Halley's avatar
base  
Bob Halley committed
493 494
{
	fprintf(stderr, "%s:%d: mem_put(%p, %p, %lu)\n", file, line, 
Bob Halley's avatar
Bob Halley committed
495
		ctx, ptr, (unsigned long)size);
Bob Halley's avatar
Bob Halley committed
496
	__isc_mem_put(ctx, ptr, size);
Bob Halley's avatar
base  
Bob Halley committed
497 498 499 500 501 502
}

/*
 * Print the stats[] on the stream "out" with suitable formatting.
 */
void
Michael Graff's avatar
Michael Graff committed
503 504
isc_mem_stats(isc_mem_t *ctx, FILE *out)
{
Bob Halley's avatar
base  
Bob Halley committed
505
	size_t i;
Michael Graff's avatar
Michael Graff committed
506 507
	const struct stats *s;
	const isc_mempool_t *pool;
Bob Halley's avatar
base  
Bob Halley committed
508

Bob Halley's avatar
Bob Halley committed
509 510
	REQUIRE(VALID_CONTEXT(ctx));
	LOCK(&ctx->lock);
Bob Halley's avatar
base  
Bob Halley committed
511

Michael Graff's avatar
Michael Graff committed
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
	if (ctx->freelists != NULL) {
		for (i = 1; i <= ctx->max_size; i++) {
			s = &ctx->stats[i];

			if (s->totalgets == 0 && s->gets == 0)
				continue;
			fprintf(out, "%s%5d: %11lu gets, %11lu rem",
				(i == ctx->max_size) ? ">=" : "  ",
				i, s->totalgets, s->gets);
			if (s->blocks != 0)
				fprintf(out, " (%lu bl, %lu ff)",
					s->blocks, s->freefrags);
			fputc('\n', out);
		}
	}

Michael Graff's avatar
Michael Graff committed
528 529 530 531 532 533 534
	/*
	 * Note that since a pool can be locked now, these stats might be
	 * somewhat off if the pool is in active use at the time the stats
	 * are dumped.  The link fields are protected by the isc_mem_t's
	 * lock, however, so walking this list and extracting integers from
	 * stats fields is always safe.
	 */
Michael Graff's avatar
Michael Graff committed
535 536 537
	pool = ISC_LIST_HEAD(ctx->pools);
	if (pool != NULL) {
		fprintf(out, "[Pool statistics]\n");
Michael Graff's avatar
Michael Graff committed
538
		fprintf(out, "%10s %10s %10s %10s %10s %10s %10s %1s\n",
Michael Graff's avatar
Michael Graff committed
539
			"size", "maxalloc", "allocated", "freecount",
Michael Graff's avatar
Michael Graff committed
540
			"freemax", "fillcount", "gets", "L");
Michael Graff's avatar
Michael Graff committed
541 542
	}
	while (pool != NULL) {
Michael Graff's avatar
Michael Graff committed
543
		fprintf(out, "%10u %10u %10u %10u %10u %10u %10u %s\n",
Michael Graff's avatar
Michael Graff committed
544 545
			pool->size, pool->maxalloc, pool->allocated,
			pool->freecount, pool->freemax, pool->fillcount,
Michael Graff's avatar
Michael Graff committed
546 547
			pool->gets,
			(pool->lock == NULL ? "N" : "Y"));
Michael Graff's avatar
Michael Graff committed
548
		pool = ISC_LIST_NEXT(pool, link);
Bob Halley's avatar
base  
Bob Halley committed
549 550
	}

Bob Halley's avatar
Bob Halley committed
551
	UNLOCK(&ctx->lock);
Bob Halley's avatar
base  
Bob Halley committed
552 553
}

Bob Halley's avatar
Bob Halley committed
554
isc_boolean_t
555
isc_mem_valid(isc_mem_t *ctx, void *ptr) {
Bob Halley's avatar
Bob Halley committed
556
	unsigned char *cp = ptr;
Bob Halley's avatar
Bob Halley committed
557
	isc_boolean_t result = ISC_FALSE;
Bob Halley's avatar
base  
Bob Halley committed
558

Bob Halley's avatar
Bob Halley committed
559 560
	REQUIRE(VALID_CONTEXT(ctx));
	LOCK(&ctx->lock);
Bob Halley's avatar
base  
Bob Halley committed
561 562

	if (ctx->lowest != NULL && cp >= ctx->lowest && cp <= ctx->highest)
Bob Halley's avatar
Bob Halley committed
563
		result = ISC_TRUE;
Bob Halley's avatar
base  
Bob Halley committed
564

Bob Halley's avatar
Bob Halley committed
565
	UNLOCK(&ctx->lock);
Bob Halley's avatar
base  
Bob Halley committed
566

Bob Halley's avatar
Bob Halley committed
567
	return (result);
Bob Halley's avatar
base  
Bob Halley committed
568 569 570 571 572 573 574
}

/*
 * Replacements for malloc() and free().
 */

void *
575
isc_mem_allocate(isc_mem_t *ctx, size_t size) {
Bob Halley's avatar
Bob Halley committed
576
	size_info *si;
Bob Halley's avatar
base  
Bob Halley committed
577 578

	size += ALIGNMENT_SIZE;
Bob Halley's avatar
Bob Halley committed
579
	si = isc_mem_get(ctx, size);
Bob Halley's avatar
base  
Bob Halley committed
580 581 582 583 584 585 586
	if (si == NULL)
		return (NULL);
	si->size = size;
	return (&si[1]);
}

void
587
isc_mem_free(isc_mem_t *ctx, void *ptr) {
Bob Halley's avatar
Bob Halley committed
588
	size_info *si;
Bob Halley's avatar
base  
Bob Halley committed
589

Bob Halley's avatar
Bob Halley committed
590
	si = &(((size_info *)ptr)[-1]);
Bob Halley's avatar
Bob Halley committed
591
	isc_mem_put(ctx, si, si->size);
Bob Halley's avatar
base  
Bob Halley committed
592 593
}

Bob Halley's avatar
Bob Halley committed
594 595 596 597
/*
 * Other useful things.
 */

Bob Halley's avatar
Bob Halley committed
598 599 600 601 602 603 604 605 606 607 608 609 610 611
char *
isc_mem_strdup(isc_mem_t *mctx, const char *s) {
	size_t len;
	char *ns;

	len = strlen(s);
	ns = isc_mem_allocate(mctx, len + 1);
	if (ns == NULL)
		return (NULL);
	strncpy(ns, s, len + 1);
	
	return (ns);
}

612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
/*
 * Quotas
 */

void
isc_mem_setquota(isc_mem_t *ctx, size_t quota) {
	REQUIRE(VALID_CONTEXT(ctx));
	LOCK(&ctx->lock);

	ctx->quota = quota;

	UNLOCK(&ctx->lock);
}

size_t
isc_mem_getquota(isc_mem_t *ctx) {
	size_t quota;

	REQUIRE(VALID_CONTEXT(ctx));
	LOCK(&ctx->lock);

	quota = ctx->quota;

	UNLOCK(&ctx->lock);

	return (quota);
}

Bob Halley's avatar
Bob Halley committed
640 641
#ifdef ISC_MEMCLUSTER_LEGACY

Bob Halley's avatar
base  
Bob Halley committed
642 643 644 645
/*
 * Public Legacy.
 */

646
static isc_mem_t *default_context = NULL;
Bob Halley's avatar
Bob Halley committed
647

Bob Halley's avatar
base  
Bob Halley committed
648 649 650 651 652
int
meminit(size_t init_max_size, size_t target_size) {
	/* need default_context lock here */
	if (default_context != NULL)
		return (-1);
Bob Halley's avatar
Bob Halley committed
653
	return (isc_mem_create(init_max_size, target_size, &default_context));
Bob Halley's avatar
base  
Bob Halley committed
654 655
}

656
isc_mem_t *
Bob Halley's avatar
base  
Bob Halley committed
657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683
mem_default_context(void) {
	/* need default_context lock here */
	if (default_context == NULL && meminit(0, 0) == -1)
		return (NULL);
	return (default_context);
}

void *
__memget(size_t size) {
	/* need default_context lock here */
	if (default_context == NULL && meminit(0, 0) == -1)
		return (NULL);
	return (__mem_get(default_context, size));
}

void
__memput(void *mem, size_t size) {
	/* need default_context lock here */
	REQUIRE(default_context != NULL);
	__mem_put(default_context, mem, size);
}

void *
__memget_debug(size_t size, const char *file, int line) {
	void *ptr;
	ptr = __memget(size);
	fprintf(stderr, "%s:%d: memget(%lu) -> %p\n", file, line,
Bob Halley's avatar
Bob Halley committed
684
		(unsigned long)size, ptr);
Bob Halley's avatar
base  
Bob Halley committed
685 686 687 688 689 690
	return (ptr);
}

void
__memput_debug(void *ptr, size_t size, const char *file, int line) {
	fprintf(stderr, "%s:%d: memput(%p, %lu)\n", file, line, 
Bob Halley's avatar
Bob Halley committed
691
		ptr, (unsigned long)size);
Bob Halley's avatar
base  
Bob Halley committed
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
	__memput(ptr, size);
}

int
memvalid(void *ptr) {
	/* need default_context lock here */
	REQUIRE(default_context != NULL);
	return (mem_valid(default_context, ptr));
}

void
memstats(FILE *out) {
	/* need default_context lock here */
	REQUIRE(default_context != NULL);
	mem_stats(default_context, out);
}
Bob Halley's avatar
Bob Halley committed
708 709

#endif /* ISC_MEMCLUSTER_LEGACY */
Michael Graff's avatar
Michael Graff committed
710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737


/*
 * Memory pool stuff
 */


#if 0
/*
 * Free all but "n" items from the pool's free list.  If n == 0, all items
 * will be returned to the mctx.
 */
static void
mempool_release(isc_mempool_t *mpctx, unsigned int n)
{
	isc_mem_t *mctx;
	element *item;
	element *next;
	unsigned int count;

	mctx = mpctx->mctx;

	if (mpctx->freecount <= n)
		return;

	INSIST(mpctx->items != NULL);
	item = mpctx->items;
	for (count = 0 ; count < n ; count++) {
Michael Graff's avatar
Michael Graff committed
738
		item = item->next;
Michael Graff's avatar
Michael Graff committed
739 740 741 742 743 744 745 746 747
		INSIST(item != NULL);
	}

	/*
	 * All remaining items are to be freed.  Lock the context once,
	 * free them all, and unlock the context.
	 */
	LOCK(&mctx->lock);
	do {
Michael Graff's avatar
Michael Graff committed
748
		next = item->next;
Michael Graff's avatar
Michael Graff committed
749 750 751 752 753 754 755 756 757 758 759
		mem_putunlocked(mctx, item, mpctx->size);
		INSIST(mpctx->freecount > 0);
		mpctx->freecount--;
		item = next;
	} while (item != NULL);
	UNLOCK(&mctx->lock);
}
#endif

/*
 * Release all items on the free list.  No locking is done, the memory
Michael Graff's avatar
Michael Graff committed
760
 * context must be locked, and the pool if needed.
Michael Graff's avatar
Michael Graff committed
761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
 */
static void
mempool_releaseall(isc_mempool_t *mpctx)
{
	isc_mem_t *mctx;
	element *item;
	element *next;

	mctx = mpctx->mctx;

	if (mpctx->freecount == 0)
		return;

	INSIST(mpctx->items != NULL);
	item = mpctx->items;

	do {
Michael Graff's avatar
Michael Graff committed
778
		next = item->next;
Bob Halley's avatar
Bob Halley committed
779
		mem_putunlocked(mctx, item, mpctx->size);
Michael Graff's avatar
Michael Graff committed
780 781 782 783 784 785 786
		INSIST(mpctx->freecount > 0);
		mpctx->freecount--;
		item = next;
	} while (item != NULL);
}

isc_result_t
Michael Graff's avatar
Michael Graff committed
787
isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp)
Michael Graff's avatar
Michael Graff committed
788 789 790 791
{
	isc_mempool_t *mpctx;

	REQUIRE(VALID_CONTEXT(mctx));
Michael Graff's avatar
Michael Graff committed
792
	REQUIRE(size > 0);
Michael Graff's avatar
Michael Graff committed
793 794 795 796 797 798 799 800
	REQUIRE(mpctxp != NULL && *mpctxp == NULL);

	/*
	 * Allocate space for this pool, initialize values, and if all works
	 * well, attach to the memory context.
	 */
	LOCK(&mctx->lock);

Bob Halley's avatar
Bob Halley committed
801
	mpctx = mem_getunlocked(mctx, sizeof(isc_mempool_t));
Michael Graff's avatar
Michael Graff committed
802 803 804 805 806 807
	if (mpctx == NULL) {
		UNLOCK(&mctx->lock);
		return (ISC_R_NOMEMORY);
	}

	mpctx->magic = MEMPOOL_MAGIC;
Michael Graff's avatar
Michael Graff committed
808
	mpctx->lock = NULL;
Michael Graff's avatar
Michael Graff committed
809
	mpctx->mctx = mctx;
Michael Graff's avatar
Michael Graff committed
810
	mpctx->size = size;
Michael Graff's avatar
Michael Graff committed
811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832
	mpctx->maxalloc = UINT_MAX;
	mpctx->allocated = 0;
	mpctx->freecount = 0;
	mpctx->freemax = 1;
	mpctx->fillcount = 1;
	mpctx->gets = 0;
	mpctx->items = NULL;

	*mpctxp = mpctx;

	ISC_LIST_APPEND(mctx->pools, mpctx, link);

	UNLOCK(&mctx->lock);

	return (ISC_R_SUCCESS);
}

void
isc_mempool_destroy(isc_mempool_t **mpctxp)
{
	isc_mempool_t *mpctx;
	isc_mem_t *mctx;
Michael Graff's avatar
Michael Graff committed
833
	isc_mutex_t *lock;
Michael Graff's avatar
Michael Graff committed
834 835 836 837 838 839 840 841

	REQUIRE(mpctxp != NULL);
	mpctx = *mpctxp;
	REQUIRE(VALID_MEMPOOL(mpctx));
	REQUIRE(mpctx->allocated == 0);

	mctx = mpctx->mctx;

Michael Graff's avatar
Michael Graff committed
842 843 844 845 846
	lock = mpctx->lock;

	if (lock != NULL)
		LOCK(lock);

Michael Graff's avatar
Michael Graff committed
847 848 849 850 851 852 853 854 855 856 857 858 859 860
	LOCK(&mctx->lock);

	/*
	 * Return any items on the free list
	 */
	mempool_releaseall(mpctx);

	/*
	 * Remove our linked list entry from the memory context.
	 */
	ISC_LIST_UNLINK(mctx->pools, mpctx, link);
	
	mpctx->magic = 0;

Bob Halley's avatar
Bob Halley committed
861
	mem_putunlocked(mpctx->mctx, mpctx, sizeof(isc_mempool_t));
Michael Graff's avatar
Michael Graff committed
862 863 864

	UNLOCK(&mctx->lock);

Michael Graff's avatar
Michael Graff committed
865 866 867
	if (lock != NULL)
		UNLOCK(lock);

Michael Graff's avatar
Michael Graff committed
868 869 870
	*mpctxp = NULL;
}

Michael Graff's avatar
Michael Graff committed
871 872 873 874 875 876 877 878 879 880
void
isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock)
{
	REQUIRE(VALID_MEMPOOL(mpctx));
	REQUIRE(mpctx->lock == NULL);
	REQUIRE(lock != NULL);

	mpctx->lock = lock;
}

Michael Graff's avatar
Michael Graff committed
881 882 883 884 885 886 887 888 889 890 891
void *
__isc_mempool_get(isc_mempool_t *mpctx)
{
	element *item;
	isc_mem_t *mctx;
	unsigned int i;

	REQUIRE(VALID_MEMPOOL(mpctx));

	mctx = mpctx->mctx;

Michael Graff's avatar
Michael Graff committed
892 893 894
	if (mpctx->lock != NULL)
		LOCK(mpctx->lock);

Michael Graff's avatar
Michael Graff committed
895 896 897
	/*
	 * Don't let the caller go over quota
	 */
Michael Graff's avatar
Michael Graff committed
898 899 900 901
	if (mpctx->allocated >= mpctx->maxalloc) {
		item = NULL;
		goto out;
	}
Michael Graff's avatar
Michael Graff committed
902 903 904 905 906 907 908 909 910 911 912

	/*
	 * if we have a free list item, return the first here
	 */
	item = mpctx->items;
	if (item != NULL) {
		mpctx->items = item->next;
		INSIST(mpctx->freecount > 0);
		mpctx->freecount--;
		mpctx->gets++;
		mpctx->allocated++;
Michael Graff's avatar
Michael Graff committed
913
		goto out;
Michael Graff's avatar
Michael Graff committed
914 915 916 917 918 919 920 921
	}

	/*
	 * We need to dip into the well.  Lock the memory context here and
	 * fill up our free list.
	 */
	LOCK(&mctx->lock);
	for (i = 0 ; i < mpctx->fillcount ; i++) {
Bob Halley's avatar
Bob Halley committed
922
		item = mem_getunlocked(mctx, mpctx->size);
Michael Graff's avatar
Michael Graff committed
923 924 925 926 927 928 929 930 931 932 933 934 935
		if (item == NULL)
			break;
		item->next = mpctx->items;
		mpctx->items = item;
		mpctx->freecount++;
	}
	UNLOCK(&mctx->lock);

	/*
	 * If we didn't get any items, return NULL.
	 */
	item = mpctx->items;
	if (item == NULL)
Michael Graff's avatar
Michael Graff committed
936
		goto out;
Michael Graff's avatar
Michael Graff committed
937 938 939 940 941

	mpctx->items = item->next;
	mpctx->freecount--;
	mpctx->gets++;
	mpctx->allocated++;
Michael Graff's avatar
Michael Graff committed
942 943 944 945 946

 out:
	if (mpctx->lock != NULL)
		UNLOCK(mpctx->lock);

Michael Graff's avatar
Michael Graff committed
947 948 949 950 951 952 953 954 955 956 957 958 959 960
	return (item);
}

void
__isc_mempool_put(isc_mempool_t *mpctx, void *mem)
{
	isc_mem_t *mctx;
	element *item;

	REQUIRE(VALID_MEMPOOL(mpctx));
	REQUIRE(mem != NULL);

	mctx = mpctx->mctx;

Michael Graff's avatar
Michael Graff committed
961 962 963
	if (mpctx->lock != NULL)
		LOCK(mpctx->lock);

Michael Graff's avatar
Michael Graff committed
964 965 966 967 968 969 970
	INSIST(mpctx->allocated > 0);
	mpctx->allocated--;

	/*
	 * If our free list is full, return this to the mctx directly.
	 */
	if (mpctx->freecount >= mpctx->freemax) {
Bob Halley's avatar
Bob Halley committed
971
		__isc_mem_put(mctx, mem, mpctx->size);
Michael Graff's avatar
Michael Graff committed
972 973
		if (mpctx->lock != NULL)
			UNLOCK(mpctx->lock);
Michael Graff's avatar
Michael Graff committed
974 975 976 977 978 979 980 981 982 983
		return;
	}

	/*
	 * Otherwise, attach it to our free list and bump the counter.
	 */
	mpctx->freecount++;
	item = (element *)mem;
	item->next = mpctx->items;
	mpctx->items = item;
Michael Graff's avatar
Michael Graff committed
984 985 986

	if (mpctx->lock != NULL)
		UNLOCK(mpctx->lock);
Michael Graff's avatar
Michael Graff committed
987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
}

void *
__isc_mempool_getdebug(isc_mempool_t *mpctx,
		       const char *file, int line)
{
	void *ptr;

	ptr = __isc_mempool_get(mpctx);
	fprintf(stderr, "%s:%d: mempool_get(%p) -> %p\n", file, line,
		mpctx, ptr);

	return (ptr);
}

void
__isc_mempool_putdebug(isc_mempool_t *mpctx, void *ptr,
		       const char *file, int line)
{
	fprintf(stderr, "%s:%d: mempool_put(%p, %p)\n", file, line, 
		mpctx, ptr);
	__isc_mempool_put(mpctx, ptr);
}

/*
 * Quotas
 */

void
isc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit)
{
	REQUIRE(VALID_MEMPOOL(mpctx));

Michael Graff's avatar
Michael Graff committed
1020 1021 1022
	if (mpctx->lock != NULL)
		LOCK(mpctx->lock);

Michael Graff's avatar
Michael Graff committed
1023
	mpctx->freemax = limit;
Michael Graff's avatar
Michael Graff committed
1024 1025 1026

	if (mpctx->lock != NULL)
		UNLOCK(mpctx->lock);
Michael Graff's avatar
Michael Graff committed
1027 1028 1029 1030 1031
}

unsigned int
isc_mempool_getfreemax(isc_mempool_t *mpctx)
{
Michael Graff's avatar
Michael Graff committed
1032 1033
	unsigned int freemax;

Michael Graff's avatar
Michael Graff committed
1034 1035
	REQUIRE(VALID_MEMPOOL(mpctx));

Michael Graff's avatar
Michael Graff committed
1036 1037 1038 1039 1040 1041 1042 1043 1044
	if (mpctx->lock != NULL)
		LOCK(mpctx->lock);

	freemax = mpctx->freemax;

	if (mpctx->lock != NULL)
		UNLOCK(mpctx->lock);

	return (freemax);
Michael Graff's avatar
Michael Graff committed
1045 1046 1047 1048 1049
}

unsigned int
isc_mempool_getfreecount(isc_mempool_t *mpctx)
{
Michael Graff's avatar
Michael Graff committed
1050 1051
	unsigned int freecount;

Michael Graff's avatar
Michael Graff committed
1052 1053
	REQUIRE(VALID_MEMPOOL(mpctx));

Michael Graff's avatar
Michael Graff committed
1054 1055 1056 1057 1058 1059 1060 1061 1062
	if (mpctx->lock != NULL)
		LOCK(mpctx->lock);

	freecount = mpctx->freecount;

	if (mpctx->lock != NULL)
		UNLOCK(mpctx->lock);

	return (freecount);
Michael Graff's avatar
Michael Graff committed
1063 1064 1065 1066 1067 1068 1069 1070 1071
}

void
isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit)
{
	REQUIRE(limit > 0);

	REQUIRE(VALID_MEMPOOL(mpctx));

Michael Graff's avatar
Michael Graff committed
1072 1073 1074
	if (mpctx->lock != NULL)
		LOCK(mpctx->lock);

Michael Graff's avatar
Michael Graff committed
1075
	mpctx->maxalloc = limit;
Michael Graff's avatar
Michael Graff committed
1076 1077 1078

	if (mpctx->lock != NULL)
		UNLOCK(mpctx->lock);
Michael Graff's avatar
Michael Graff committed
1079 1080 1081 1082 1083
}

unsigned int
isc_mempool_getmaxalloc(isc_mempool_t *mpctx)
{
Michael Graff's avatar
Michael Graff committed
1084 1085
	unsigned int maxalloc;

Michael Graff's avatar
Michael Graff committed
1086 1087
	REQUIRE(VALID_MEMPOOL(mpctx));

Michael Graff's avatar
Michael Graff committed
1088 1089 1090 1091 1092 1093 1094 1095 1096
	if (mpctx->lock != NULL)
		LOCK(mpctx->lock);

	maxalloc = mpctx->maxalloc;

	if (mpctx->lock != NULL)
		UNLOCK(mpctx->lock);

	return (maxalloc);
Michael Graff's avatar
Michael Graff committed
1097 1098 1099 1100 1101
}

unsigned int
isc_mempool_getallocated(isc_mempool_t *mpctx)
{
Michael Graff's avatar
Michael Graff committed
1102 1103
	unsigned int allocated;

Michael Graff's avatar
Michael Graff committed
1104 1105
	REQUIRE(VALID_MEMPOOL(mpctx));

Michael Graff's avatar
Michael Graff committed
1106 1107 1108 1109 1110 1111 1112 1113 1114
	if (mpctx->lock != NULL)
		LOCK(mpctx->lock);

	allocated = mpctx->allocated;

	if (mpctx->lock != NULL)
		UNLOCK(mpctx->lock);

	return (allocated);
Michael Graff's avatar
Michael Graff committed
1115 1116 1117 1118 1119 1120 1121 1122
}

void
isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit)
{
	REQUIRE(limit > 0);
	REQUIRE(VALID_MEMPOOL(mpctx));

Michael Graff's avatar
Michael Graff committed
1123 1124 1125
	if (mpctx->lock != NULL)
		LOCK(mpctx->lock);

Michael Graff's avatar
Michael Graff committed
1126
	mpctx->fillcount = limit;
Michael Graff's avatar
Michael Graff committed
1127 1128 1129

	if (mpctx->lock != NULL)
		UNLOCK(mpctx->lock);
Michael Graff's avatar
Michael Graff committed
1130 1131 1132 1133 1134
}

unsigned int
isc_mempool_getfillcount(isc_mempool_t *mpctx)
{
Michael Graff's avatar
Michael Graff committed
1135 1136
	unsigned int fillcount;

Michael Graff's avatar
Michael Graff committed
1137