mem.c revision 2983bfafb769d9c64d11bfdde7f5384ea236b4df
e672951ed28b2e9cc7a19c3d7fa4a258382f981cAutomatic Updater * Copyright (c) 1997, 1998 by Internet Software Consortium.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Permission to use, copy, modify, and distribute this software for any
ec5347e2c775f027573ce5648b910361aa926c01Automatic Updater * purpose with or without fee is hereby granted, provided that the above
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley * copyright notice and this permission notice appear in all copies.
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
dafcb997e390efa4423883dafd100c975c4095d6Mark Andrews * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
5619558151f1aa4249b3ead979e76876e29278b6Bob Halleytypedef struct {
5619558151f1aa4249b3ead979e76876e29278b6Bob Halleytypedef struct {
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley * This structure must be ALIGNMENT_SIZE bytes.
904a5734375869ffb504ed8cde6b68cafadb6d64Bob Halley unsigned long gets;
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley unsigned long totalgets;
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley unsigned long blocks;
ca67883a666bdf314d3da958d5195e7215b1f797Bob Halley unsigned long freefrags;
e496615043400500492fa7b891c515c8e7cb7d08Bob Halley unsigned char ** basic_table;
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley unsigned char * lowest;
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley unsigned char * highest;
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley/* Forward. */
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley/* Macros. */
904a5734375869ffb504ed8cde6b68cafadb6d64Bob Halley#define ALIGNMENT_SIZE sizeof (void *)
61fb42c4ef45d88e115bd769c30c4f36b461870bMark Andrews INSIST(isc_mutex_lock(&(ctx)->mutex) == ISC_R_SUCCESS)
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley INSIST(isc_mutex_unlock(&(ctx)->mutex) == ISC_R_SUCCESS)
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley/* Private Inline-able. */
5619558151f1aa4249b3ead979e76876e29278b6Bob Halleystatic inline size_t
078d49b63324f01d98301ee21671abee0c41fcdeBob Halley * If there is no remainder for the integer division of
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley * then we already have a good size; if not, then we need
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley * to round up the result in order to get a size big
904a5734375869ffb504ed8cde6b68cafadb6d64Bob Halley * enough to satisfy the request and be aligned on ALIGNMENT_SIZE
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley * byte boundaries.
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley/* Public. */
35541328a8c18ba1f984300dfe30ec8713c90031Mark Andrewsisc_memctx_create(size_t init_max_size, size_t target_size,
28640d1da26d561f4137122fe64e9e8cc08bf11eBob Halley ctx->freelists = malloc(ctx->max_size * sizeof (element *));
bf345589ce0b0b64533d4566e4992a0e63aac6f5Bob Halley ctx->stats = malloc((ctx->max_size+1) * sizeof (struct stats));
bf345589ce0b0b64533d4566e4992a0e63aac6f5Bob Halley memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof (struct stats));
e672951ed28b2e9cc7a19c3d7fa4a258382f981cAutomatic Updater if (isc_mutex_init(&ctx->mutex) != ISC_R_SUCCESS) {
1c724c986de1449e3b2f1eeae4c724dc0d97603cBob Halley "isc_mutex_init() failed");
e02884167b7c969b56413f76c48c3802c4dca14dAndreas Gustafsson unsigned int i;
bf345589ce0b0b64533d4566e4992a0e63aac6f5Bob Halley unsigned char **table;
bf345589ce0b0b64533d4566e4992a0e63aac6f5Bob Halley unsigned int table_size;
bf345589ce0b0b64533d4566e4992a0e63aac6f5Bob Halley /* Require: we hold the context lock. */
bf345589ce0b0b64533d4566e4992a0e63aac6f5Bob Halley if (ctx->basic_table_count <= ctx->basic_table_size) {
bf345589ce0b0b64533d4566e4992a0e63aac6f5Bob Halley table_size = ctx->basic_table_size + TABLE_INCREMENT;
bf345589ce0b0b64533d4566e4992a0e63aac6f5Bob Halley table = malloc(table_size * sizeof (unsigned char *));
bf345589ce0b0b64533d4566e4992a0e63aac6f5Bob Halley ctx->basic_table_size * sizeof (unsigned char *));
7837d146219db7a85a4b444a9cdf6602254a4f75Bob Halley new = malloc(NUM_BASIC_BLOCKS * ctx->mem_target);
1c724c986de1449e3b2f1eeae4c724dc0d97603cBob Halley * curr is now pointing at the last block in the
1c724c986de1449e3b2f1eeae4c724dc0d97603cBob Halley last = first + NUM_BASIC_BLOCKS * ctx->mem_target - 1;
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley if (size >= ctx->max_size || new_size >= ctx->max_size) {
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley /* memget() was called on something beyond our upper limit. */
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley * If there are no blocks in the free list for this size, get a chunk
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley * of memory and then break it up into "new_size"-sized blocks, adding
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley * them to the free list.
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson ctx->basic_blocks = ctx->basic_blocks->next;
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson /* Set up a linked-list of blocks of size "new_size". */
45e1bd63587102c3bb361eaca42ee7b714fb3542Mark Andrews /* curr is now pointing at the last block in the array. */
5619558151f1aa4249b3ead979e76876e29278b6Bob Halley /* The free list uses the "rounded-up" size "new_size": */
76883e8cee593f45c65b0936e5d6e8f778d6e3efMichael Graff ctx->freelists[new_size] = ctx->freelists[new_size]->next;
8af4b7042d84e0699f7c1de306526098030b74a9Mark Andrews * The stats[] uses the _actual_ "size" requested by the
69be7837c920fac5c71a73e8fad586f9a2711e96Michael Graff * caller, with the caveat (in the code above) that "size" >= the
bf345589ce0b0b64533d4566e4992a0e63aac6f5Bob Halley * max. size (max_size) ends up getting recorded as a call to
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson * This is a call from an external caller,
c569a0e4d518bf30be1b2ba9cc3592fe470e9822Mark Andrews * so we want to count this as a user "put".
89d8adb6663b13435ff9ae1eb53e45da7fa79275Bob Halley__isc_mem_put(isc_memctx_t ctx, void *mem, size_t size) {
8dfa9caeec8e68db0c937e347a3d6629e7627d54Bob Halley if (size == ctx->max_size || new_size >= ctx->max_size) {
8dfa9caeec8e68db0c937e347a3d6629e7627d54Bob Halley /* memput() called on something beyond our upper limit */
b2ca6fd3a8293440b4d263723525396059cf2400Brian Wellington INSIST(ctx->stats[ctx->max_size].gets != 0);
c3b708aaf1bb0a118e0e11befa1b732acfb1d079Bob Halley /* The free list uses the "rounded-up" size "new_size": */
bf345589ce0b0b64533d4566e4992a0e63aac6f5Bob Halley ((element *)mem)->next = ctx->freelists[new_size];
bf345589ce0b0b64533d4566e4992a0e63aac6f5Bob Halley * The stats[] uses the _actual_ "size" requested by the
bf345589ce0b0b64533d4566e4992a0e63aac6f5Bob Halley * caller, with the caveat (in the code above) that "size" >= the
bf345589ce0b0b64533d4566e4992a0e63aac6f5Bob Halley * max. size (max_size) ends up getting recorded as a call to
c569a0e4d518bf30be1b2ba9cc3592fe470e9822Mark Andrews__isc_mem_getdebug(isc_memctx_t ctx, size_t size, const char *file, int line) {
c569a0e4d518bf30be1b2ba9cc3592fe470e9822Mark Andrews fprintf(stderr, "%s:%d: mem_get(%p, %lu) -> %p\n", file, line,
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson__isc_mem_putdebug(isc_memctx_t ctx, void *ptr, size_t size, const char *file,
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson fprintf(stderr, "%s:%d: mem_put(%p, %p, %lu)\n", file, line,
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson * Print the stats[] on the stream "out" with suitable formatting.
febaa091847ab004f40500cc475a819f2c73fcddAndreas Gustafsson fprintf(out, "%s%5d: %11lu gets, %11lu rem",
2dd99c098ca162f985b7ef3c8142a964ad8281aeMark Andrews if (ctx->lowest != NULL && cp >= ctx->lowest && cp <= ctx->highest)
def8e47c688e2480a4539d69c3d1a0a28a7c0550Mark Andrews * Replacements for malloc() and free().
def8e47c688e2480a4539d69c3d1a0a28a7c0550Mark Andrewsisc_mem_allocate(isc_memctx_t ctx, size_t size) {
8dfa9caeec8e68db0c937e347a3d6629e7627d54Bob Halley * Public Legacy.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrencememinit(size_t init_max_size, size_t target_size) {
76883e8cee593f45c65b0936e5d6e8f778d6e3efMichael Graff /* need default_context lock here */
8af4b7042d84e0699f7c1de306526098030b74a9Mark Andrews return (-1);
94a08e09db3dc844b6ee4841c368a2d7074a9c3fAndreas Gustafsson return (isc_mem_create(init_max_size, target_size, &default_context));
bf345589ce0b0b64533d4566e4992a0e63aac6f5Bob Halley /* need default_context lock here */
69be7837c920fac5c71a73e8fad586f9a2711e96Michael Graff if (default_context == NULL && meminit(0, 0) == -1)
22f735acbce7ffe95af20bb58bb8929b6f1d674fMichael Graff /* need default_context lock here */
904a5734375869ffb504ed8cde6b68cafadb6d64Bob Halley if (default_context == NULL && meminit(0, 0) == -1)
69be7837c920fac5c71a73e8fad586f9a2711e96Michael Graff /* need default_context lock here */
c3b708aaf1bb0a118e0e11befa1b732acfb1d079Bob Halley__memget_debug(size_t size, const char *file, int line) {
43b8fb75704f290a48fc96461140b42b2488348dMark Andrews fprintf(stderr, "%s:%d: memget(%lu) -> %p\n", file, line,
13eaef2df27683658868c3828c18880d7419a16aDavid Lawrence__memput_debug(void *ptr, size_t size, const char *file, int line) {
13eaef2df27683658868c3828c18880d7419a16aDavid Lawrence fprintf(stderr, "%s:%d: memput(%p, %lu)\n", file, line,
c3b708aaf1bb0a118e0e11befa1b732acfb1d079Bob Halley /* need default_context lock here */
c3b708aaf1bb0a118e0e11befa1b732acfb1d079Bob Halley /* need default_context lock here */
c3b708aaf1bb0a118e0e11befa1b732acfb1d079Bob Halley#endif /* ISC_MEMCLUSTER_LEGACY */