mem.c revision 92f9189aeec4ee6385700dbd7c6bed9cabd2e182
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * Copyright (C) 1997-2000 Internet Software Consortium.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * Permission to use, copy, modify, and distribute this software for any
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * purpose with or without fee is hereby granted, provided that the above
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * copyright notice and this permission notice appear in all copies.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
ab023a65562e62b85a824509d829b6fad87e00b1Rob Austein/* $Id: mem.c,v 1.71 2000/12/06 20:34:34 tale Exp $ */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington#define NUM_BASIC_BLOCKS 64 /* must be > 1 */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtontypedef struct {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * This structure must be ALIGNMENT_SIZE bytes.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington unsigned long gets;
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington unsigned long blocks;
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington#define VALID_CONTEXT(c) ((c) != NULL && (c)->magic == MEM_MAGIC)
571688b02f955f6304649866e768b1f81739cbedBrian Wellington unsigned char ** basic_table;
571688b02f955f6304649866e768b1f81739cbedBrian Wellington unsigned char * lowest;
571688b02f955f6304649866e768b1f81739cbedBrian Wellington unsigned char * highest;
e2fd12f3a020ca8c5de168a44fb72e339cdaa3e9Brian Wellington#define MEMPOOL_MAGIC 0x4D454d70U /* MEMp. */
23f64ea0dcd7f5b7094ae6ade2a002fb7dde1466Brian Wellington#define VALID_MEMPOOL(c) ((c) != NULL && (c)->magic == MEMPOOL_MAGIC)
23f64ea0dcd7f5b7094ae6ade2a002fb7dde1466Brian Wellington /* always unlocked */
23f64ea0dcd7f5b7094ae6ade2a002fb7dde1466Brian Wellington /* locked via the memory context's lock */
23f64ea0dcd7f5b7094ae6ade2a002fb7dde1466Brian Wellington ISC_LINK(isc_mempool_t) link; /* next pool in this mem context */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington /* optionally locked from here down */
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington size_t size; /* size of each item on this pool */
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington unsigned int maxalloc; /* max number of items allowed */
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington unsigned int allocated; /* # of items currently given out */
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington unsigned int freecount; /* # of items on reserved list */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington unsigned int freemax; /* # of items allowed on free list */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington unsigned int fillcount; /* # of items to fetch on each fill */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington /* Stats only. */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington unsigned int gets; /* # of requests to this pool */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington /* Debugging only. */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington char name[16]; /* printed name in stats reports */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * Private Inline-able.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington#define ADD_TRACE(a, b, c, d, e)
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington#define DELETE_TRACE(a, b, c, d, e)
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington#define ADD_TRACE(a, b, c, d, e) add_trace_entry(a, b, c, d, e)
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington#define DELETE_TRACE(a, b, c, d, e) delete_trace_entry(a, b, c, d, e)
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington#define MEM_TRACE ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington#define MEM_RECORD ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0)
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * mctx must be locked.
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellingtonstatic inline void
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellingtonadd_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington unsigned int i;
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington "add %p size %u "
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington "file %s line %u mctx %p\n"),
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington for (i = 0 ; i < DEBUGLIST_COUNT ; i++) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington ISC_LIST_PREPEND(mctx->debuglist, dl, link);
77ac297199fc44809d9628558223627c10ae3f31Brian Wellingtonstatic inline void
77ac297199fc44809d9628558223627c10ae3f31Brian Wellingtondelete_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size,
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington unsigned int i;
e2fd12f3a020ca8c5de168a44fb72e339cdaa3e9Brian Wellington fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
e2fd12f3a020ca8c5de168a44fb72e339cdaa3e9Brian Wellington "del %p size %u "
e2fd12f3a020ca8c5de168a44fb72e339cdaa3e9Brian Wellington "file %s line %u mctx %p\n"),
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington for (i = 0 ; i < DEBUGLIST_COUNT ; i++) {
e2fd12f3a020ca8c5de168a44fb72e339cdaa3e9Brian Wellington * If we get here, we didn't find the item on the list. We're
77ac297199fc44809d9628558223627c10ae3f31Brian Wellington#endif /* ISC_MEM_TRACKLINES */
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson * round down to ALIGNMENT_SIZE
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * Round up the result in order to get a size big
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * enough to satisfy the request and be aligned on ALIGNMENT_SIZE
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * byte boundaries.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonstatic inline void
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonsplit(isc_mem_t *ctx, size_t size, size_t new_size) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington unsigned char *ptr;
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * Unlink a frag of size 'size'.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington ptr = (unsigned char *)ctx->freelists[size];
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington ctx->freelists[size] = ctx->freelists[size]->next;
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * Create a frag of size 'new_size' and link it in.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington ((element *)ptr)->next = ctx->freelists[new_size];
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * Create a frag of size 'size - new_size' and link it in.
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson ((element *)ptr)->next = ctx->freelists[remaining_size];
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson ctx->freelists[remaining_size] = (element *)ptr;
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafssontry_split(isc_mem_t *ctx, size_t new_size) {
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson * Try splitting a frag that's at least twice as big as the size
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson * No luck. Try splitting any frag bigger than the size we need.
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson unsigned char **table;
a4c351fcef77fb332e3cb20253fb96556a414a17Brian Wellington /* Require: we hold the context lock. */
a4c351fcef77fb332e3cb20253fb96556a414a17Brian Wellington * Did we hit the quota for this context?
a4c351fcef77fb332e3cb20253fb96556a414a17Brian Wellington increment = NUM_BASIC_BLOCKS * ctx->mem_target;
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington if (ctx->quota != 0 && ctx->total + increment > ctx->quota)
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington INSIST(ctx->basic_table_count <= ctx->basic_table_size);
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson if (ctx->basic_table_count == ctx->basic_table_size) {
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson table_size = ctx->basic_table_size + TABLE_INCREMENT;
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson table_size * sizeof (unsigned char *));
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson sizeof (unsigned char *));
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson (ctx->memfree)(ctx->arg, ctx->basic_table);
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson new = (ctx->memalloc)(ctx->arg, NUM_BASIC_BLOCKS * ctx->mem_target);
229ce407c359b0b641759ba1fc4a5fa2054a44daBrian Wellington ctx->basic_table[ctx->basic_table_count] = new;
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson for (i = 0; i < (NUM_BASIC_BLOCKS - 1); i++) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * curr is now pointing at the last block in the
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson last = first + NUM_BASIC_BLOCKS * ctx->mem_target - 1;
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson if (first < ctx->lowest || ctx->lowest == NULL)
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellingtonmore_frags(isc_mem_t *ctx, size_t new_size) {
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * Try to get more fragments by chopping up a basic block.
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * We can't get more memory from the OS, or we've
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * hit the quota for this context.
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * XXXRTH "At quota" notification here.
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * Maybe we can split one of our existing
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * list frags.
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington ctx->basic_blocks = ctx->basic_blocks->next;
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * Set up a linked-list of blocks of size
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * "new_size".
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * Add the remaining fragment of the basic block to a free list.
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson ((element *)next)->next = ctx->freelists[total_size];
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson ctx->freelists[total_size] = (element *)next;
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson * curr is now pointing at the last block in the
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafssonstatic inline void *
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellingtonmem_getunlocked(isc_mem_t *ctx, size_t size) {
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson if (size >= ctx->max_size || new_size >= ctx->max_size) {
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson * memget() was called on something beyond our upper limit.
307ba34fa07db768c3a899844f248a2c1d7dcc7fAndreas Gustafsson if (ctx->quota != 0 && ctx->total + size > ctx->quota) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * If we don't set new_size to size, then the
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * ISC_MEM_FILL code might write over bytes we
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * If there are no blocks in the free list for this size, get a chunk
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * of memory and then break it up into "new_size"-sized blocks, adding
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * them to the free list.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington if (ctx->freelists[new_size] == NULL && !more_frags(ctx, new_size))
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * The free list uses the "rounded-up" size "new_size".
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington ctx->freelists[new_size] = ctx->freelists[new_size]->next;
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * The stats[] uses the _actual_ "size" requested by the
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * caller, with the caveat (in the code above) that "size" >= the
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * max. size (max_size) ends up getting recorded as a call to
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington memset(ret, 0xbe, new_size); /* Mnemonic for "beef". */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonstatic inline void
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtoncheck_overrun(void *mem, size_t size, size_t new_size) {
5e387b9ce6bafdfadedb5b34e4c33a4404e5d589Brian Wellington unsigned char *cp;
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonstatic inline void
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonmem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington if (size == ctx->max_size || new_size >= ctx->max_size) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * memput() called on something beyond our upper limit.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington memset(mem, 0xde, size); /* Mnemonic for "dead". */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington INSIST(ctx->stats[ctx->max_size].gets != 0);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington memset(mem, 0xde, new_size); /* Mnemonic for "dead". */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * The free list uses the "rounded-up" size "new_size".
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington ((element *)mem)->next = ctx->freelists[new_size];
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * The stats[] uses the _actual_ "size" requested by the
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * caller, with the caveat (in the code above) that "size" >= the
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * max. size (max_size) ends up getting recorded as a call to
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonisc_mem_createx(size_t init_max_size, size_t target_size,
c0d2891f6e08fcf5379dfb9a1bf8fbbb63f1952aMark Andrews isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington ctx->freelists = (memalloc)(arg, ctx->max_size * sizeof (element *));
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington (ctx->max_size+1) * sizeof (struct stats));
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof (struct stats));
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington if (isc_mutex_init(&ctx->lock) != ISC_R_SUCCESS) {
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington "isc_mutex_init() %s",
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
5e387b9ce6bafdfadedb5b34e4c33a4404e5d589Brian Wellingtonisc_mem_create(size_t init_max_size, size_t target_size,
daa73eae708d568d453e6082e0890d35886a9e0fMark Andrews return (isc_mem_createx(init_max_size, target_size,
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington unsigned int i;
a4c351fcef77fb332e3cb20253fb96556a414a17Brian Wellington#if 0 /* XXX brister debugging */
a4c351fcef77fb332e3cb20253fb96556a414a17Brian Wellington for (i = 0; i < ctx->basic_table_count; i++)
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington for (i = 0; i < ctx->basic_table_count; i++)
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington (ctx->memfree)(ctx->arg, ctx->basic_table[i]);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington (ctx->memfree)(ctx->arg, ctx->basic_table);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonisc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington REQUIRE(targetp != NULL && *targetp == NULL);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * isc_mem_putanddetach() is the equivalent of:
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * mctx = NULL;
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * isc_mem_attach(ptr->mctx, &mctx);
7a6f285bc933d08353d2f18290c85def575b6e57Andreas Gustafsson * isc_mem_detach(&ptr->mctx);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * isc_mem_put(mctx, ptr, sizeof(*ptr);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * isc_mem_detach(&mctx);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonisc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * Must be before mem_putunlocked() as ctxp is usually within
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * [ptr..ptr+size).
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * This routine provides legacy support for callers who use mctxs
c302b021cc65cc9a358a9a1cbe48de12364f4cb6Brian Wellingtonisc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) {
c302b021cc65cc9a358a9a1cbe48de12364f4cb6Brian Wellington res = isc_ondestroy_register(&ctx->ondestroy, task, event);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonisc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington if (ctx->hi_water != 0 && !ctx->hi_called &&
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington /* XXX remove */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington fprintf(stderr,"inuse %u, total %u\n", ctx->inuse, ctx->total);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington /* XXX remove */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington fprintf(stderr, "%s water(%p, ISC_MEM_HIWATER)\n",
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington (ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonisc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington if (ctx->hi_called && ctx->inuse < ctx->lo_water) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington /* XXX remove */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington fprintf(stderr,"inuse %u, total %u\n", ctx->inuse, ctx->total);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington /* XXX remove */
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington fprintf(stderr, "%s water(%p,ISC_MEM_LOWATER)\n",
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington (ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington for (i = 0; i < ctx->max_size; i += ALIGNMENT_SIZE) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * Print the stats[] on the stream "out" with suitable formatting.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington const struct stats *s;
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington fprintf(out, "%s%5lu: %11lu gets, %11lu rem",
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * Note that since a pool can be locked now, these stats might be
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * somewhat off if the pool is in active use at the time the stats
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * are dumped. The link fields are protected by the isc_mem_t's
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * lock, however, so walking this list and extracting integers from
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * stats fields is always safe.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington fprintf(out, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington "[Pool statistics]\n"));
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington fprintf(out, "%15s %10s %10s %10s %10s %10s %10s %10s %1s\n",
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington fprintf(out, "%15s %10lu %10u %10u %10u %10u %10u %10u %s\n",
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington pool->name, (unsigned long) pool->size, pool->maxalloc,
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington pool->allocated, pool->freecount, pool->freemax,
23f64ea0dcd7f5b7094ae6ade2a002fb7dde1466Brian Wellington unsigned int i;
23f64ea0dcd7f5b7094ae6ade2a002fb7dde1466Brian Wellington fprintf(out, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
daa73eae708d568d453e6082e0890d35886a9e0fMark Andrews "DUMP OF ALL OUTSTANDING "
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington "MEMORY ALLOCATIONS\n"));
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington fprintf(out, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington "\tNone.\n"));
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington for (i = 0 ; i < DEBUGLIST_COUNT ; i++)
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington "line %u\n"),
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington if (ctx->lowest != NULL && cp >= ctx->lowest && cp <= ctx->highest)
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * Replacements for malloc() and free() -- they implicitly remember the
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * size of the object allocated (with some additional overhead).
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonisc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonisc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington ADD_TRACE(ctx, si, si[-1].u.size, file, line);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonisc__mem_free(isc_mem_t *ctx, void *ptr FLARG) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington DELETE_TRACE(ctx, ptr, si->u.size, file, line);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * Other useful things.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonisc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington ns = isc__mem_allocate(mctx, len + 1 FLARG_PASS);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonisc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonisc_mem_setsplit(isc_mem_t *ctx, isc_boolean_t flag) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonisc_mem_setquota(isc_mem_t *ctx, size_t quota) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonisc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * Memory pool stuff
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * Free all but "n" items from the pool's free list. If n == 0, all items
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * will be returned to the mctx.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonmempool_release(isc_mempool_t *mpctx, unsigned int n) {
f24c135e09214c3843a49fd32ebef2f6a436ba8eBrian Wellington * All remaining items are to be freed. Lock the context once,
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * free them all, and unlock the context.
f24c135e09214c3843a49fd32ebef2f6a436ba8eBrian Wellington * Release all items on the free list. No locking is done, the memory
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * context must be locked, and the pool if needed.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonisc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
78838d3e0cd62423c23de5503910e01884d2104bBrian Wellington REQUIRE(mpctxp != NULL && *mpctxp == NULL);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * Allocate space for this pool, initialize values, and if all works
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * well, attach to the memory context.
a012d6dbfb100390efa7d0d4be64ada0210b09ddBrian Wellington mpctx = mem_getunlocked(mctx, sizeof(isc_mempool_t));
d0eb2cc33c5db3366a16b1cb0abcca6ec7c8ee3cTatuya JINMEI 神明達哉 ISC_LIST_APPENDUNSAFE(mctx->pools, mpctx, link);
a012d6dbfb100390efa7d0d4be64ada0210b09ddBrian Wellingtonisc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington memset(mpctx->name, 0, sizeof(mpctx->name));
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington strncpy(mpctx->name, name, sizeof(mpctx->name) - 1);
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellingtonisc_mempool_destroy(isc_mempool_t **mpctxp) {
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * Return any items on the free list
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * Remove our linked list entry from the memory context.
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington mem_putunlocked(mpctx->mctx, mpctx, sizeof(isc_mempool_t));
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellingtonisc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) {
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellingtonisc__mempool_get(isc_mempool_t *mpctx FLARG) {
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington unsigned int i;
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * Don't let the caller go over quota
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * if we have a free list item, return the first here
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * We need to dip into the well. Lock the memory context here and
60b90a37f41ab7607762d0e9791e79bd19eae4f4Brian Wellington * fill up our free list.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington * If we didn't get any items, return NULL.
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellington ADD_TRACE(mctx, item, mpctx->size, file, line);
033ba09d6df0ac92a736a480b9c3b164b61dccb2Brian Wellingtonisc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
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);