1998-08-17 22:05:58 +00:00
|
|
|
/*
|
1998-12-12 20:48:14 +00:00
|
|
|
* Copyright (C) 1997, 1998 Internet Software Consortium.
|
|
|
|
*
|
1998-08-17 22:05:58 +00:00
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
1998-12-12 20:48:14 +00:00
|
|
|
*
|
1998-08-17 22:05:58 +00:00
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
|
|
|
* ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
|
|
|
* CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
|
|
|
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
|
|
|
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
|
|
* SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
1998-12-12 19:25:20 +00:00
|
|
|
#include <config.h>
|
1998-08-17 22:05:58 +00:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
1998-12-12 19:25:20 +00:00
|
|
|
#include <stddef.h>
|
1998-08-17 22:05:58 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
#include <isc/assertions.h>
|
1998-12-04 20:00:26 +00:00
|
|
|
#include <isc/error.h>
|
1998-12-11 20:38:46 +00:00
|
|
|
#include <isc/mem.h>
|
1998-11-11 19:02:24 +00:00
|
|
|
#ifndef ISC_SINGLETHREADED
|
1998-08-18 19:28:30 +00:00
|
|
|
#include <isc/mutex.h>
|
|
|
|
#endif
|
|
|
|
|
1998-08-17 22:05:58 +00:00
|
|
|
/*
|
|
|
|
* Types.
|
|
|
|
*/
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
void * next;
|
1998-10-21 22:01:08 +00:00
|
|
|
} element;
|
1998-08-17 22:05:58 +00:00
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
size_t size;
|
|
|
|
/*
|
|
|
|
* This structure must be ALIGNMENT_SIZE bytes.
|
|
|
|
*/
|
|
|
|
} *size_info;
|
|
|
|
|
|
|
|
struct stats {
|
1998-08-18 00:29:57 +00:00
|
|
|
unsigned long gets;
|
|
|
|
unsigned long totalgets;
|
|
|
|
unsigned long blocks;
|
|
|
|
unsigned long freefrags;
|
1998-08-17 22:05:58 +00:00
|
|
|
};
|
|
|
|
|
1998-10-21 22:01:08 +00:00
|
|
|
struct isc_memctx {
|
1998-08-17 22:05:58 +00:00
|
|
|
size_t max_size;
|
|
|
|
size_t mem_target;
|
1998-10-21 22:01:08 +00:00
|
|
|
element ** freelists;
|
|
|
|
element * basic_blocks;
|
1998-09-16 21:38:08 +00:00
|
|
|
unsigned char ** basic_table;
|
|
|
|
unsigned int basic_table_count;
|
|
|
|
unsigned int basic_table_size;
|
1998-08-18 00:29:57 +00:00
|
|
|
unsigned char * lowest;
|
|
|
|
unsigned char * highest;
|
1998-08-17 22:05:58 +00:00
|
|
|
struct stats * stats;
|
1998-10-22 01:33:20 +00:00
|
|
|
isc_mutex_t mutex;
|
1998-08-17 22:05:58 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Forward. */
|
|
|
|
|
|
|
|
static size_t quantize(size_t);
|
|
|
|
|
|
|
|
/* Macros. */
|
|
|
|
|
|
|
|
#define DEF_MAX_SIZE 1100
|
|
|
|
#define DEF_MEM_TARGET 4096
|
|
|
|
#define ALIGNMENT_SIZE sizeof (void *)
|
|
|
|
#define NUM_BASIC_BLOCKS 64 /* must be > 1 */
|
1998-09-16 21:38:08 +00:00
|
|
|
#define TABLE_INCREMENT 1024
|
1998-08-17 22:05:58 +00:00
|
|
|
|
1998-11-11 19:02:24 +00:00
|
|
|
#ifndef ISC_SINGLETHREADED
|
1998-10-22 01:33:20 +00:00
|
|
|
#define LOCK_CONTEXT(ctx) \
|
|
|
|
INSIST(isc_mutex_lock(&(ctx)->mutex) == ISC_R_SUCCESS)
|
|
|
|
#define UNLOCK_CONTEXT(ctx) \
|
|
|
|
INSIST(isc_mutex_unlock(&(ctx)->mutex) == ISC_R_SUCCESS)
|
1998-08-18 19:28:30 +00:00
|
|
|
#else
|
|
|
|
#define LOCK_CONTEXT(ctx)
|
|
|
|
#define UNLOCK_CONTEXT(ctx)
|
|
|
|
#endif
|
1998-08-17 22:05:58 +00:00
|
|
|
|
|
|
|
/* Private Inline-able. */
|
|
|
|
|
1998-08-18 19:28:30 +00:00
|
|
|
static inline size_t
|
1998-08-17 22:05:58 +00:00
|
|
|
quantize(size_t size) {
|
|
|
|
int remainder;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If there is no remainder for the integer division of
|
|
|
|
*
|
|
|
|
* (rightsize/ALIGNMENT_SIZE)
|
|
|
|
*
|
|
|
|
* then we already have a good size; if not, then we need
|
|
|
|
* to round up the result in order to get a size big
|
|
|
|
* enough to satisfy the request and be aligned on ALIGNMENT_SIZE
|
|
|
|
* byte boundaries.
|
|
|
|
*/
|
|
|
|
remainder = size % ALIGNMENT_SIZE;
|
|
|
|
if (remainder != 0)
|
|
|
|
size += ALIGNMENT_SIZE - remainder;
|
|
|
|
return (size);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Public. */
|
|
|
|
|
1998-10-21 22:01:08 +00:00
|
|
|
isc_result_t
|
|
|
|
isc_memctx_create(size_t init_max_size, size_t target_size,
|
|
|
|
isc_memctx_t *ctxp)
|
|
|
|
{
|
|
|
|
isc_memctx_t ctx;
|
|
|
|
|
|
|
|
REQUIRE(ctxp != NULL && *ctxp == NULL);
|
1998-08-17 22:05:58 +00:00
|
|
|
|
|
|
|
ctx = malloc(sizeof *ctx);
|
|
|
|
if (init_max_size == 0)
|
|
|
|
ctx->max_size = DEF_MAX_SIZE;
|
|
|
|
else
|
|
|
|
ctx->max_size = init_max_size;
|
|
|
|
if (target_size == 0)
|
|
|
|
ctx->mem_target = DEF_MEM_TARGET;
|
|
|
|
else
|
|
|
|
ctx->mem_target = target_size;
|
1998-10-21 22:01:08 +00:00
|
|
|
ctx->freelists = malloc(ctx->max_size * sizeof (element *));
|
1998-08-17 22:05:58 +00:00
|
|
|
if (ctx->freelists == NULL) {
|
|
|
|
free(ctx);
|
1998-10-21 22:01:08 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
1998-08-17 22:05:58 +00:00
|
|
|
}
|
|
|
|
memset(ctx->freelists, 0,
|
1998-10-21 22:01:08 +00:00
|
|
|
ctx->max_size * sizeof (element *));
|
1998-08-17 22:05:58 +00:00
|
|
|
ctx->stats = malloc((ctx->max_size+1) * sizeof (struct stats));
|
|
|
|
if (ctx->stats == NULL) {
|
|
|
|
free(ctx->freelists);
|
|
|
|
free(ctx);
|
1998-10-21 22:01:08 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
1998-08-17 22:05:58 +00:00
|
|
|
}
|
|
|
|
memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof (struct stats));
|
|
|
|
ctx->basic_blocks = NULL;
|
1998-09-16 21:38:08 +00:00
|
|
|
ctx->basic_table = NULL;
|
|
|
|
ctx->basic_table_count = 0;
|
|
|
|
ctx->basic_table_size = 0;
|
1998-08-17 22:05:58 +00:00
|
|
|
ctx->lowest = NULL;
|
|
|
|
ctx->highest = NULL;
|
1998-10-22 01:33:20 +00:00
|
|
|
if (isc_mutex_init(&ctx->mutex) != ISC_R_SUCCESS) {
|
1998-08-18 19:28:30 +00:00
|
|
|
free(ctx->stats);
|
|
|
|
free(ctx->freelists);
|
|
|
|
free(ctx);
|
1998-10-21 22:01:08 +00:00
|
|
|
UNEXPECTED_ERROR(__FILE__, __LINE__,
|
1998-10-22 01:33:20 +00:00
|
|
|
"isc_mutex_init() failed");
|
1998-10-21 22:01:08 +00:00
|
|
|
return (ISC_R_UNEXPECTED);
|
1998-08-18 19:28:30 +00:00
|
|
|
}
|
1998-08-17 22:05:58 +00:00
|
|
|
*ctxp = ctx;
|
1998-10-21 22:01:08 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1998-08-17 22:05:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-10-21 22:01:08 +00:00
|
|
|
isc_memctx_destroy(isc_memctx_t *ctxp) {
|
1998-09-16 21:38:08 +00:00
|
|
|
unsigned int i;
|
1998-10-21 22:01:08 +00:00
|
|
|
isc_memctx_t ctx;
|
1998-09-16 21:38:08 +00:00
|
|
|
|
1998-08-17 22:05:58 +00:00
|
|
|
REQUIRE(ctxp != NULL);
|
1998-10-21 22:01:08 +00:00
|
|
|
|
1998-09-16 21:38:08 +00:00
|
|
|
ctx = *ctxp;
|
|
|
|
|
|
|
|
for (i = 0; i <= ctx->max_size; i++)
|
|
|
|
INSIST(ctx->stats[i].gets == 0);
|
|
|
|
|
|
|
|
for (i = 0; i < ctx->basic_table_count; i++)
|
|
|
|
free(ctx->basic_table[i]);
|
|
|
|
free(ctx->freelists);
|
|
|
|
free(ctx->stats);
|
|
|
|
free(ctx->basic_table);
|
1998-10-22 01:33:20 +00:00
|
|
|
(void)isc_mutex_destroy(&ctx->mutex);
|
1998-09-16 21:38:08 +00:00
|
|
|
free(ctx);
|
1998-08-17 22:05:58 +00:00
|
|
|
|
|
|
|
*ctxp = NULL;
|
|
|
|
}
|
|
|
|
|
1998-09-16 21:38:08 +00:00
|
|
|
static void
|
1998-10-21 22:01:08 +00:00
|
|
|
more_basic_blocks(isc_memctx_t ctx) {
|
1998-09-16 21:38:08 +00:00
|
|
|
void *new;
|
|
|
|
unsigned char *curr, *next;
|
|
|
|
unsigned char *first, *last;
|
|
|
|
unsigned char **table;
|
|
|
|
unsigned int table_size;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
/* Require: we hold the context lock. */
|
|
|
|
|
|
|
|
if (ctx->basic_table_count <= ctx->basic_table_size) {
|
|
|
|
table_size = ctx->basic_table_size + TABLE_INCREMENT;
|
|
|
|
table = malloc(table_size * sizeof (unsigned char *));
|
|
|
|
if (table == NULL)
|
|
|
|
return;
|
|
|
|
memcpy(table, ctx->basic_table,
|
|
|
|
ctx->basic_table_size * sizeof (unsigned char *));
|
|
|
|
free(ctx->basic_table);
|
|
|
|
ctx->basic_table = table;
|
|
|
|
ctx->basic_table_size = table_size;
|
|
|
|
} else
|
|
|
|
table = NULL;
|
|
|
|
|
|
|
|
new = malloc(NUM_BASIC_BLOCKS * ctx->mem_target);
|
|
|
|
if (new == NULL) {
|
|
|
|
if (table != NULL)
|
|
|
|
free(table);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ctx->basic_table[ctx->basic_table_count] = new;
|
|
|
|
ctx->basic_table_count++;
|
|
|
|
curr = new;
|
|
|
|
next = curr + ctx->mem_target;
|
|
|
|
for (i = 0; i < (NUM_BASIC_BLOCKS - 1); i++) {
|
1998-10-21 22:01:08 +00:00
|
|
|
((element *)curr)->next = next;
|
1998-09-16 21:38:08 +00:00
|
|
|
curr = next;
|
|
|
|
next += ctx->mem_target;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* curr is now pointing at the last block in the
|
|
|
|
* array.
|
|
|
|
*/
|
1998-10-21 22:01:08 +00:00
|
|
|
((element *)curr)->next = NULL;
|
1998-09-16 21:38:08 +00:00
|
|
|
first = new;
|
|
|
|
last = first + NUM_BASIC_BLOCKS * ctx->mem_target - 1;
|
|
|
|
if (first < ctx->lowest || ctx->lowest == NULL)
|
|
|
|
ctx->lowest = first;
|
|
|
|
if (last > ctx->highest)
|
|
|
|
ctx->highest = last;
|
|
|
|
ctx->basic_blocks = new;
|
|
|
|
}
|
|
|
|
|
1998-08-17 22:05:58 +00:00
|
|
|
void *
|
1998-10-21 22:01:08 +00:00
|
|
|
__isc_mem_get(isc_memctx_t ctx, size_t size) {
|
1998-08-17 22:05:58 +00:00
|
|
|
size_t new_size = quantize(size);
|
|
|
|
void *ret;
|
|
|
|
|
|
|
|
REQUIRE(size > 0);
|
|
|
|
|
|
|
|
LOCK_CONTEXT(ctx);
|
|
|
|
|
|
|
|
if (size >= ctx->max_size || new_size >= ctx->max_size) {
|
|
|
|
/* memget() was called on something beyond our upper limit. */
|
|
|
|
ret = malloc(size);
|
|
|
|
if (ret != NULL) {
|
|
|
|
ctx->stats[ctx->max_size].gets++;
|
|
|
|
ctx->stats[ctx->max_size].totalgets++;
|
|
|
|
}
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If there are no blocks in the free list for this size, get a chunk
|
|
|
|
* of memory and then break it up into "new_size"-sized blocks, adding
|
|
|
|
* them to the free list.
|
|
|
|
*/
|
|
|
|
if (ctx->freelists[new_size] == NULL) {
|
|
|
|
int i, frags;
|
|
|
|
size_t total_size;
|
|
|
|
void *new;
|
1998-08-18 00:29:57 +00:00
|
|
|
unsigned char *curr, *next;
|
1998-08-17 22:05:58 +00:00
|
|
|
|
|
|
|
if (ctx->basic_blocks == NULL) {
|
1998-09-16 21:38:08 +00:00
|
|
|
more_basic_blocks(ctx);
|
|
|
|
if (ctx->basic_blocks == NULL) {
|
1998-08-17 22:05:58 +00:00
|
|
|
ret = NULL;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
total_size = ctx->mem_target;
|
|
|
|
new = ctx->basic_blocks;
|
|
|
|
ctx->basic_blocks = ctx->basic_blocks->next;
|
|
|
|
frags = total_size / new_size;
|
|
|
|
ctx->stats[new_size].blocks++;
|
|
|
|
ctx->stats[new_size].freefrags += frags;
|
|
|
|
/* Set up a linked-list of blocks of size "new_size". */
|
|
|
|
curr = new;
|
|
|
|
next = curr + new_size;
|
|
|
|
for (i = 0; i < (frags - 1); i++) {
|
1998-10-21 22:01:08 +00:00
|
|
|
((element *)curr)->next = next;
|
1998-08-17 22:05:58 +00:00
|
|
|
curr = next;
|
|
|
|
next += new_size;
|
|
|
|
}
|
|
|
|
/* curr is now pointing at the last block in the array. */
|
1998-10-21 22:01:08 +00:00
|
|
|
((element *)curr)->next = NULL;
|
1998-08-17 22:05:58 +00:00
|
|
|
ctx->freelists[new_size] = new;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The free list uses the "rounded-up" size "new_size": */
|
|
|
|
ret = ctx->freelists[new_size];
|
|
|
|
ctx->freelists[new_size] = ctx->freelists[new_size]->next;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The stats[] uses the _actual_ "size" requested by the
|
|
|
|
* caller, with the caveat (in the code above) that "size" >= the
|
|
|
|
* max. size (max_size) ends up getting recorded as a call to
|
|
|
|
* max_size.
|
|
|
|
*/
|
|
|
|
ctx->stats[size].gets++;
|
|
|
|
ctx->stats[size].totalgets++;
|
|
|
|
ctx->stats[new_size].freefrags--;
|
|
|
|
|
|
|
|
done:
|
|
|
|
UNLOCK_CONTEXT(ctx);
|
|
|
|
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This is a call from an external caller,
|
|
|
|
* so we want to count this as a user "put".
|
|
|
|
*/
|
|
|
|
void
|
1998-10-21 22:01:08 +00:00
|
|
|
__isc_mem_put(isc_memctx_t ctx, void *mem, size_t size) {
|
1998-08-17 22:05:58 +00:00
|
|
|
size_t new_size = quantize(size);
|
|
|
|
|
|
|
|
REQUIRE(size > 0);
|
|
|
|
|
|
|
|
LOCK_CONTEXT(ctx);
|
|
|
|
|
|
|
|
if (size == ctx->max_size || new_size >= ctx->max_size) {
|
|
|
|
/* memput() called on something beyond our upper limit */
|
|
|
|
free(mem);
|
|
|
|
INSIST(ctx->stats[ctx->max_size].gets != 0);
|
|
|
|
ctx->stats[ctx->max_size].gets--;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The free list uses the "rounded-up" size "new_size": */
|
1998-10-21 22:01:08 +00:00
|
|
|
((element *)mem)->next = ctx->freelists[new_size];
|
|
|
|
ctx->freelists[new_size] = (element *)mem;
|
1998-08-17 22:05:58 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* The stats[] uses the _actual_ "size" requested by the
|
|
|
|
* caller, with the caveat (in the code above) that "size" >= the
|
|
|
|
* max. size (max_size) ends up getting recorded as a call to
|
|
|
|
* max_size.
|
|
|
|
*/
|
|
|
|
INSIST(ctx->stats[size].gets != 0);
|
|
|
|
ctx->stats[size].gets--;
|
|
|
|
ctx->stats[new_size].freefrags++;
|
|
|
|
|
|
|
|
done:
|
|
|
|
UNLOCK_CONTEXT(ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
1998-10-21 22:01:08 +00:00
|
|
|
__isc_mem_getdebug(isc_memctx_t ctx, size_t size, const char *file, int line) {
|
1998-08-17 22:05:58 +00:00
|
|
|
void *ptr;
|
1998-10-21 22:01:08 +00:00
|
|
|
|
|
|
|
ptr = __isc_mem_get(ctx, size);
|
1998-08-17 22:05:58 +00:00
|
|
|
fprintf(stderr, "%s:%d: mem_get(%p, %lu) -> %p\n", file, line,
|
1998-08-18 00:29:57 +00:00
|
|
|
ctx, (unsigned long)size, ptr);
|
1998-08-17 22:05:58 +00:00
|
|
|
return (ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-10-21 22:01:08 +00:00
|
|
|
__isc_mem_putdebug(isc_memctx_t ctx, void *ptr, size_t size, const char *file,
|
|
|
|
int line)
|
1998-08-17 22:05:58 +00:00
|
|
|
{
|
|
|
|
fprintf(stderr, "%s:%d: mem_put(%p, %p, %lu)\n", file, line,
|
1998-08-18 00:29:57 +00:00
|
|
|
ctx, ptr, (unsigned long)size);
|
1998-10-21 22:01:08 +00:00
|
|
|
__isc_mem_put(ctx, ptr, size);
|
1998-08-17 22:05:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Print the stats[] on the stream "out" with suitable formatting.
|
|
|
|
*/
|
|
|
|
void
|
1998-10-21 22:01:08 +00:00
|
|
|
isc_mem_stats(isc_memctx_t ctx, FILE *out) {
|
1998-08-17 22:05:58 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
LOCK_CONTEXT(ctx);
|
|
|
|
|
|
|
|
if (ctx->freelists == NULL)
|
|
|
|
return;
|
|
|
|
for (i = 1; i <= ctx->max_size; i++) {
|
|
|
|
const struct stats *s = &ctx->stats[i];
|
|
|
|
|
|
|
|
if (s->totalgets == 0 && s->gets == 0)
|
|
|
|
continue;
|
|
|
|
fprintf(out, "%s%5d: %11lu gets, %11lu rem",
|
|
|
|
(i == ctx->max_size) ? ">=" : " ",
|
|
|
|
i, s->totalgets, s->gets);
|
|
|
|
if (s->blocks != 0)
|
|
|
|
fprintf(out, " (%lu bl, %lu ff)",
|
|
|
|
s->blocks, s->freefrags);
|
|
|
|
fputc('\n', out);
|
|
|
|
}
|
|
|
|
|
|
|
|
UNLOCK_CONTEXT(ctx);
|
|
|
|
}
|
|
|
|
|
1998-10-21 22:01:08 +00:00
|
|
|
isc_boolean_t
|
|
|
|
isc_mem_valid(isc_memctx_t ctx, void *ptr) {
|
1998-08-18 00:29:57 +00:00
|
|
|
unsigned char *cp = ptr;
|
1998-10-21 22:01:08 +00:00
|
|
|
isc_boolean_t result = ISC_FALSE;
|
1998-08-17 22:05:58 +00:00
|
|
|
|
|
|
|
LOCK_CONTEXT(ctx);
|
|
|
|
|
|
|
|
if (ctx->lowest != NULL && cp >= ctx->lowest && cp <= ctx->highest)
|
1998-10-21 22:01:08 +00:00
|
|
|
result = ISC_TRUE;
|
1998-08-17 22:05:58 +00:00
|
|
|
|
|
|
|
UNLOCK_CONTEXT(ctx);
|
|
|
|
|
1998-10-21 22:01:08 +00:00
|
|
|
return (result);
|
1998-08-17 22:05:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Replacements for malloc() and free().
|
|
|
|
*/
|
|
|
|
|
|
|
|
void *
|
1998-10-21 22:01:08 +00:00
|
|
|
isc_mem_allocate(isc_memctx_t ctx, size_t size) {
|
1998-08-17 22:05:58 +00:00
|
|
|
size_info si;
|
|
|
|
|
|
|
|
size += ALIGNMENT_SIZE;
|
1998-10-21 22:01:08 +00:00
|
|
|
si = isc_mem_get(ctx, size);
|
1998-08-17 22:05:58 +00:00
|
|
|
if (si == NULL)
|
|
|
|
return (NULL);
|
|
|
|
si->size = size;
|
|
|
|
return (&si[1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1998-10-21 22:01:08 +00:00
|
|
|
isc_mem_free(isc_memctx_t ctx, void *ptr) {
|
1998-08-17 22:05:58 +00:00
|
|
|
size_info si;
|
|
|
|
|
|
|
|
si = &(((size_info)ptr)[-1]);
|
1998-10-21 22:01:08 +00:00
|
|
|
isc_mem_put(ctx, si, si->size);
|
1998-08-17 22:05:58 +00:00
|
|
|
}
|
|
|
|
|
1998-10-21 22:01:08 +00:00
|
|
|
#ifdef ISC_MEMCLUSTER_LEGACY
|
|
|
|
|
1998-08-17 22:05:58 +00:00
|
|
|
/*
|
|
|
|
* Public Legacy.
|
|
|
|
*/
|
|
|
|
|
1998-10-21 22:01:08 +00:00
|
|
|
static isc_memctx_t default_context = NULL;
|
|
|
|
|
1998-08-17 22:05:58 +00:00
|
|
|
int
|
|
|
|
meminit(size_t init_max_size, size_t target_size) {
|
|
|
|
/* need default_context lock here */
|
|
|
|
if (default_context != NULL)
|
|
|
|
return (-1);
|
1998-10-22 01:33:20 +00:00
|
|
|
return (isc_mem_create(init_max_size, target_size, &default_context));
|
1998-08-17 22:05:58 +00:00
|
|
|
}
|
|
|
|
|
1998-10-21 22:01:08 +00:00
|
|
|
isc_memctx_t
|
1998-08-17 22:05:58 +00:00
|
|
|
mem_default_context(void) {
|
|
|
|
/* need default_context lock here */
|
|
|
|
if (default_context == NULL && meminit(0, 0) == -1)
|
|
|
|
return (NULL);
|
|
|
|
return (default_context);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
__memget(size_t size) {
|
|
|
|
/* need default_context lock here */
|
|
|
|
if (default_context == NULL && meminit(0, 0) == -1)
|
|
|
|
return (NULL);
|
|
|
|
return (__mem_get(default_context, size));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
__memput(void *mem, size_t size) {
|
|
|
|
/* need default_context lock here */
|
|
|
|
REQUIRE(default_context != NULL);
|
|
|
|
__mem_put(default_context, mem, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void *
|
|
|
|
__memget_debug(size_t size, const char *file, int line) {
|
|
|
|
void *ptr;
|
|
|
|
ptr = __memget(size);
|
|
|
|
fprintf(stderr, "%s:%d: memget(%lu) -> %p\n", file, line,
|
1998-08-18 00:29:57 +00:00
|
|
|
(unsigned long)size, ptr);
|
1998-08-17 22:05:58 +00:00
|
|
|
return (ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
__memput_debug(void *ptr, size_t size, const char *file, int line) {
|
|
|
|
fprintf(stderr, "%s:%d: memput(%p, %lu)\n", file, line,
|
1998-08-18 00:29:57 +00:00
|
|
|
ptr, (unsigned long)size);
|
1998-08-17 22:05:58 +00:00
|
|
|
__memput(ptr, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
memvalid(void *ptr) {
|
|
|
|
/* need default_context lock here */
|
|
|
|
REQUIRE(default_context != NULL);
|
|
|
|
return (mem_valid(default_context, ptr));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
memstats(FILE *out) {
|
|
|
|
/* need default_context lock here */
|
|
|
|
REQUIRE(default_context != NULL);
|
|
|
|
mem_stats(default_context, out);
|
|
|
|
}
|
1998-10-21 22:01:08 +00:00
|
|
|
|
|
|
|
#endif /* ISC_MEMCLUSTER_LEGACY */
|