mem.c revision 6fda1577669dca9e0d8e4832e407bac34cc12de6
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Copyright (C) 1997-2000 Internet Software Consortium.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Permission to use, copy, modify, and distribute this software for any
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * purpose with or without fee is hereby granted, provided that the above
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * copyright notice and this permission notice appear in all copies.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson/* $Id: mem.c,v 1.73 2000/12/07 20:15:57 marka Exp $ */
d60f5b9bc8c1e1f7ddebc6c7834f7550a8e8be6fBob Halley * Constants.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson#define NUM_BASIC_BLOCKS 64 /* must be > 1 */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson#define FLARG , const char *file, int line
8803b0510877fd08044542edbb55e2be72fae36fAndreas Gustafssontypedef struct {
8803b0510877fd08044542edbb55e2be72fae36fAndreas Gustafsson * This structure must be ALIGNMENT_SIZE bytes.
8803b0510877fd08044542edbb55e2be72fae36fAndreas Gustafsson unsigned long gets;
8803b0510877fd08044542edbb55e2be72fae36fAndreas Gustafsson unsigned long blocks;
8803b0510877fd08044542edbb55e2be72fae36fAndreas Gustafsson#define VALID_CONTEXT(c) ((c) != NULL && (c)->magic == MEM_MAGIC)
8803b0510877fd08044542edbb55e2be72fae36fAndreas Gustafsson unsigned char ** basic_table;
8803b0510877fd08044542edbb55e2be72fae36fAndreas Gustafsson unsigned char * lowest;
8803b0510877fd08044542edbb55e2be72fae36fAndreas Gustafsson unsigned char * highest;
8803b0510877fd08044542edbb55e2be72fae36fAndreas Gustafsson#define MEMPOOL_MAGIC 0x4D454d70U /* MEMp. */
8803b0510877fd08044542edbb55e2be72fae36fAndreas Gustafsson#define VALID_MEMPOOL(c) ((c) != NULL && (c)->magic == MEMPOOL_MAGIC)
8803b0510877fd08044542edbb55e2be72fae36fAndreas Gustafsson /* always unlocked */
8803b0510877fd08044542edbb55e2be72fae36fAndreas Gustafsson isc_mem_t *mctx; /* our memory context */
f4c0131a46ea183238027ef9c3400cc6079b8b85Andreas Gustafsson /* locked via the memory context's lock */
f4c0131a46ea183238027ef9c3400cc6079b8b85Andreas Gustafsson ISC_LINK(isc_mempool_t) link; /* next pool in this mem context */
f4c0131a46ea183238027ef9c3400cc6079b8b85Andreas Gustafsson /* optionally locked from here down */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson element *items; /* low water item list */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson size_t size; /* size of each item on this pool */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson unsigned int maxalloc; /* max number of items allowed */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson unsigned int allocated; /* # of items currently given out */
581db30788a4920ba8558287a0dccf3c1a210c5aAndreas Gustafsson unsigned int freecount; /* # of items on reserved list */
581db30788a4920ba8558287a0dccf3c1a210c5aAndreas Gustafsson unsigned int freemax; /* # of items allowed on free list */
581db30788a4920ba8558287a0dccf3c1a210c5aAndreas Gustafsson unsigned int fillcount; /* # of items to fetch on each fill */
581db30788a4920ba8558287a0dccf3c1a210c5aAndreas Gustafsson /* Stats only. */
581db30788a4920ba8558287a0dccf3c1a210c5aAndreas Gustafsson unsigned int gets; /* # of requests to this pool */
581db30788a4920ba8558287a0dccf3c1a210c5aAndreas Gustafsson /* Debugging only. */
581db30788a4920ba8558287a0dccf3c1a210c5aAndreas Gustafsson char name[16]; /* printed name in stats reports */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Private Inline-able.
581db30788a4920ba8558287a0dccf3c1a210c5aAndreas Gustafsson#define ADD_TRACE(a, b, c, d, e)
581db30788a4920ba8558287a0dccf3c1a210c5aAndreas Gustafsson#define DELETE_TRACE(a, b, c, d, e)
581db30788a4920ba8558287a0dccf3c1a210c5aAndreas Gustafsson#define ADD_TRACE(a, b, c, d, e) add_trace_entry(a, b, c, d, e)
581db30788a4920ba8558287a0dccf3c1a210c5aAndreas Gustafsson#define DELETE_TRACE(a, b, c, d, e) delete_trace_entry(a, b, c, d, e)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson#define MEM_TRACE ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson#define MEM_RECORD ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0)
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * mctx must be locked.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic inline void
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonadd_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson unsigned int i;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson "add %p size %u "
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson "file %s line %u mctx %p\n"),
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson for (i = 0 ; i < DEBUGLIST_COUNT ; i++) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson for (i = 1 ; i < DEBUGLIST_COUNT ; i++) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ISC_LIST_PREPEND(mctx->debuglist, dl, link);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic inline void
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssondelete_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson unsigned int i;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson "del %p size %u "
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson "file %s line %u mctx %p\n"),
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson for (i = 0 ; i < DEBUGLIST_COUNT ; i++) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * If we get here, we didn't find the item on the list. We're
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson#endif /* ISC_MEM_TRACKLINES */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * round down to ALIGNMENT_SIZE
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Round up the result in order to get a size big
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * enough to satisfy the request and be aligned on ALIGNMENT_SIZE
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * byte boundaries.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic inline void
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonsplit(isc_mem_t *ctx, size_t size, size_t new_size) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson unsigned char *ptr;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Unlink a frag of size 'size'.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ptr = (unsigned char *)ctx->freelists[size];
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ctx->freelists[size] = ctx->freelists[size]->next;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Create a frag of size 'new_size' and link it in.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ((element *)ptr)->next = ctx->freelists[new_size];
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ctx->freelists[new_size] = (element *)ptr;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Create a frag of size 'size - new_size' and link it in.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ((element *)ptr)->next = ctx->freelists[remaining_size];
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ctx->freelists[remaining_size] = (element *)ptr;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssontry_split(isc_mem_t *ctx, size_t new_size) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Try splitting a frag that's at least twice as big as the size
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * No luck. Try splitting any frag bigger than the size we need.
732e0731dec1922747bb3b3147cf2c3d16b22eaaBob Halley unsigned char **table;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* Require: we hold the context lock. */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Did we hit the quota for this context?
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson increment = NUM_BASIC_BLOCKS * ctx->mem_target;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (ctx->quota != 0 && ctx->total + increment > ctx->quota)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson INSIST(ctx->basic_table_count <= ctx->basic_table_size);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (ctx->basic_table_count == ctx->basic_table_size) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson table_size = ctx->basic_table_size + TABLE_INCREMENT;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson table_size * sizeof (unsigned char *));
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson sizeof (unsigned char *));
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson (ctx->memfree)(ctx->arg, ctx->basic_table);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson new = (ctx->memalloc)(ctx->arg, NUM_BASIC_BLOCKS * ctx->mem_target);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ctx->basic_table[ctx->basic_table_count] = new;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson for (i = 0; i < (NUM_BASIC_BLOCKS - 1); i++) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ((element *)curr)->next = (element *)next;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * curr is now pointing at the last block in the
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson last = first + NUM_BASIC_BLOCKS * ctx->mem_target - 1;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (first < ctx->lowest || ctx->lowest == NULL)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonmore_frags(isc_mem_t *ctx, size_t new_size) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Try to get more fragments by chopping up a basic block.
f4c0131a46ea183238027ef9c3400cc6079b8b85Andreas Gustafsson * We can't get more memory from the OS, or we've
f4c0131a46ea183238027ef9c3400cc6079b8b85Andreas Gustafsson * hit the quota for this context.
f4c0131a46ea183238027ef9c3400cc6079b8b85Andreas Gustafsson * XXXRTH "At quota" notification here.
f4c0131a46ea183238027ef9c3400cc6079b8b85Andreas Gustafsson * Maybe we can split one of our existing
f4c0131a46ea183238027ef9c3400cc6079b8b85Andreas Gustafsson ctx->basic_blocks = ctx->basic_blocks->next;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Set up a linked-list of blocks of size
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ((element *)curr)->next = (element *)next;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Add the remaining fragment of the basic block to a free list.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ((element *)next)->next = ctx->freelists[total_size];
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ctx->freelists[total_size] = (element *)next;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * curr is now pointing at the last block in the
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic inline void *
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonmem_getunlocked(isc_mem_t *ctx, size_t size) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (size >= ctx->max_size || new_size >= ctx->max_size) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * memget() was called on something beyond our upper limit.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (ctx->quota != 0 && ctx->total + size > ctx->quota) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * If we don't set new_size to size, then the
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * ISC_MEM_FILL code might write over bytes we
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * If there are no blocks in the free list for this size, get a chunk
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * of memory and then break it up into "new_size"-sized blocks, adding
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * them to the free list.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (ctx->freelists[new_size] == NULL && !more_frags(ctx, new_size))
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * The free list uses the "rounded-up" size "new_size".
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ctx->freelists[new_size] = ctx->freelists[new_size]->next;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * The stats[] uses the _actual_ "size" requested by the
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * caller, with the caveat (in the code above) that "size" >= the
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * max. size (max_size) ends up getting recorded as a call to
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson memset(ret, 0xbe, new_size); /* Mnemonic for "beef". */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic inline void
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssoncheck_overrun(void *mem, size_t size, size_t new_size) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson unsigned char *cp;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonstatic inline void
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonmem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (size == ctx->max_size || new_size >= ctx->max_size) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * memput() called on something beyond our upper limit.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson memset(mem, 0xde, size); /* Mnemonic for "dead". */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson INSIST(ctx->stats[ctx->max_size].gets != 0);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson memset(mem, 0xde, new_size); /* Mnemonic for "dead". */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * The free list uses the "rounded-up" size "new_size".
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ((element *)mem)->next = ctx->freelists[new_size];
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ctx->freelists[new_size] = (element *)mem;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * The stats[] uses the _actual_ "size" requested by the
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * caller, with the caveat (in the code above) that "size" >= the
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * max. size (max_size) ends up getting recorded as a call to
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssondefault_memalloc(void *arg, size_t size) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonisc_mem_createx(size_t init_max_size, size_t target_size,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ctx->freelists = (memalloc)(arg, ctx->max_size * sizeof (element *));
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson (ctx->max_size+1) * sizeof (struct stats));
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof (struct stats));
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (isc_mutex_init(&ctx->lock) != ISC_R_SUCCESS) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson "isc_mutex_init() %s",
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonisc_mem_create(size_t init_max_size, size_t target_size,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson return (isc_mem_createx(init_max_size, target_size,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson unsigned int i;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson ISC_LIST_UNLINK(ctx->debuglist, dl, link);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson#if 0 /* XXX brister debugging */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson for (i = 0; i < ctx->basic_table_count; i++)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson for (i = 0; i < ctx->basic_table_count; i++)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson (ctx->memfree)(ctx->arg, ctx->basic_table[i]);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson (ctx->memfree)(ctx->arg, ctx->freelists);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson (ctx->memfree)(ctx->arg, ctx->basic_table);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonisc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson REQUIRE(targetp != NULL && *targetp == NULL);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * isc_mem_putanddetach() is the equivalent of:
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * mctx = NULL;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * isc_mem_attach(ptr->mctx, &mctx);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * isc_mem_detach(&ptr->mctx);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * isc_mem_put(mctx, ptr, sizeof(*ptr);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * isc_mem_detach(&mctx);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonisc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Must be before mem_putunlocked() as ctxp is usually within
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * [ptr..ptr+size).
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson DELETE_TRACE(ctx, ptr, size, file, line);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * This routine provides legacy support for callers who use mctxs
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonisc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson res = isc_ondestroy_register(&ctx->ondestroy, task, event);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonisc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (ctx->hi_water != 0 && !ctx->hi_called &&
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* XXX remove */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson fprintf(stderr,"inuse %u, total %u\n", ctx->inuse, ctx->total);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* XXX remove */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson fprintf(stderr, "%s water(%p, ISC_MEM_HIWATER)\n",
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson (ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonisc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson DELETE_TRACE(ctx, ptr, size, file, line);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson if (ctx->hi_called && ctx->inuse < ctx->lo_water) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* XXX remove */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson fprintf(stderr,"inuse %u, total %u\n", ctx->inuse, ctx->total);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson /* XXX remove */
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson fprintf(stderr, "%s water(%p,ISC_MEM_LOWATER)\n",
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson (ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson for (i = 0; i < ctx->max_size; i += ALIGNMENT_SIZE) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Print the stats[] on the stream "out" with suitable formatting.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafssonisc_mem_stats(isc_mem_t *ctx, FILE *out) {
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson const struct stats *s;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson fprintf(out, "%s%5lu: %11lu gets, %11lu rem",
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson (unsigned long) i, s->totalgets, s->gets);
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * Note that since a pool can be locked now, these stats might be
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * somewhat off if the pool is in active use at the time the stats
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * are dumped. The link fields are protected by the isc_mem_t's
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * lock, however, so walking this list and extracting integers from
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson * stats fields is always safe.
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson fprintf(out, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson "[Pool statistics]\n"));
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson fprintf(out, "%15s %10s %10s %10s %10s %10s %10s %10s %1s\n",
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
c6e66777242752532a094561fc728233cab9bc2fAndreas Gustafsson isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
c6e66777242752532a094561fc728233cab9bc2fAndreas Gustafsson isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
c6e66777242752532a094561fc728233cab9bc2fAndreas Gustafsson isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
c6e66777242752532a094561fc728233cab9bc2fAndreas Gustafsson isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
c6e66777242752532a094561fc728233cab9bc2fAndreas Gustafsson isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
c6e66777242752532a094561fc728233cab9bc2fAndreas Gustafsson fprintf(out, "%15s %10lu %10u %10u %10u %10u %10u %10u %s\n",
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson pool->name, (unsigned long) pool->size, pool->maxalloc,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson pool->allocated, pool->freecount, pool->freemax,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson unsigned int i;
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson fprintf(out, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson "DUMP OF ALL OUTSTANDING "
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson "MEMORY ALLOCATIONS\n"));
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson fprintf(out, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson "\tNone.\n"));
4cd3d6df39927315e3fadc07a8da3788175f4195Andreas Gustafsson for (i = 0 ; i < DEBUGLIST_COUNT ; i++)
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mem_valid(isc_mem_t *ctx, void *ptr) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson if (ctx->lowest != NULL && cp >= ctx->lowest && cp <= ctx->highest)
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * Replacements for malloc() and free() -- they implicitly remember the
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * size of the object allocated (with some additional overhead).
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson si = isc__mem_allocateunlocked(ctx, size);
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson ADD_TRACE(ctx, si, si[-1].u.size, file, line);
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc__mem_free(isc_mem_t *ctx, void *ptr FLARG) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson DELETE_TRACE(ctx, ptr, si->u.size, file, line);
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * Other useful things.
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson ns = isc__mem_allocate(mctx, len + 1 FLARG_PASS);
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mem_setsplit(isc_mem_t *ctx, isc_boolean_t flag) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mem_setquota(isc_mem_t *ctx, size_t quota) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mem_setwater(isc_mem_t *ctx, isc_mem_water_t water, void *water_arg,
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * Memory pool stuff
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * Free all but "n" items from the pool's free list. If n == 0, all items
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * will be returned to the mctx.
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonmempool_release(isc_mempool_t *mpctx, unsigned int n) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * All remaining items are to be freed. Lock the context once,
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * free them all, and unlock the context.
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson mem_putunlocked(mctx, item, mpctx->size);
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * Release all items on the free list. No locking is done, the memory
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * context must be locked, and the pool if needed.
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonmempool_releaseall(isc_mempool_t *mpctx) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson mem_putunlocked(mctx, item, mpctx->size);
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson REQUIRE(mpctxp != NULL && *mpctxp == NULL);
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * Allocate space for this pool, initialize values, and if all works
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * well, attach to the memory context.
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson mpctx = mem_getunlocked(mctx, sizeof(isc_mempool_t));
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson ISC_LIST_INITANDAPPEND(mctx->pools, mpctx, link);
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson memset(mpctx->name, 0, sizeof(mpctx->name));
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson strncpy(mpctx->name, name, sizeof(mpctx->name) - 1);
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mempool_destroy(isc_mempool_t **mpctxp) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * Return any items on the free list
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * Remove our linked list entry from the memory context.
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson ISC_LIST_UNLINK(mctx->pools, mpctx, link);
8803b0510877fd08044542edbb55e2be72fae36fAndreas Gustafsson mem_putunlocked(mpctx->mctx, mpctx, sizeof(isc_mempool_t));
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc__mempool_get(isc_mempool_t *mpctx FLARG) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson unsigned int i;
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * Don't let the caller go over quota
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson if (mpctx->allocated >= mpctx->maxalloc) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * if we have a free list item, return the first here
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * We need to dip into the well. Lock the memory context here and
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * fill up our free list.
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson for (i = 0 ; i < mpctx->fillcount ; i++) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson item = mem_getunlocked(mctx, mpctx->size);
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * If we didn't get any items, return NULL.
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson ADD_TRACE(mctx, item, mpctx->size, file, line);
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson DELETE_TRACE(mctx, mem, mpctx->size, file, line);
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * If our free list is full, return this to the mctx directly.
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson if (mpctx->freecount >= mpctx->freemax) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafsson * Otherwise, attach it to our free list and bump the counter.
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mempool_setfreemax(isc_mempool_t *mpctx, unsigned int limit) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mempool_getfreemax(isc_mempool_t *mpctx) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mempool_getfreecount(isc_mempool_t *mpctx) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mempool_getmaxalloc(isc_mempool_t *mpctx) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mempool_getallocated(isc_mempool_t *mpctx) {
b2c71d98dfc4dab5c6b8c8f39cf8fed3d899e94cAndreas Gustafssonisc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) {