mem.c revision f859f35d857ba99d0fff548db6d568499a58de63
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * Copyright (C) 1997, 1998, 1999 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Permission to use, copy, modify, and distribute this software for any
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * purpose with or without fee is hereby granted, provided that the above
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff * We want this on during development to catch:
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff * 1. some reference after free bugs.
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson * 2. some failure to initalise bugs.
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff * During development it is nice to be able to see names associated with
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein * memory pools.
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson#define NUM_BASIC_BLOCKS 64 /* must be > 1 */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updatertypedef struct {
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencetypedef struct {
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff * This structure must be ALIGNMENT_SIZE bytes.
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater unsigned long gets;
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater unsigned long blocks;
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater#define VALID_CONTEXT(c) ((c) != NULL && (c)->magic == MEM_MAGIC)
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein unsigned char ** basic_table;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson unsigned char * lowest;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson unsigned char * highest;
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater#define MEMPOOL_MAGIC 0x4D454d70U /* MEMp. */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater#define VALID_MEMPOOL(c) ((c) != NULL && (c)->magic == MEMPOOL_MAGIC)
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater /* always unlocked */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater /* locked via the memory context's lock */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater ISC_LINK(isc_mempool_t) link; /* next pool in this mem context */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater /* optionally locked from here down */
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff size_t size; /* size of each item on this pool */
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff unsigned int maxalloc; /* max number of items allowed */
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff unsigned int allocated; /* # of items currently given out */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater unsigned int freecount; /* # of items on reserved list */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater unsigned int freemax; /* # of items allowed on free list */
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff unsigned int fillcount; /* # of items to fetch on each fill */
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson /* Stats only. */
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson unsigned int gets; /* # of requests to this pool */
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson /* Debugging only. */
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson char name[16]; /* printed name in stats reports */
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonstatic inline void mem_putunlocked(isc_mem_t *, void *, size_t);
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonstatic inline void * mem_getunlocked(isc_mem_t *, size_t);
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews * Private Inline-able.
4c1817c29c78d533eae9f4bdf8c9b4d5c90ebfdbMark Andrews * Round up the result in order to get a size big
4c1817c29c78d533eae9f4bdf8c9b4d5c90ebfdbMark Andrews * enough to satisfy the request and be aligned on ALIGNMENT_SIZE
4c1817c29c78d533eae9f4bdf8c9b4d5c90ebfdbMark Andrews * byte boundaries.
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updaterisc_mem_createx(size_t init_max_size, size_t target_size,
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater ctx->freelists = (memalloc)(arg, ctx->max_size * sizeof (element *));
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater (ctx->max_size+1) * sizeof (struct stats));
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof (struct stats));
c20ffa38dee7efa0dc01822d4bac5e41729b9b61Brian Wellington if (isc_mutex_init(&ctx->lock) != ISC_R_SUCCESS) {
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater "isc_mutex_init() failed");
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updaterisc_mem_create(size_t init_max_size, size_t target_size,
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater return (isc_mem_createx(init_max_size, target_size,
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater unsigned int i;
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater#if 0 /* XXX brister debugging */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater for (i = 0; i < ctx->basic_table_count; i++)
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater for (i = 0; i < ctx->basic_table_count; i++)
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater (ctx->memfree)(ctx->arg, ctx->basic_table[i]);
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater (ctx->memfree)(ctx->arg, ctx->basic_table);
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater unsigned char **table;
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater /* Require: we hold the context lock. */
c20ffa38dee7efa0dc01822d4bac5e41729b9b61Brian Wellington * Did we hit the quota for this context?
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington increment = NUM_BASIC_BLOCKS * ctx->mem_target;
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater if (ctx->quota != 0 && ctx->total + increment > ctx->quota)
7618f0551eb745354ee695907e568b0be1f2c8f5Andreas Gustafsson INSIST(ctx->basic_table_count <= ctx->basic_table_size);
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater if (ctx->basic_table_count == ctx->basic_table_size) {
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater table_size = ctx->basic_table_size + TABLE_INCREMENT;
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson table_size * sizeof (unsigned char *));
ed04318ef686581fc9a20965a5be02abfb4f1bd5Andreas Gustafsson sizeof (unsigned char *));
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater (ctx->memfree)(ctx->arg, ctx->basic_table);
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater new = (ctx->memalloc)(ctx->arg, NUM_BASIC_BLOCKS * ctx->mem_target);
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater ctx->basic_table[ctx->basic_table_count] = new;
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater for (i = 0; i < (NUM_BASIC_BLOCKS - 1); i++) {
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * curr is now pointing at the last block in the
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater last = first + NUM_BASIC_BLOCKS * ctx->mem_target - 1;
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater if (first < ctx->lowest || ctx->lowest == NULL)
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonstatic inline void *
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafssonmem_getunlocked(isc_mem_t *ctx, size_t size)
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater if (size >= ctx->max_size || new_size >= ctx->max_size) {
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater /* memget() was called on something beyond our upper limit. */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater if (ctx->quota != 0 && ctx->total + size > ctx->quota) {
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * If we don't set new_size to size, then the
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * ISC_MEM_FILL code might write over bytes we
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * If there are no blocks in the free list for this size, get a chunk
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * of memory and then break it up into "new_size"-sized blocks, adding
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * them to the free list.
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson ctx->basic_blocks = ctx->basic_blocks->next;
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater /* Set up a linked-list of blocks of size "new_size". */
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson /* curr is now pointing at the last block in the array. */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater /* The free list uses the "rounded-up" size "new_size": */
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellington ctx->freelists[new_size] = ctx->freelists[new_size]->next;
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * The stats[] uses the _actual_ "size" requested by the
f991461dc144794d80ff8d85e430fd8a6e6113f3David Lawrence * caller, with the caveat (in the code above) that "size" >= the
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * max. size (max_size) ends up getting recorded as a call to
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater memset(ret, 0xbe, new_size); /* Mnemonic for "beef". */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater__isc_mem_put(isc_mem_t *ctx, void *mem, size_t size)
f0e246e271f84c6fe960a3c36703a56d1067431cBrian Wellingtonstatic inline void
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updatermem_putunlocked(isc_mem_t *ctx, void *mem, size_t size)
f991461dc144794d80ff8d85e430fd8a6e6113f3David Lawrence if (size == ctx->max_size || new_size >= ctx->max_size) {
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater /* memput() called on something beyond our upper limit */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater memset(mem, 0xde, size); /* Mnemonic for "dead". */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater INSIST(ctx->stats[ctx->max_size].gets != 0);
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater memset(mem, 0xde, new_size); /* Mnemonic for "dead". */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater /* The free list uses the "rounded-up" size "new_size": */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater ((element *)mem)->next = ctx->freelists[new_size];
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater ctx->freelists[new_size] = (element *)mem;
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * The stats[] uses the _actual_ "size" requested by the
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * caller, with the caveat (in the code above) that "size" >= the
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * max. size (max_size) ends up getting recorded as a call to
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater__isc_mem_getdebug(isc_mem_t *ctx, size_t size, const char *file, int line) {
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater fprintf(stderr, "%s:%d: mem_get(%p, %lu) -> %p\n", file, line,
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater__isc_mem_putdebug(isc_mem_t *ctx, void *ptr, size_t size, const char *file,
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson fprintf(stderr, "%s:%d: mem_put(%p, %p, %lu)\n", file, line,
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Print the stats[] on the stream "out" with suitable formatting.
b239c8294a5653d21876d084e0c5b029f6b9fc5dMichael Graff const struct stats *s;
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater fprintf(out, "%s%5d: %11lu gets, %11lu rem",
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * Note that since a pool can be locked now, these stats might be
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * somewhat off if the pool is in active use at the time the stats
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * are dumped. The link fields are protected by the isc_mem_t's
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * lock, however, so walking this list and extracting integers from
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * stats fields is always safe.
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater fprintf(out, "%15s %10s %10s %10s %10s %10s %10s %10s %1s\n",
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater "name", "size", "maxalloc", "allocated", "freecount",
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater fprintf(out, "%15s %10u %10u %10u %10u %10u %10u %10u %s\n",
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater pool->allocated, pool->freecount, pool->freemax,
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater if (ctx->lowest != NULL && cp >= ctx->lowest && cp <= ctx->highest)
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * Replacements for malloc() and free().
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updaterisc_mem_allocate(isc_mem_t *ctx, size_t size) {
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * Other useful things.
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updaterisc_mem_strdup(isc_mem_t *mctx, const char *s) {
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updaterisc_mem_destroy_check(isc_mem_t *mctx, isc_boolean_t flag) {
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updaterisc_mem_setquota(isc_mem_t *ctx, size_t quota) {
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews * Public Legacy.
f991461dc144794d80ff8d85e430fd8a6e6113f3David Lawrencememinit(size_t init_max_size, size_t target_size) {
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater /* need default_context lock here */
9a7d202077fae00fbdca610d8a8d90689e30f331Mark Andrews return (-1);
9a7d202077fae00fbdca610d8a8d90689e30f331Mark Andrews return (isc_mem_create(init_max_size, target_size, &default_context));
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater /* need default_context lock here */
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews if (default_context == NULL && meminit(0, 0) == -1)
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater /* need default_context lock here */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater if (default_context == NULL && meminit(0, 0) == -1)
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater return (__mem_get(default_context, size));
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater /* need default_context lock here */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater__memget_debug(size_t size, const char *file, int line) {
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater fprintf(stderr, "%s:%d: memget(%lu) -> %p\n", file, line,
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater__memput_debug(void *ptr, size_t size, const char *file, int line) {
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater fprintf(stderr, "%s:%d: memput(%p, %lu)\n", file, line,
3a34b87c878990c6303358efd22265c2c5980c65Mark Andrews /* need default_context lock here */
f951f076f3d321c52b824a866caff28ce4f8e06cAndreas Gustafsson return (mem_valid(default_context, ptr));
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater /* need default_context lock here */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater#endif /* ISC_MEMCLUSTER_LEGACY */
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * Memory pool stuff
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * Free all but "n" items from the pool's free list. If n == 0, all items
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * will be returned to the mctx.
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updatermempool_release(isc_mempool_t *mpctx, unsigned int n)
c20ffa38dee7efa0dc01822d4bac5e41729b9b61Brian Wellington * All remaining items are to be freed. Lock the context once,
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * free them all, and unlock the context.
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * Release all items on the free list. No locking is done, the memory
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * context must be locked, and the pool if needed.
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updaterisc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp)
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater REQUIRE(mpctxp != NULL && *mpctxp == NULL);
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * Allocate space for this pool, initialize values, and if all works
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater * well, attach to the memory context.
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater mpctx = mem_getunlocked(mctx, sizeof(isc_mempool_t));
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater ISC_LIST_APPEND(mctx->pools, mpctx, link);
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updaterisc_mempool_setname(isc_mempool_t *mpctx, char *name)
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater memset(mpctx->name, 0, sizeof(mpctx->name));
f172f06ff2e7609dd7d91914a44b4e24cff8bb7aAutomatic Updater strncpy(mpctx->name, name, sizeof(mpctx->name) - 1);
goto out;
goto out;
goto out;
out:
return (item);
void *ptr;
return (ptr);
unsigned int freemax;
return (freemax);
unsigned int freecount;
return (freecount);
unsigned int maxalloc;
return (maxalloc);
unsigned int allocated;
return (allocated);
unsigned int fillcount;
return (fillcount);