mem.c revision 36bcb04af27e050ddc04b2ff37dbeafc84538fd4
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer/*
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Copyright (C) 1997, 1998, 1999, 2000 Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Permission to use, copy, modify, and distribute this software for any
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * purpose with or without fee is hereby granted, provided that the above
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence *
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
15a44745412679c30a6d022733925af70a38b715David Lawrence * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
15a44745412679c30a6d022733925af70a38b715David Lawrence * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
15a44745412679c30a6d022733925af70a38b715David Lawrence * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
15a44745412679c30a6d022733925af70a38b715David Lawrence * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15a44745412679c30a6d022733925af70a38b715David Lawrence * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
15a44745412679c30a6d022733925af70a38b715David Lawrence * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
15a44745412679c30a6d022733925af70a38b715David Lawrence * SOFTWARE.
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
19c8df90f1f23c3df870c1771c89c1acdb15020eMichael Sawyer#include <config.h>
47058d17266420179fa294de6b82d8fb5b918df4Michael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#include <stdio.h>
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#include <stdlib.h>
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#include <stddef.h>
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#include <limits.h>
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
c9defbf4b968e8a61f391246431ac63d0d6a39abMichael Sawyer#include <isc/mem.h>
c9defbf4b968e8a61f391246431ac63d0d6a39abMichael Sawyer#include <isc/ondestroy.h>
c9defbf4b968e8a61f391246431ac63d0d6a39abMichael Sawyer#include <isc/string.h>
c9defbf4b968e8a61f391246431ac63d0d6a39abMichael Sawyer
c9defbf4b968e8a61f391246431ac63d0d6a39abMichael Sawyer#ifndef ISC_SINGLETHREADED
c9defbf4b968e8a61f391246431ac63d0d6a39abMichael Sawyer#include <isc/mutex.h>
c9defbf4b968e8a61f391246431ac63d0d6a39abMichael Sawyer#include <isc/util.h>
c9defbf4b968e8a61f391246431ac63d0d6a39abMichael Sawyer#else
1893b56ef9f5f2bc2a0fbe80d3c6b69df1bdc7c2Michael Sawyer#define LOCK(l)
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#define UNLOCK(l)
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer#endif
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyerboolean isc_mem_debugging = ISC_FALSE;
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer#ifndef ISC_MEM_FILL
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer /*
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer * XXXMPA
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * We want this on during development to catch:
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * 1. some reference after free bugs.
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * 2. some failure to initalise bugs.
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#define ISC_MEM_FILL 1
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#endif
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer#ifndef ISC_MEMPOOL_NAMES
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer/*
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * During development it is nice to be able to see names associated with
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * memory pools.
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#define ISC_MEMPOOL_NAMES 1
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#endif
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer/*
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Constants.
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
1893b56ef9f5f2bc2a0fbe80d3c6b69df1bdc7c2Michael Sawyer#define DEF_MAX_SIZE 1100
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer#define DEF_MEM_TARGET 4096
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#define ALIGNMENT_SIZE 8
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer#define NUM_BASIC_BLOCKS 64 /* must be > 1 */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define TABLE_INCREMENT 1024
6c6a62933dda281cb9193de1d54d4c9e74515f5aMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer/*
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Types.
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyertypedef struct element element;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyerstruct element {
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer element * next;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer};
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyertypedef struct {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /*
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * This structure must be ALIGNMENT_SIZE bytes.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer union {
a5ed46c9fd270775c39770bfd0250a52d374ebf2Michael Sawyer size_t size;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer char bytes[ALIGNMENT_SIZE];
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer } u;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer} size_info;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyerstruct stats {
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer unsigned long gets;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer unsigned long totalgets;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer unsigned long blocks;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer unsigned long freefrags;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer};
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#define MEM_MAGIC 0x4D656d43U /* MemC. */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#define VALID_CONTEXT(c) ((c) != NULL && (c)->magic == MEM_MAGIC)
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyerstruct isc_mem {
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer unsigned int magic;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer isc_ondestroy_t ondestroy;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer isc_mutex_t lock;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer isc_memalloc_t memalloc;
a5ed46c9fd270775c39770bfd0250a52d374ebf2Michael Sawyer isc_memfree_t memfree;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer void * arg;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer size_t max_size;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer size_t mem_target;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer element ** freelists;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer element * basic_blocks;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned char ** basic_table;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int basic_table_count;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence unsigned int basic_table_size;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned char * lowest;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned char * highest;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_boolean_t checkfree;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_boolean_t trysplit;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer struct stats * stats;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int references;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer size_t quota;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer size_t total;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer size_t inuse;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ISC_LIST(isc_mempool_t) pools;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer};
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define MEMPOOL_MAGIC 0x4D454d70U /* MEMp. */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#define VALID_MEMPOOL(c) ((c) != NULL && (c)->magic == MEMPOOL_MAGIC)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerstruct isc_mempool {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /* always unlocked */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int magic; /* magic number */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_mutex_t *lock; /* optional lock */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_mem_t *mctx; /* our memory context */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /* locked via the memory context's lock */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ISC_LINK(isc_mempool_t) link; /* next pool in this mem context */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /* optionally locked from here down */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer element *items; /* low water item list */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer size_t size; /* size of each item on this pool */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int maxalloc; /* max number of items allowed */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int allocated; /* # of items currently given out */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int freecount; /* # of items on reserved list */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int freemax; /* # of items allowed on free list */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int fillcount; /* # of items to fetch on each fill */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /* Stats only. */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int gets; /* # of requests to this pool */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /* Debugging only. */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#if ISC_MEMPOOL_NAMES
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer char name[16]; /* printed name in stats reports */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#endif
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer};
cd720113a2fc8a781d4e33350b8a2b62857b31d8David Lawrence
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer/*
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Private Inline-able.
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer */
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyerstatic inline size_t
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyerquantize(size_t size) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer int temp;
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer /*
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Round up the result in order to get a size big
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * enough to satisfy the request and be aligned on ALIGNMENT_SIZE
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer * byte boundaries.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer if (size == 0)
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer return (ALIGNMENT_SIZE);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer temp = size + (ALIGNMENT_SIZE - 1);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer return (temp - temp % ALIGNMENT_SIZE);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerstatic inline void
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyersplit(isc_mem_t *ctx, size_t size, size_t new_size) {
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer unsigned char *ptr;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer size_t remaining_size;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer /*
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Unlink a frag of size 'size'.
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer ptr = (unsigned char *)ctx->freelists[size];
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer ctx->freelists[size] = ctx->freelists[size]->next;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer ctx->stats[size].freefrags--;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer /*
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Create a frag of size 'new_size' and link it in.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ((element *)ptr)->next = ctx->freelists[new_size];
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer ctx->freelists[new_size] = (element *)ptr;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->stats[new_size].freefrags++;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /*
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Create a frag of size 'size - new_size' and link it in.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer remaining_size = size - new_size;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ptr += new_size;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ((element *)ptr)->next = ctx->freelists[remaining_size];
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer ctx->freelists[remaining_size] = (element *)ptr;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->stats[remaining_size].freefrags++;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyerstatic inline isc_boolean_t
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyertry_split(isc_mem_t *ctx, size_t new_size) {
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer size_t i, doubled_size;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (!ctx->trysplit)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (ISC_FALSE);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer /*
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Try splitting a frag that's at least twice as big as the size
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * we want.
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer doubled_size = new_size * 2;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer for (i = doubled_size;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer i < ctx->max_size;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer i += ALIGNMENT_SIZE) {
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer if (ctx->freelists[i] != NULL) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer split(ctx, i, new_size);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (ISC_TRUE);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /*
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * No luck. Try splitting any frag bigger than the size we need.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer for (i = new_size + ALIGNMENT_SIZE;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer i < doubled_size;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer i += ALIGNMENT_SIZE) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (ctx->freelists[i] != NULL) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer split(ctx, i, new_size);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (ISC_TRUE);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (ISC_FALSE);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerstatic inline isc_boolean_t
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyermore_basic_blocks(isc_mem_t *ctx) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer void *new;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned char *curr, *next;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned char *first, *last;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned char **table;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned int table_size;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer size_t increment;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer int i;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /* Require: we hold the context lock. */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /*
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Did we hit the quota for this context?
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer increment = NUM_BASIC_BLOCKS * ctx->mem_target;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (ctx->quota != 0 && ctx->total + increment > ctx->quota)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (ISC_FALSE);
a5ed46c9fd270775c39770bfd0250a52d374ebf2Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer INSIST(ctx->basic_table_count <= ctx->basic_table_size);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (ctx->basic_table_count == ctx->basic_table_size) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer table_size = ctx->basic_table_size + TABLE_INCREMENT;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer table = (ctx->memalloc)(ctx->arg,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer table_size * sizeof (unsigned char *));
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (table == NULL)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (ISC_FALSE);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (ctx->basic_table_size != 0) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer memcpy(table, ctx->basic_table,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->basic_table_size *
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer sizeof (unsigned char *));
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer (ctx->memfree)(ctx->arg, ctx->basic_table);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->basic_table = table;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->basic_table_size = table_size;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer new = (ctx->memalloc)(ctx->arg, NUM_BASIC_BLOCKS * ctx->mem_target);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (new == NULL)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (ISC_FALSE);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->total += increment;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->basic_table[ctx->basic_table_count] = new;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->basic_table_count++;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer curr = new;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer next = curr + ctx->mem_target;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer for (i = 0; i < (NUM_BASIC_BLOCKS - 1); i++) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ((element *)curr)->next = (element *)next;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer curr = next;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer next += ctx->mem_target;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /*
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * curr is now pointing at the last block in the
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * array.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ((element *)curr)->next = NULL;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer first = new;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer last = first + NUM_BASIC_BLOCKS * ctx->mem_target - 1;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (first < ctx->lowest || ctx->lowest == NULL)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->lowest = first;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (last > ctx->highest)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->highest = last;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->basic_blocks = new;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (ISC_TRUE);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerstatic inline isc_boolean_t
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyermore_frags(isc_mem_t *ctx, size_t new_size) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer int i, frags;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer size_t total_size;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer void *new;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer unsigned char *curr, *next;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /*
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Try to get more fragments by chopping up a basic block.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (ctx->basic_blocks == NULL) {
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence if (!more_basic_blocks(ctx)) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /*
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * We can't get more memory from the OS, or we've
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * hit the quota for this context.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /*
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * XXXRTH "At quota" notification here.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /*
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * Maybe we can split one of our existing
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer * list frags.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer return (try_split(ctx, new_size));
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer total_size = ctx->mem_target;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer new = ctx->basic_blocks;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer ctx->basic_blocks = ctx->basic_blocks->next;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer frags = total_size / new_size;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer ctx->stats[new_size].blocks++;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer ctx->stats[new_size].freefrags += frags;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer /*
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * Set up a linked-list of blocks of size
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * "new_size".
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer curr = new;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer next = curr + new_size;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer for (i = 0; i < (frags - 1); i++) {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ((element *)curr)->next = (element *)next;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer curr = next;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer next += new_size;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer }
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer /*
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * curr is now pointing at the last block in the
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer * array.
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ((element *)curr)->next = NULL;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->freelists[new_size] = new;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer return (ISC_TRUE);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer}
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyerstatic inline void *
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyermem_getunlocked(isc_mem_t *ctx, size_t size) {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer size_t new_size = quantize(size);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer void *ret;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer if (size >= ctx->max_size || new_size >= ctx->max_size) {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer /*
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * memget() was called on something beyond our upper limit.
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer if (ctx->quota != 0 && ctx->total + size > ctx->quota) {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ret = NULL;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer goto done;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer }
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ret = (ctx->memalloc)(ctx->arg, size);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer if (ret != NULL) {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->total += size;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->inuse += size;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->stats[ctx->max_size].gets++;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->stats[ctx->max_size].totalgets++;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer /*
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * If we don't set new_size to size, then the
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * ISC_MEM_FILL code might write over bytes we
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * don't own.
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer new_size = size;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer }
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer goto done;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer }
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer /*
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * If there are no blocks in the free list for this size, get a chunk
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * of memory and then break it up into "new_size"-sized blocks, adding
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * them to the free list.
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer if (ctx->freelists[new_size] == NULL && !more_frags(ctx, new_size))
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer return (NULL);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer /*
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * The free list uses the "rounded-up" size "new_size".
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ret = ctx->freelists[new_size];
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->freelists[new_size] = ctx->freelists[new_size]->next;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer /*
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * The stats[] uses the _actual_ "size" requested by the
a5ed46c9fd270775c39770bfd0250a52d374ebf2Michael Sawyer * caller, with the caveat (in the code above) that "size" >= the
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * max. size (max_size) ends up getting recorded as a call to
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * max_size.
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->stats[size].gets++;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->stats[size].totalgets++;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->stats[new_size].freefrags--;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->inuse += new_size;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer done:
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer#if ISC_MEM_FILL
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer if (ret != NULL)
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer memset(ret, 0xbe, new_size); /* Mnemonic for "beef". */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer#endif
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer return (ret);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer}
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyerstatic inline void
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyermem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer size_t new_size = quantize(size);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer if (size == ctx->max_size || new_size >= ctx->max_size) {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer /*
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * memput() called on something beyond our upper limit.
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer#if ISC_MEM_FILL
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer memset(mem, 0xde, size); /* Mnemonic for "dead". */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer#endif
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer (ctx->memfree)(ctx->arg, mem);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer INSIST(ctx->stats[ctx->max_size].gets != 0);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->stats[ctx->max_size].gets--;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer INSIST(size <= ctx->total);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->inuse -= size;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->total -= size;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer return;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer }
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer#if ISC_MEM_FILL
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer#if ISC_MEM_CHECKOVERRUN
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer check_overrun(mem, size, new_size);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer#endif
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer memset(mem, 0xde, new_size); /* Mnemonic for "dead". */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer#endif
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer /*
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * The free list uses the "rounded-up" size "new_size".
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ((element *)mem)->next = ctx->freelists[new_size];
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence ctx->freelists[new_size] = (element *)mem;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer /*
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * The stats[] uses the _actual_ "size" requested by the
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * caller, with the caveat (in the code above) that "size" >= the
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * max. size (max_size) ends up getting recorded as a call to
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * max_size.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer INSIST(ctx->stats[size].gets != 0);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->stats[size].gets--;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->stats[new_size].freefrags++;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->inuse -= new_size;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer}
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer/*
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer * Private.
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer */
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyerstatic void *
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyerdefault_memalloc(void *arg, size_t size) {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer UNUSED(arg);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer return (malloc(size));
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer}
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyerstatic void
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerdefault_memfree(void *arg, void *ptr) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer UNUSED(arg);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer free(ptr);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer/*
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Public.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc_result_t
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc_mem_createx(size_t init_max_size, size_t target_size,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_mem_t **ctxp)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer{
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_mem_t *ctx;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer REQUIRE(ctxp != NULL && *ctxp == NULL);
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer REQUIRE(memalloc != NULL);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer REQUIRE(memfree != NULL);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer ctx = (memalloc)(arg, sizeof *ctx);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (ctx == NULL)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (ISC_R_NOMEMORY);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (init_max_size == 0)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->max_size = DEF_MAX_SIZE;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer else
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->max_size = init_max_size;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer if (target_size == 0)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->mem_target = DEF_MEM_TARGET;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer else
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->mem_target = target_size;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->memalloc = memalloc;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->memfree = memfree;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->arg = arg;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->freelists = (memalloc)(arg, ctx->max_size * sizeof (element *));
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer if (ctx->freelists == NULL) {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer (memfree)(arg, ctx);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer return (ISC_R_NOMEMORY);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->checkfree = ISC_TRUE;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->trysplit = ISC_FALSE;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer memset(ctx->freelists, 0,
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence ctx->max_size * sizeof (element *));
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->stats = (memalloc)(arg,
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer (ctx->max_size+1) * sizeof (struct stats));
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (ctx->stats == NULL) {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer (memfree)(arg, ctx->freelists);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer (memfree)(arg, ctx);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer return (ISC_R_NOMEMORY);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer }
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof (struct stats));
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->basic_blocks = NULL;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer ctx->basic_table = NULL;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer ctx->basic_table_count = 0;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer ctx->basic_table_size = 0;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->lowest = NULL;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->highest = NULL;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer if (isc_mutex_init(&ctx->lock) != ISC_R_SUCCESS) {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer (memfree)(arg, ctx->stats);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer (memfree)(arg, ctx->freelists);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence (memfree)(arg, ctx);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer UNEXPECTED_ERROR(__FILE__, __LINE__,
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer "isc_mutex_init() failed");
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (ISC_R_UNEXPECTED);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer }
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->references = 1;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->quota = 0;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->total = 0;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->inuse = 0;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ctx->magic = MEM_MAGIC;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer isc_ondestroy_init(&ctx->ondestroy);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer ISC_LIST_INIT(ctx->pools);
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer *ctxp = ctx;
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer return (ISC_R_SUCCESS);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc_result_t
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc_mem_create(size_t init_max_size, size_t target_size,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_mem_t **ctxp)
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer{
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer return (isc_mem_createx(init_max_size, target_size,
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer default_memalloc, default_memfree, NULL,
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer ctxp));
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer}
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyerstatic void
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyerdestroy(isc_mem_t *ctx) {
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer unsigned int i;
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer isc_ondestroy_t ondest;
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->magic = 0;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer INSIST(ISC_LIST_EMPTY(ctx->pools));
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer INSIST(ctx->references == 0);
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer if (ctx->checkfree) {
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer for (i = 0; i <= ctx->max_size; i++)
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer INSIST(ctx->stats[i].gets == 0);
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer }
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer#if 0 /* XXX brister debugging */
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer for (i = 0; i < ctx->basic_table_count; i++)
5564b21be5cf3e7b8f751af268f2c1522c1744e3David Lawrence memset(ctx->basic_table[i], 0x0,
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer NUM_BASIC_BLOCKS * ctx->mem_target);
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer#endif
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer for (i = 0; i < ctx->basic_table_count; i++)
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer (ctx->memfree)(ctx->arg, ctx->basic_table[i]);
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer (ctx->memfree)(ctx->arg, ctx->freelists);
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer (ctx->memfree)(ctx->arg, ctx->stats);
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer (ctx->memfree)(ctx->arg, ctx->basic_table);
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer ondest = ctx->ondestroy;
5564b21be5cf3e7b8f751af268f2c1522c1744e3David Lawrence
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer (void)isc_mutex_destroy(&ctx->lock);
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer (ctx->memfree)(ctx->arg, ctx);
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer isc_ondestroy_notify(&ondest, ctx);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
48674819ebf9176b5d5582ae851e485c324c1159Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyervoid
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer REQUIRE(VALID_CONTEXT(source));
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer REQUIRE(targetp != NULL && *targetp == NULL);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer LOCK(&source->lock);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer source->references++;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer UNLOCK(&source->lock);
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer *targetp = source;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyervoid
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc_mem_detach(isc_mem_t **ctxp) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_mem_t *ctx;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_boolean_t want_destroy = ISC_FALSE;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer REQUIRE(ctxp != NULL);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx = *ctxp;
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer REQUIRE(VALID_CONTEXT(ctx));
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer LOCK(&ctx->lock);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer INSIST(ctx->references > 0);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx->references--;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (ctx->references == 0)
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer want_destroy = ISC_TRUE;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer UNLOCK(&ctx->lock);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (want_destroy)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer destroy(ctx);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer *ctxp = NULL;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyervoid
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc_mem_destroy(isc_mem_t **ctxp) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_mem_t *ctx;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_boolean_t want_destroy = ISC_FALSE;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /*
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * This routine provides legacy support for callers who use mctxs
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * without attaching/detaching.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer REQUIRE(ctxp != NULL);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx = *ctxp;
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer REQUIRE(VALID_CONTEXT(ctx));
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer LOCK(&ctx->lock);
d821f1cd7e97552401296e880e7518c98c9ebea1Michael Sawyer REQUIRE(ctx->references == 1);
f8fec75ee8f429821137aee090f56ab678404a56Michael Sawyer ctx->references--;
6c6a62933dda281cb9193de1d54d4c9e74515f5aMichael Sawyer if (ctx->references == 0)
48674819ebf9176b5d5582ae851e485c324c1159Michael Sawyer want_destroy = ISC_TRUE;
48674819ebf9176b5d5582ae851e485c324c1159Michael Sawyer UNLOCK(&ctx->lock);
48674819ebf9176b5d5582ae851e485c324c1159Michael Sawyer
48674819ebf9176b5d5582ae851e485c324c1159Michael Sawyer if (want_destroy)
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer destroy(ctx);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer *ctxp = NULL;
48674819ebf9176b5d5582ae851e485c324c1159Michael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyerisc_result_t
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyerisc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) {
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer isc_result_t res;
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer LOCK(&ctx->lock);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer res = isc_ondestroy_register(&ctx->ondestroy, task, event);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer UNLOCK(&ctx->lock);
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer return (res);
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer}
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyerisc_result_t
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyerisc_mem_restore(isc_mem_t *ctx) {
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer isc_result_t result;
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer result = isc_mutex_init(&ctx->lock);
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer if (result != ISC_R_SUCCESS)
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer ctx->magic = 0;
cd720113a2fc8a781d4e33350b8a2b62857b31d8David Lawrence
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (result);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyervoid *
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc__mem_get(isc_mem_t *ctx, size_t size) {
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer void *ret;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer REQUIRE(VALID_CONTEXT(ctx));
9fe3676b8490319aa65182f2072cbf5086097979Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer LOCK(&ctx->lock);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ret = mem_getunlocked(ctx, size);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer UNLOCK(&ctx->lock);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (ret);
17747cd5ee98901b435cd2b3019c52937955a981Michael Sawyer}
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer#if ISC_MEM_FILL != 0 && ISC_MEM_CHECKOVERRUN != 0
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyerstatic inline void
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyercheck_overrun(void *mem, size_t size, size_t new_size) {
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer unsigned char *cp;
48674819ebf9176b5d5582ae851e485c324c1159Michael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer cp = (unsigned char *)mem;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer cp += size;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer while (size < new_size) {
cd720113a2fc8a781d4e33350b8a2b62857b31d8David Lawrence INSIST(*cp == 0xbe);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer cp++;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer size++;
9fe3676b8490319aa65182f2072cbf5086097979Michael Sawyer }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer#endif
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyervoid
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc__mem_put(isc_mem_t *ctx, void *mem, size_t size) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer REQUIRE(VALID_CONTEXT(ctx));
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer LOCK(&ctx->lock);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer mem_putunlocked(ctx, mem, size);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer UNLOCK(&ctx->lock);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyervoid *
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc__mem_getdebug(isc_mem_t *ctx, size_t size, const char *file, int line) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer void *ptr;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ptr = isc__mem_get(ctx, size);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (isc_mem_debugging)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer fprintf(stderr, "%s:%d: mem_get(%p, %lu) -> %p\n", file, line,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx, (unsigned long)size, ptr);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (ptr);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyervoid
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc__mem_putdebug(isc_mem_t *ctx, void *ptr, size_t size, const char *file,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer int line)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer{
cd720113a2fc8a781d4e33350b8a2b62857b31d8David Lawrence if (isc_mem_debugging)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer fprintf(stderr, "%s:%d: mem_put(%p, %p, %lu)\n", file, line,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx, ptr, (unsigned long)size);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc__mem_put(ctx, ptr, size);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc_result_t
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc_mem_preallocate(isc_mem_t *ctx) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer size_t i;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc_result_t result = ISC_R_SUCCESS;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer void *ptr;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer REQUIRE(VALID_CONTEXT(ctx));
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer LOCK(&ctx->lock);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer for (i = 0; i < ctx->max_size; i += ALIGNMENT_SIZE) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ptr = mem_getunlocked(ctx, i);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (ptr == NULL) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer result = ISC_R_NOMEMORY;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer break;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer mem_putunlocked(ctx, ptr, i);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer UNLOCK(&ctx->lock);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (result);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
19c8df90f1f23c3df870c1771c89c1acdb15020eMichael Sawyer/*
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Print the stats[] on the stream "out" with suitable formatting.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer */
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyervoid
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc_mem_stats(isc_mem_t *ctx, FILE *out) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer size_t i;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer const struct stats *s;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer const isc_mempool_t *pool;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer REQUIRE(VALID_CONTEXT(ctx));
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer LOCK(&ctx->lock);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
19c8df90f1f23c3df870c1771c89c1acdb15020eMichael Sawyer if (ctx->freelists != NULL) {
19c8df90f1f23c3df870c1771c89c1acdb15020eMichael Sawyer for (i = 0; i <= ctx->max_size; i++) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer s = &ctx->stats[i];
19c8df90f1f23c3df870c1771c89c1acdb15020eMichael Sawyer
19c8df90f1f23c3df870c1771c89c1acdb15020eMichael Sawyer if (s->totalgets == 0 && s->gets == 0)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer continue;
19c8df90f1f23c3df870c1771c89c1acdb15020eMichael Sawyer fprintf(out, "%s%5d: %11lu gets, %11lu rem",
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer (i == ctx->max_size) ? ">=" : " ",
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer i, s->totalgets, s->gets);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (s->blocks != 0)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer fprintf(out, " (%lu bl, %lu ff)",
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer s->blocks, s->freefrags);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer fputc('\n', out);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer /*
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Note that since a pool can be locked now, these stats might be
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * somewhat off if the pool is in active use at the time the stats
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * are dumped. The link fields are protected by the isc_mem_t's
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * lock, however, so walking this list and extracting integers from
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * stats fields is always safe.
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer */
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer pool = ISC_LIST_HEAD(ctx->pools);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (pool != NULL) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer fprintf(out, "[Pool statistics]\n");
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer fprintf(out, "%15s %10s %10s %10s %10s %10s %10s %10s %1s\n",
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer "name", "size", "maxalloc", "allocated", "freecount",
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer "freemax", "fillcount", "gets", "L");
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer while (pool != NULL) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer fprintf(out, "%15s %10u %10u %10u %10u %10u %10u %10u %s\n",
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer pool->name, pool->size, pool->maxalloc,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer pool->allocated, pool->freecount, pool->freemax,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer pool->fillcount, pool->gets,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer (pool->lock == NULL ? "N" : "Y"));
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer pool = ISC_LIST_NEXT(pool, link);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer }
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer UNLOCK(&ctx->lock);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc_boolean_t
e715e011788a529446b8013239c33599542ece32Michael Sawyerisc_mem_valid(isc_mem_t *ctx, void *ptr) {
e715e011788a529446b8013239c33599542ece32Michael Sawyer unsigned char *cp = ptr;
e715e011788a529446b8013239c33599542ece32Michael Sawyer isc_boolean_t result = ISC_FALSE;
e715e011788a529446b8013239c33599542ece32Michael Sawyer
e715e011788a529446b8013239c33599542ece32Michael Sawyer REQUIRE(VALID_CONTEXT(ctx));
e715e011788a529446b8013239c33599542ece32Michael Sawyer LOCK(&ctx->lock);
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer if (ctx->lowest != NULL && cp >= ctx->lowest && cp <= ctx->highest)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer result = ISC_TRUE;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer UNLOCK(&ctx->lock);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer return (result);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer/*
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer * Replacements for malloc() and free() -- they implicitly remember the
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * size of the object allocated (with some additional overhead).
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer */
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyervoid *
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyerisc__mem_allocate(isc_mem_t *ctx, size_t size) {
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer size_info *si;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer size += ALIGNMENT_SIZE;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer si = isc__mem_get(ctx, size);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer if (si == NULL)
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer return (NULL);
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer si->u.size = size;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer return (&si[1]);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer}
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyervoid *
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyerisc__mem_allocatedebug(isc_mem_t *ctx, size_t size, const char *file,
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer int line) {
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer size_info *si;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
f8fec75ee8f429821137aee090f56ab678404a56Michael Sawyer si = isc__mem_allocate(ctx, size);
6c6a62933dda281cb9193de1d54d4c9e74515f5aMichael Sawyer if (si == NULL)
f8fec75ee8f429821137aee090f56ab678404a56Michael Sawyer return (NULL);
6c6a62933dda281cb9193de1d54d4c9e74515f5aMichael Sawyer if (isc_mem_debugging)
ad7bb5bff3e796f5648835bf87a203d23d8319e4David Lawrence fprintf(stderr, "%s:%d: mem_get(%p, %lu) -> %p\n", file, line,
ad7bb5bff3e796f5648835bf87a203d23d8319e4David Lawrence ctx, (unsigned long)si[-1].u.size, si);
f8fec75ee8f429821137aee090f56ab678404a56Michael Sawyer return (si);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer}
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyervoid
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyerisc__mem_free(isc_mem_t *ctx, void *ptr) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer size_info *si;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer si = &(((size_info *)ptr)[-1]);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc__mem_put(ctx, si, si->u.size);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyervoid
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc__mem_freedebug(isc_mem_t *ctx, void *ptr, const char *file, int line) {
844eaa56d6d647b38b2a5cf08f7ea5ab7b752690Michael Sawyer size_info *si;
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer si = &(((size_info *)ptr)[-1]);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer if (isc_mem_debugging)
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer fprintf(stderr, "%s:%d: mem_put(%p, %p, %lu)\n", file, line,
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer ctx, ptr, (unsigned long)si->u.size);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer isc__mem_put(ctx, si, si->u.size);
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer}
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer
9fe3676b8490319aa65182f2072cbf5086097979Michael Sawyer/*
9fe3676b8490319aa65182f2072cbf5086097979Michael Sawyer * Other useful things.
9fe3676b8490319aa65182f2072cbf5086097979Michael Sawyer */
9fe3676b8490319aa65182f2072cbf5086097979Michael Sawyer
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyerchar *
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyerisc__mem_strdup(isc_mem_t *mctx, const char *s) {
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer size_t len;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer char *ns;
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer
6fe03d6c83ec02d4494edc870f5e892d419b6885Michael Sawyer len = strlen(s);
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer ns = isc__mem_allocate(mctx, len + 1);
aa6054ec74819f754bcf19442ca9b39d948171adMichael Sawyer if (ns == NULL)
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer return (NULL);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer strncpy(ns, s, len + 1);
1893b56ef9f5f2bc2a0fbe80d3c6b69df1bdc7c2Michael Sawyer
38cf6e52ce4b33795713388824b69d78e430b115Michael Sawyer return (ns);
1893b56ef9f5f2bc2a0fbe80d3c6b69df1bdc7c2Michael Sawyer}
1893b56ef9f5f2bc2a0fbe80d3c6b69df1bdc7c2Michael Sawyer
bf9163715dca2bfa7645d714dc091881e7183f73Brian Wellingtonchar *
db8b100cae62de849ecf4ba9ad3be811fb375b53Michael Sawyerisc__mem_strdupdebug(isc_mem_t *mctx, const char *s, const char *file,
db8b100cae62de849ecf4ba9ad3be811fb375b53Michael Sawyer int line) {
db8b100cae62de849ecf4ba9ad3be811fb375b53Michael Sawyer char *ptr;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence size_info *si;
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer ptr = isc__mem_strdup(mctx, s);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer si = &(((size_info *)ptr)[-1]);
cefd68008fbba3488a077052ae62aa12b6de502bMichael Sawyer if (isc_mem_debugging)
fprintf(stderr, "%s:%d: mem_get(%p, %lu) -> %p\n", file, line,
mctx, (unsigned long)si->u.size, ptr);
return (ptr);
}
void
isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) {
REQUIRE(VALID_CONTEXT(ctx));
LOCK(&ctx->lock);
ctx->checkfree = flag;
UNLOCK(&ctx->lock);
}
void
isc_mem_setsplit(isc_mem_t *ctx, isc_boolean_t flag) {
REQUIRE(VALID_CONTEXT(ctx));
LOCK(&ctx->lock);
ctx->trysplit = flag;
UNLOCK(&ctx->lock);
}
/*
* 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);
}
size_t
isc_mem_inuse(isc_mem_t *ctx) {
size_t inuse;
REQUIRE(VALID_CONTEXT(ctx));
LOCK(&ctx->lock);
inuse = ctx->inuse;
UNLOCK(&ctx->lock);
return (inuse);
}
#ifdef ISC_MEMCLUSTER_LEGACY
/*
* Public Legacy.
*/
static isc_mem_t *default_context = NULL;
int
meminit(size_t init_max_size, size_t target_size) {
/*
* Need default_context lock here.
*/
if (default_context != NULL)
return (-1);
return (isc_mem_create(init_max_size, target_size, &default_context));
}
isc_mem_t *
mem_default_context(void) {
/*
* Need default_context lock here.
*/
if (default_context == NULL && meminit(0, 0) == -1)
return (NULL);
return (default_context);
}
void *
isc__legacy_memget(size_t size) {
/*
* Need default_context lock here.
*/
if (default_context == NULL && meminit(0, 0) == -1)
return (NULL);
return (isc__mem_get(default_context, size));
}
void
isc__legacy_memput(void *mem, size_t size) {
/*
* Need default_context lock here.
*/
REQUIRE(default_context != NULL);
isc__mem_put(default_context, mem, size);
}
void *
isc__legacy_memget_debug(size_t size, const char *file, int line) {
void *ptr;
ptr = isc__legacy_memget(size);
if (isc_mem_debugging)
fprintf(stderr, "%s:%d: memget(%lu) -> %p\n", file, line,
(unsigned long)size, ptr);
return (ptr);
}
void
isc__legacy_memput_debug(void *ptr, size_t size, const char *file, int line) {
if (isc_mem_debugging)
fprintf(stderr, "%s:%d: memput(%p, %lu)\n", file, line,
ptr, (unsigned long)size);
isc__legacy_memput(ptr, size);
}
int
memvalid(void *ptr) {
/*
* Need default_context lock here.
*/
REQUIRE(default_context != NULL);
return (isc_mem_valid(default_context, ptr));
}
void
memstats(FILE *out) {
/*
* Need default_context lock here.
*/
REQUIRE(default_context != NULL);
isc_mem_stats(default_context, out);
}
#endif /* ISC_MEMCLUSTER_LEGACY */
/*
* 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++) {
item = item->next;
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 {
next = item->next;
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
* context must be locked, and the pool if needed.
*/
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 {
next = item->next;
mem_putunlocked(mctx, item, mpctx->size);
INSIST(mpctx->freecount > 0);
mpctx->freecount--;
item = next;
} while (item != NULL);
}
isc_result_t
isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
isc_mempool_t *mpctx;
REQUIRE(VALID_CONTEXT(mctx));
REQUIRE(size > 0);
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);
mpctx = mem_getunlocked(mctx, sizeof(isc_mempool_t));
if (mpctx == NULL) {
UNLOCK(&mctx->lock);
return (ISC_R_NOMEMORY);
}
mpctx->magic = MEMPOOL_MAGIC;
mpctx->lock = NULL;
mpctx->mctx = mctx;
mpctx->size = size;
mpctx->maxalloc = UINT_MAX;
mpctx->allocated = 0;
mpctx->freecount = 0;
mpctx->freemax = 1;
mpctx->fillcount = 1;
mpctx->gets = 0;
#if ISC_MEMPOOL_NAMES
mpctx->name[0] = 0;
#endif
mpctx->items = NULL;
*mpctxp = mpctx;
ISC_LIST_APPEND(mctx->pools, mpctx, link);
UNLOCK(&mctx->lock);
return (ISC_R_SUCCESS);
}
void
isc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
REQUIRE(name != NULL);
#if ISC_MEMPOOL_NAMES
if (mpctx->lock != NULL)
LOCK(mpctx->lock);
memset(mpctx->name, 0, sizeof(mpctx->name));
strncpy(mpctx->name, name, sizeof(mpctx->name) - 1);
if (mpctx->lock != NULL)
UNLOCK(mpctx->lock);
#else
UNUSED(mpctx);
UNUSED(name);
#endif
}
void
isc_mempool_destroy(isc_mempool_t **mpctxp) {
isc_mempool_t *mpctx;
isc_mem_t *mctx;
isc_mutex_t *lock;
REQUIRE(mpctxp != NULL);
mpctx = *mpctxp;
REQUIRE(VALID_MEMPOOL(mpctx));
REQUIRE(mpctx->allocated == 0);
mctx = mpctx->mctx;
lock = mpctx->lock;
if (lock != NULL)
LOCK(lock);
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;
mem_putunlocked(mpctx->mctx, mpctx, sizeof(isc_mempool_t));
UNLOCK(&mctx->lock);
if (lock != NULL)
UNLOCK(lock);
*mpctxp = NULL;
}
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;
}
void *
isc__mempool_get(isc_mempool_t *mpctx) {
element *item;
isc_mem_t *mctx;
unsigned int i;
REQUIRE(VALID_MEMPOOL(mpctx));
mctx = mpctx->mctx;
if (mpctx->lock != NULL)
LOCK(mpctx->lock);
/*
* Don't let the caller go over quota
*/
if (mpctx->allocated >= mpctx->maxalloc) {
item = NULL;
goto out;
}
/*
* 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++;
goto out;
}
/*
* 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++) {
item = mem_getunlocked(mctx, mpctx->size);
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)
goto out;
mpctx->items = item->next;
mpctx->freecount--;
mpctx->gets++;
mpctx->allocated++;
out:
if (mpctx->lock != NULL)
UNLOCK(mpctx->lock);
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;
if (mpctx->lock != NULL)
LOCK(mpctx->lock);
INSIST(mpctx->allocated > 0);
mpctx->allocated--;
/*
* If our free list is full, return this to the mctx directly.
*/
if (mpctx->freecount >= mpctx->freemax) {
isc__mem_put(mctx, mem, mpctx->size);
if (mpctx->lock != NULL)
UNLOCK(mpctx->lock);
return;
}
/*
* Otherwise, attach it to our free list and bump the counter.
*/
mpctx->freecount++;
item = (element *)mem;
item->next = mpctx->items;
mpctx->items = item;
if (mpctx->lock != NULL)
UNLOCK(mpctx->lock);
}
void *
isc__mempool_getdebug(isc_mempool_t *mpctx, const char *file, int line) {
void *ptr;
ptr = isc__mempool_get(mpctx);
if (isc_mem_debugging)
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)
{
if (isc_mem_debugging)
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));
if (mpctx->lock != NULL)
LOCK(mpctx->lock);
mpctx->freemax = limit;
if (mpctx->lock != NULL)
UNLOCK(mpctx->lock);
}
unsigned int
isc_mempool_getfreemax(isc_mempool_t *mpctx) {
unsigned int freemax;
REQUIRE(VALID_MEMPOOL(mpctx));
if (mpctx->lock != NULL)
LOCK(mpctx->lock);
freemax = mpctx->freemax;
if (mpctx->lock != NULL)
UNLOCK(mpctx->lock);
return (freemax);
}
unsigned int
isc_mempool_getfreecount(isc_mempool_t *mpctx) {
unsigned int freecount;
REQUIRE(VALID_MEMPOOL(mpctx));
if (mpctx->lock != NULL)
LOCK(mpctx->lock);
freecount = mpctx->freecount;
if (mpctx->lock != NULL)
UNLOCK(mpctx->lock);
return (freecount);
}
void
isc_mempool_setmaxalloc(isc_mempool_t *mpctx, unsigned int limit) {
REQUIRE(limit > 0);
REQUIRE(VALID_MEMPOOL(mpctx));
if (mpctx->lock != NULL)
LOCK(mpctx->lock);
mpctx->maxalloc = limit;
if (mpctx->lock != NULL)
UNLOCK(mpctx->lock);
}
unsigned int
isc_mempool_getmaxalloc(isc_mempool_t *mpctx) {
unsigned int maxalloc;
REQUIRE(VALID_MEMPOOL(mpctx));
if (mpctx->lock != NULL)
LOCK(mpctx->lock);
maxalloc = mpctx->maxalloc;
if (mpctx->lock != NULL)
UNLOCK(mpctx->lock);
return (maxalloc);
}
unsigned int
isc_mempool_getallocated(isc_mempool_t *mpctx) {
unsigned int allocated;
REQUIRE(VALID_MEMPOOL(mpctx));
if (mpctx->lock != NULL)
LOCK(mpctx->lock);
allocated = mpctx->allocated;
if (mpctx->lock != NULL)
UNLOCK(mpctx->lock);
return (allocated);
}
void
isc_mempool_setfillcount(isc_mempool_t *mpctx, unsigned int limit) {
REQUIRE(limit > 0);
REQUIRE(VALID_MEMPOOL(mpctx));
if (mpctx->lock != NULL)
LOCK(mpctx->lock);
mpctx->fillcount = limit;
if (mpctx->lock != NULL)
UNLOCK(mpctx->lock);
}
unsigned int
isc_mempool_getfillcount(isc_mempool_t *mpctx) {
unsigned int fillcount;
REQUIRE(VALID_MEMPOOL(mpctx));
if (mpctx->lock != NULL)
LOCK(mpctx->lock);
fillcount = mpctx->fillcount;
if (mpctx->lock != NULL)
UNLOCK(mpctx->lock);
return (fillcount);
}