mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-09-01 06:55:30 +00:00
Revamp memory stuff.
Now, if you define ISC_MEM_TRACKLINES, and set isc_mem_debugging = 2 first thing in main(), isc_mem_stats() will dump the file/line where any leaking allocations were made.
This commit is contained in:
@@ -15,7 +15,7 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: mem.h,v 1.37 2000/06/28 03:46:37 tale Exp $ */
|
/* $Id: mem.h,v 1.38 2000/07/26 19:06:20 explorer Exp $ */
|
||||||
|
|
||||||
#ifndef ISC_MEM_H
|
#ifndef ISC_MEM_H
|
||||||
#define ISC_MEM_H 1
|
#define ISC_MEM_H 1
|
||||||
@@ -37,28 +37,82 @@ typedef void (*isc_memfree_t)(void *, void *);
|
|||||||
#if !defined(ISC_MEM_DEBUG) && !defined(ISC_MEM_DEBUGOFF)
|
#if !defined(ISC_MEM_DEBUG) && !defined(ISC_MEM_DEBUGOFF)
|
||||||
#define ISC_MEM_DEBUG
|
#define ISC_MEM_DEBUG
|
||||||
#endif
|
#endif
|
||||||
extern isc_boolean_t isc_mem_debugging;
|
|
||||||
|
/*
|
||||||
|
* Define ISC_MEM_TRACKLINES to turn on detailed tracing of memory allocation
|
||||||
|
* and freeing by file and line number.
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
#define ISC_MEM_TRACKLINES
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define ISC_MEM_CHECKOVERRUN to turn on checks for using memory outside
|
||||||
|
* the requested space. This will increase the size of each allocation.
|
||||||
|
*/
|
||||||
|
#if 0
|
||||||
|
#define ISC_MEM_CHECKOVERRUN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define ISC_MEM_FILL to fill each block of memory returned to the system
|
||||||
|
* with the byte string '0xbe'. This helps track down uninitialized pointers
|
||||||
|
* and the like. On freeing memory, the space is filled with '0xde' for
|
||||||
|
* the same reasons.
|
||||||
|
*/
|
||||||
|
#define ISC_MEM_FILL
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Define this to turn on memory pool names.
|
||||||
|
*/
|
||||||
|
#define ISC_MEMPOOL_NAMES
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _DEBUGTRACE
|
||||||
|
* log (to isc_lctx) each allocation and free.
|
||||||
|
*
|
||||||
|
* _DEBUGRECORD
|
||||||
|
* remember each allocation, and match them up on free. Crash if
|
||||||
|
* a free doesn't match an allocation
|
||||||
|
*/
|
||||||
|
extern unsigned int isc_mem_debugging;
|
||||||
|
#define ISC_MEM_DEBUGTRACE 0x00000001U
|
||||||
|
#define ISC_MEM_DEBUGRECORD 0x00000002U
|
||||||
|
|
||||||
|
#ifdef ISC_MEM_TRACKLINES
|
||||||
|
#define _ISC_MEM_FILELINE , __FILE__, __LINE__
|
||||||
|
#define _ISC_MEM_FLARG , const char *, int
|
||||||
|
#else
|
||||||
|
#define _ISC_MEM_FILELINE
|
||||||
|
#define _ISC_MEM_FLARG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define isc_mem_get(c, s) isc__mem_get((c), (s) _ISC_MEM_FILELINE)
|
||||||
|
#define isc_mem_allocate(c, s) isc__mem_allocate((c), (s) _ISC_MEM_FILELINE)
|
||||||
|
#define isc_mem_strdup(c, p) isc__mem_strdup((c), (p) _ISC_MEM_FILELINE)
|
||||||
|
#define isc_mempool_get(c) isc__mempool_get((c) _ISC_MEM_FILELINE)
|
||||||
|
|
||||||
#ifdef ISC_MEM_DEBUG
|
#ifdef ISC_MEM_DEBUG
|
||||||
#define isc_mem_get(c, s) isc__mem_getdebug(c, s, __FILE__, __LINE__)
|
#define isc_mem_put(c, p, s) \
|
||||||
#define isc_mem_put(c, p, s) isc__mem_putdebug(c, p, s, __FILE__, __LINE__)
|
do { \
|
||||||
#define isc_mem_allocate(c, s) isc__mem_allocatedebug(c, s, \
|
isc__mem_put((c), (p), (s) _ISC_MEM_FILELINE); \
|
||||||
__FILE__, __LINE__)
|
(p) = NULL; \
|
||||||
#define isc_mem_free(c, p) isc__mem_freedebug(c, p, __FILE__, __LINE__)
|
} while (0)
|
||||||
#define isc_mem_strdup(c, p) isc__mem_strdupdebug(c, p, \
|
#define isc_mem_free(c, p) \
|
||||||
__FILE__, __LINE__)
|
do { \
|
||||||
#define isc_mempool_get(c) isc__mempool_getdebug(c, __FILE__, __LINE__)
|
isc__mem_free((c), (p) _ISC_MEM_FILELINE); \
|
||||||
#define isc_mempool_put(c, p) isc__mempool_putdebug(c, p, \
|
(p) = NULL; \
|
||||||
__FILE__, __LINE__)
|
} while (0)
|
||||||
|
#define isc_mempool_put(c, p) \
|
||||||
|
do { \
|
||||||
|
isc__mempool_put((c), (p) _ISC_MEM_FILELINE); \
|
||||||
|
(p) = NULL; \
|
||||||
|
} while (0)
|
||||||
#else
|
#else
|
||||||
#define isc_mem_get isc__mem_get
|
#define isc_mem_put(c, p, s) isc__mem_put((c), (p), (s) _ISC_MEM_FILELINE)
|
||||||
#define isc_mem_put isc__mem_put
|
#define isc_mem_free(c, p) isc__mem_free((c), (p) _ISC_MEM_FILELINE)
|
||||||
#define isc_mem_allocate isc__mem_allocate
|
#define isc_mempool_put(c, p) isc__mempool_put((c), (p) _ISC_MEM_FILELINE)
|
||||||
#define isc_mem_free isc__mem_free
|
#endif
|
||||||
#define isc_mem_strdup isc__mem_strdup
|
|
||||||
#define isc_mempool_get isc__mempool_get
|
|
||||||
#define isc_mempool_put isc__mempool_put
|
|
||||||
#endif /* ISC_MEM_DEBUG */
|
|
||||||
|
|
||||||
isc_result_t isc_mem_create(size_t, size_t, isc_mem_t **);
|
isc_result_t isc_mem_create(size_t, size_t, isc_mem_t **);
|
||||||
void isc_mem_attach(isc_mem_t *, isc_mem_t **);
|
void isc_mem_attach(isc_mem_t *, isc_mem_t **);
|
||||||
@@ -67,25 +121,19 @@ void isc_mem_destroy(isc_mem_t **);
|
|||||||
isc_result_t isc_mem_ondestroy(isc_mem_t *ctx,
|
isc_result_t isc_mem_ondestroy(isc_mem_t *ctx,
|
||||||
isc_task_t *task,
|
isc_task_t *task,
|
||||||
isc_event_t **event);
|
isc_event_t **event);
|
||||||
void * isc__mem_get(isc_mem_t *, size_t);
|
void * isc__mem_get(isc_mem_t *, size_t
|
||||||
void isc__mem_put(isc_mem_t *, void *, size_t);
|
_ISC_MEM_FLARG);
|
||||||
void * isc__mem_getdebug(isc_mem_t *, size_t,
|
void isc__mem_put(isc_mem_t *, void *,
|
||||||
const char *, int);
|
size_t _ISC_MEM_FLARG);
|
||||||
void isc__mem_putdebug(isc_mem_t *, void *,
|
|
||||||
size_t, const char *, int);
|
|
||||||
isc_result_t isc_mem_preallocate(isc_mem_t *);
|
isc_result_t isc_mem_preallocate(isc_mem_t *);
|
||||||
void isc_mem_stats(isc_mem_t *, FILE *);
|
void isc_mem_stats(isc_mem_t *, FILE *);
|
||||||
isc_boolean_t isc_mem_valid(isc_mem_t *, void *);
|
isc_boolean_t isc_mem_valid(isc_mem_t *, void *);
|
||||||
void * isc__mem_allocate(isc_mem_t *, size_t);
|
void * isc__mem_allocate(isc_mem_t *, size_t
|
||||||
void * isc__mem_allocatedebug(isc_mem_t *, size_t,
|
_ISC_MEM_FLARG);
|
||||||
const char *, int);
|
void isc__mem_free(isc_mem_t *, void *
|
||||||
void isc__mem_free(isc_mem_t *, void *);
|
_ISC_MEM_FLARG);
|
||||||
void isc__mem_freedebug(isc_mem_t *, void *,
|
char * isc__mem_strdup(isc_mem_t *, const char *
|
||||||
const char *, int);
|
_ISC_MEM_FLARG);
|
||||||
char * isc__mem_strdup(isc_mem_t *, const char *);
|
|
||||||
char * isc__mem_strdupdebug(isc_mem_t *,
|
|
||||||
const char *,
|
|
||||||
const char *, int);
|
|
||||||
void isc_mem_setdestroycheck(isc_mem_t *,
|
void isc_mem_setdestroycheck(isc_mem_t *,
|
||||||
isc_boolean_t);
|
isc_boolean_t);
|
||||||
void isc_mem_setsplit(isc_mem_t *, isc_boolean_t);
|
void isc_mem_setsplit(isc_mem_t *, isc_boolean_t);
|
||||||
@@ -99,38 +147,6 @@ isc_result_t isc_mem_createx(size_t, size_t,
|
|||||||
void *arg, isc_mem_t **);
|
void *arg, isc_mem_t **);
|
||||||
isc_result_t isc_mem_restore(isc_mem_t *);
|
isc_result_t isc_mem_restore(isc_mem_t *);
|
||||||
|
|
||||||
#ifdef ISC_MEMCLUSTER_LEGACY
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Legacy.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define meminit isc__legacy_meminit
|
|
||||||
#define mem_default_context isc__legacy_mem_default_context
|
|
||||||
#ifdef MEMCLUSTER_DEBUG
|
|
||||||
#define memget(s) isc__legacy_memget_debug(s, __FILE__, __LINE__)
|
|
||||||
#define memput(p, s) isc__legacy_memput_debug(p, s, \
|
|
||||||
__FILE__, __LINE__)
|
|
||||||
#else
|
|
||||||
#define memget isc__legacy_memget
|
|
||||||
#define memput isc__legacy_memput
|
|
||||||
#endif
|
|
||||||
#define memvalid isc__legacy_memvalid
|
|
||||||
#define memstats isc__legacy_memstats
|
|
||||||
|
|
||||||
int meminit(size_t, size_t);
|
|
||||||
isc_mem_t * mem_default_context(void);
|
|
||||||
void * isc__legacy_memget(size_t);
|
|
||||||
void isc__legacy_memput(void *, size_t);
|
|
||||||
void * isc__legacy_memget_debug(size_t, const char *,
|
|
||||||
int);
|
|
||||||
void isc__legacy_memput_debug(void *, size_t,
|
|
||||||
const char *, int);
|
|
||||||
int memvalid(void *);
|
|
||||||
void memstats(FILE *);
|
|
||||||
|
|
||||||
#endif /* ISC_MEMCLUSTER_LEGACY */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Memory pools
|
* Memory pools
|
||||||
*/
|
*/
|
||||||
@@ -139,11 +155,8 @@ void memstats(FILE *);
|
|||||||
* Internal (but public) functions. Don't call these from application
|
* Internal (but public) functions. Don't call these from application
|
||||||
* code. Use isc_mempool_get() and isc_mempool_put() instead.
|
* code. Use isc_mempool_get() and isc_mempool_put() instead.
|
||||||
*/
|
*/
|
||||||
void * isc__mempool_get(isc_mempool_t *);
|
void * isc__mempool_get(isc_mempool_t * _ISC_MEM_FLARG);
|
||||||
void isc__mempool_put(isc_mempool_t *, void *);
|
void isc__mempool_put(isc_mempool_t *, void * _ISC_MEM_FLARG);
|
||||||
void * isc__mempool_getdebug(isc_mempool_t *, const char *, int);
|
|
||||||
void isc__mempool_putdebug(isc_mempool_t *, void *,
|
|
||||||
const char *, int);
|
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp);
|
isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp);
|
||||||
|
434
lib/isc/mem.c
434
lib/isc/mem.c
@@ -15,7 +15,7 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: mem.c,v 1.53 2000/06/26 20:27:42 bwelling Exp $ */
|
/* $Id: mem.c,v 1.54 2000/07/26 19:06:19 explorer Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@@ -37,26 +37,7 @@
|
|||||||
#define UNLOCK(l)
|
#define UNLOCK(l)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
isc_boolean_t isc_mem_debugging = ISC_FALSE;
|
unsigned int isc_mem_debugging = 0;
|
||||||
|
|
||||||
#ifndef ISC_MEM_FILL
|
|
||||||
/*
|
|
||||||
* XXXMPA
|
|
||||||
* We want this on during development to catch:
|
|
||||||
* 1. some reference after free bugs.
|
|
||||||
* 2. some failure to initalise bugs.
|
|
||||||
*/
|
|
||||||
#define ISC_MEM_FILL 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ISC_MEMPOOL_NAMES
|
|
||||||
/*
|
|
||||||
* During development it is nice to be able to see names associated with
|
|
||||||
* memory pools.
|
|
||||||
*/
|
|
||||||
#define ISC_MEMPOOL_NAMES 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Constants.
|
* Constants.
|
||||||
@@ -67,13 +48,29 @@ isc_boolean_t isc_mem_debugging = ISC_FALSE;
|
|||||||
#define ALIGNMENT_SIZE 8
|
#define ALIGNMENT_SIZE 8
|
||||||
#define NUM_BASIC_BLOCKS 64 /* must be > 1 */
|
#define NUM_BASIC_BLOCKS 64 /* must be > 1 */
|
||||||
#define TABLE_INCREMENT 1024
|
#define TABLE_INCREMENT 1024
|
||||||
|
#define DEBUGLIST_COUNT 1024
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Types.
|
* Types.
|
||||||
*/
|
*/
|
||||||
|
#ifdef ISC_MEM_TRACKLINES
|
||||||
|
typedef struct debuglink debuglink_t;
|
||||||
|
struct debuglink {
|
||||||
|
ISC_LINK(debuglink_t) link;
|
||||||
|
const void *ptr[DEBUGLIST_COUNT];
|
||||||
|
const char *file[DEBUGLIST_COUNT];
|
||||||
|
unsigned int line[DEBUGLIST_COUNT];
|
||||||
|
unsigned int count;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define FLARG_PASS , file, line
|
||||||
|
#define FLARG , const char *file, int line
|
||||||
|
#else
|
||||||
|
#define FLARG_PASS
|
||||||
|
#define FLARG
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct element element;
|
typedef struct element element;
|
||||||
|
|
||||||
struct element {
|
struct element {
|
||||||
element * next;
|
element * next;
|
||||||
};
|
};
|
||||||
@@ -122,6 +119,9 @@ struct isc_mem {
|
|||||||
size_t total;
|
size_t total;
|
||||||
size_t inuse;
|
size_t inuse;
|
||||||
ISC_LIST(isc_mempool_t) pools;
|
ISC_LIST(isc_mempool_t) pools;
|
||||||
|
#ifdef ISC_MEM_TRACKLINES
|
||||||
|
ISC_LIST(debuglink_t) debuglist;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MEMPOOL_MAGIC 0x4D454d70U /* MEMp. */
|
#define MEMPOOL_MAGIC 0x4D454d70U /* MEMp. */
|
||||||
@@ -145,7 +145,7 @@ struct isc_mempool {
|
|||||||
/* Stats only. */
|
/* Stats only. */
|
||||||
unsigned int gets; /* # of requests to this pool */
|
unsigned int gets; /* # of requests to this pool */
|
||||||
/* Debugging only. */
|
/* Debugging only. */
|
||||||
#if ISC_MEMPOOL_NAMES
|
#ifdef ISC_MEMPOOL_NAMES
|
||||||
char name[16]; /* printed name in stats reports */
|
char name[16]; /* printed name in stats reports */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
@@ -154,6 +154,111 @@ struct isc_mempool {
|
|||||||
* Private Inline-able.
|
* Private Inline-able.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifndef ISC_MEM_TRACKLINES
|
||||||
|
#define ADD_TRACE(a, b, c, d, e)
|
||||||
|
#define DELETE_TRACE(a, b, c, d, e)
|
||||||
|
#else
|
||||||
|
#define ADD_TRACE(a, b, c, d, e) add_trace_entry(a, b, c, d, e)
|
||||||
|
#define DELETE_TRACE(a, b, c, d, e) delete_trace_entry(a, b, c, d, e)
|
||||||
|
|
||||||
|
#define MEM_TRACE ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)
|
||||||
|
#define MEM_RECORD ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* mctx must be locked.
|
||||||
|
*/
|
||||||
|
static inline void
|
||||||
|
add_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size
|
||||||
|
const char *file, int line)
|
||||||
|
{
|
||||||
|
debuglink_t *dl;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (MEM_TRACE)
|
||||||
|
fprintf(stderr, "add %p size %u file %s line %u\n",
|
||||||
|
ptr, size, file, line);
|
||||||
|
|
||||||
|
if (!MEM_RECORD)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dl = ISC_LIST_HEAD(mctx->debuglist);
|
||||||
|
while (dl != NULL) {
|
||||||
|
if (dl->count == DEBUGLIST_COUNT)
|
||||||
|
goto next;
|
||||||
|
for (i = 0 ; i < DEBUGLIST_COUNT ; i++) {
|
||||||
|
if (dl->ptr[i] == NULL) {
|
||||||
|
dl->ptr[i] = ptr;
|
||||||
|
dl->file[i] = file;
|
||||||
|
dl->line[i] = line;
|
||||||
|
dl->count++;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next:
|
||||||
|
dl = ISC_LIST_NEXT(dl, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
dl = malloc(sizeof(debuglink_t));
|
||||||
|
INSIST(dl != NULL);
|
||||||
|
|
||||||
|
ISC_LINK_INIT(dl, link);
|
||||||
|
for (i = 1 ; i < DEBUGLIST_COUNT ; i++) {
|
||||||
|
dl->ptr[i] = NULL;
|
||||||
|
dl->file[i] = NULL;
|
||||||
|
dl->line[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
dl->ptr[0] = ptr;
|
||||||
|
dl->file[0] = file;
|
||||||
|
dl->line[0] = line;
|
||||||
|
dl->count = 1;
|
||||||
|
|
||||||
|
ISC_LIST_PREPEND(mctx->debuglist, dl, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
delete_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size,
|
||||||
|
const char *file, unsigned int line)
|
||||||
|
{
|
||||||
|
debuglink_t *dl;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if (MEM_TRACE)
|
||||||
|
fprintf(stderr, "del %p size %u file %s line %u\n",
|
||||||
|
ptr, size, file, line);
|
||||||
|
|
||||||
|
if (!MEM_RECORD)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dl = ISC_LIST_HEAD(mctx->debuglist);
|
||||||
|
while (dl != NULL) {
|
||||||
|
for (i = 0 ; i < DEBUGLIST_COUNT ; i++) {
|
||||||
|
if (dl->ptr[i] == ptr) {
|
||||||
|
dl->ptr[i] = NULL;
|
||||||
|
dl->file[i] = NULL;
|
||||||
|
dl->line[i] = 0;
|
||||||
|
|
||||||
|
INSIST(dl->count > 0);
|
||||||
|
dl->count--;
|
||||||
|
if (dl->count == 0) {
|
||||||
|
ISC_LIST_UNLINK(mctx->debuglist,
|
||||||
|
dl, link);
|
||||||
|
free(dl);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dl = ISC_LIST_NEXT(dl, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we get here, we didn't find the item on the list. We're
|
||||||
|
* screwed.
|
||||||
|
*/
|
||||||
|
INSIST(dl != NULL);
|
||||||
|
}
|
||||||
|
#endif /* ISC_MEM_TRACKLINES */
|
||||||
|
|
||||||
static inline size_t
|
static inline size_t
|
||||||
quantize(size_t size) {
|
quantize(size_t size) {
|
||||||
int temp;
|
int temp;
|
||||||
@@ -412,7 +517,7 @@ mem_getunlocked(isc_mem_t *ctx, size_t size) {
|
|||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
#if ISC_MEM_FILL
|
#ifdef ISC_MEM_FILL
|
||||||
if (ret != NULL)
|
if (ret != NULL)
|
||||||
memset(ret, 0xbe, new_size); /* Mnemonic for "beef". */
|
memset(ret, 0xbe, new_size); /* Mnemonic for "beef". */
|
||||||
#endif
|
#endif
|
||||||
@@ -428,7 +533,7 @@ mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) {
|
|||||||
/*
|
/*
|
||||||
* memput() called on something beyond our upper limit.
|
* memput() called on something beyond our upper limit.
|
||||||
*/
|
*/
|
||||||
#if ISC_MEM_FILL
|
#ifdef ISC_MEM_FILL
|
||||||
memset(mem, 0xde, size); /* Mnemonic for "dead". */
|
memset(mem, 0xde, size); /* Mnemonic for "dead". */
|
||||||
#endif
|
#endif
|
||||||
(ctx->memfree)(ctx->arg, mem);
|
(ctx->memfree)(ctx->arg, mem);
|
||||||
@@ -440,8 +545,8 @@ mem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ISC_MEM_FILL
|
#ifdef ISC_MEM_FILL
|
||||||
#if ISC_MEM_CHECKOVERRUN
|
#ifdef ISC_MEM_CHECKOVERRUN
|
||||||
check_overrun(mem, size, new_size);
|
check_overrun(mem, size, new_size);
|
||||||
#endif
|
#endif
|
||||||
memset(mem, 0xde, new_size); /* Mnemonic for "dead". */
|
memset(mem, 0xde, new_size); /* Mnemonic for "dead". */
|
||||||
@@ -549,6 +654,9 @@ isc_mem_createx(size_t init_max_size, size_t target_size,
|
|||||||
ctx->magic = MEM_MAGIC;
|
ctx->magic = MEM_MAGIC;
|
||||||
isc_ondestroy_init(&ctx->ondestroy);
|
isc_ondestroy_init(&ctx->ondestroy);
|
||||||
ISC_LIST_INIT(ctx->pools);
|
ISC_LIST_INIT(ctx->pools);
|
||||||
|
#ifdef ISC_MEM_TRACKLINES
|
||||||
|
ISC_LIST_INIT(ctx->debuglist);
|
||||||
|
#endif
|
||||||
|
|
||||||
*ctxp = ctx;
|
*ctxp = ctx;
|
||||||
return (ISC_R_SUCCESS);
|
return (ISC_R_SUCCESS);
|
||||||
@@ -571,6 +679,9 @@ destroy(isc_mem_t *ctx) {
|
|||||||
ctx->magic = 0;
|
ctx->magic = 0;
|
||||||
|
|
||||||
INSIST(ISC_LIST_EMPTY(ctx->pools));
|
INSIST(ISC_LIST_EMPTY(ctx->pools));
|
||||||
|
#ifdef ISC_MEM_TRACKLINES
|
||||||
|
INSIST(ISC_LIST_EMPTY(ctx->debuglist));
|
||||||
|
#endif
|
||||||
INSIST(ctx->references == 0);
|
INSIST(ctx->references == 0);
|
||||||
|
|
||||||
if (ctx->checkfree) {
|
if (ctx->checkfree) {
|
||||||
@@ -683,20 +794,7 @@ isc_mem_restore(isc_mem_t *ctx) {
|
|||||||
return (result);
|
return (result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
#if defined(ISC_MEM_FILL) && defined(ISC_MEM_CHECKOVERRUN)
|
||||||
isc__mem_get(isc_mem_t *ctx, size_t size) {
|
|
||||||
void *ret;
|
|
||||||
|
|
||||||
REQUIRE(VALID_CONTEXT(ctx));
|
|
||||||
|
|
||||||
LOCK(&ctx->lock);
|
|
||||||
ret = mem_getunlocked(ctx, size);
|
|
||||||
UNLOCK(&ctx->lock);
|
|
||||||
|
|
||||||
return (ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if ISC_MEM_FILL != 0 && ISC_MEM_CHECKOVERRUN != 0
|
|
||||||
static inline void
|
static inline void
|
||||||
check_overrun(void *mem, size_t size, size_t new_size) {
|
check_overrun(void *mem, size_t size, size_t new_size) {
|
||||||
unsigned char *cp;
|
unsigned char *cp;
|
||||||
@@ -711,34 +809,29 @@ check_overrun(void *mem, size_t size, size_t new_size) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void *
|
||||||
isc__mem_put(isc_mem_t *ctx, void *mem, size_t size) {
|
isc__mem_get(isc_mem_t *ctx, size_t size FLARG) {
|
||||||
|
void *ptr;
|
||||||
|
|
||||||
REQUIRE(VALID_CONTEXT(ctx));
|
REQUIRE(VALID_CONTEXT(ctx));
|
||||||
|
|
||||||
LOCK(&ctx->lock);
|
LOCK(&ctx->lock);
|
||||||
mem_putunlocked(ctx, mem, size);
|
ptr = mem_getunlocked(ctx, size);
|
||||||
|
ADD_TRACE(ctx, ptr, size, file, line);
|
||||||
UNLOCK(&ctx->lock);
|
UNLOCK(&ctx->lock);
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
isc__mem_getdebug(isc_mem_t *ctx, size_t size, const char *file, int line) {
|
|
||||||
void *ptr;
|
|
||||||
|
|
||||||
ptr = isc__mem_get(ctx, size);
|
|
||||||
if (isc_mem_debugging)
|
|
||||||
fprintf(stderr, "%s:%d: mem_get(%p, %lu) -> %p\n", file, line,
|
|
||||||
ctx, (unsigned long)size, ptr);
|
|
||||||
return (ptr);
|
return (ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__mem_putdebug(isc_mem_t *ctx, void *ptr, size_t size, const char *file,
|
isc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG)
|
||||||
int line)
|
|
||||||
{
|
{
|
||||||
if (isc_mem_debugging)
|
REQUIRE(VALID_CONTEXT(ctx));
|
||||||
fprintf(stderr, "%s:%d: mem_put(%p, %p, %lu)\n", file, line,
|
REQUIRE(ptr != NULL);
|
||||||
ctx, ptr, (unsigned long)size);
|
|
||||||
isc__mem_put(ctx, ptr, size);
|
LOCK(&ctx->lock);
|
||||||
|
DELETE_TRACE(ctx, ptr, size, file, line);
|
||||||
|
mem_putunlocked(ctx, ptr, size);
|
||||||
|
UNLOCK(&ctx->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
isc_result_t
|
isc_result_t
|
||||||
@@ -816,6 +909,27 @@ isc_mem_stats(isc_mem_t *ctx, FILE *out) {
|
|||||||
pool = ISC_LIST_NEXT(pool, link);
|
pool = ISC_LIST_NEXT(pool, link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ISC_MEM_TRACKLINES
|
||||||
|
if (isc_mem_debugging > 1) {
|
||||||
|
debuglink_t *dl;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
fprintf(out, "DUMP OF ALL OUTSTANDING MEMORY ALLOCATIONS\n");
|
||||||
|
dl = ISC_LIST_HEAD(ctx->debuglist);
|
||||||
|
if (dl == NULL)
|
||||||
|
fprintf(out, "\tNone.\n");
|
||||||
|
while (dl != NULL) {
|
||||||
|
for (i = 0 ; i < DEBUGLIST_COUNT ; i++)
|
||||||
|
if (dl->ptr[i] != NULL)
|
||||||
|
fprintf(out,
|
||||||
|
"\tptr %p file %s line %u\n",
|
||||||
|
dl->ptr[i], dl->file[i],
|
||||||
|
dl->line[i]);
|
||||||
|
dl = ISC_LIST_NEXT(dl, link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
UNLOCK(&ctx->lock);
|
UNLOCK(&ctx->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -840,12 +954,12 @@ isc_mem_valid(isc_mem_t *ctx, void *ptr) {
|
|||||||
* size of the object allocated (with some additional overhead).
|
* size of the object allocated (with some additional overhead).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void *
|
static void *
|
||||||
isc__mem_allocate(isc_mem_t *ctx, size_t size) {
|
isc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) {
|
||||||
size_info *si;
|
size_info *si;
|
||||||
|
|
||||||
size += ALIGNMENT_SIZE;
|
size += ALIGNMENT_SIZE;
|
||||||
si = isc__mem_get(ctx, size);
|
si = mem_getunlocked(ctx, size);
|
||||||
if (si == NULL)
|
if (si == NULL)
|
||||||
return (NULL);
|
return (NULL);
|
||||||
si->u.size = size;
|
si->u.size = size;
|
||||||
@@ -853,36 +967,34 @@ isc__mem_allocate(isc_mem_t *ctx, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
isc__mem_allocatedebug(isc_mem_t *ctx, size_t size, const char *file,
|
isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {
|
||||||
int line) {
|
|
||||||
size_info *si;
|
size_info *si;
|
||||||
|
|
||||||
si = isc__mem_allocate(ctx, size);
|
REQUIRE(VALID_CONTEXT(ctx));
|
||||||
if (si == NULL)
|
|
||||||
return (NULL);
|
LOCK(&ctx->lock);
|
||||||
if (isc_mem_debugging)
|
si = isc__mem_allocateunlocked(ctx, size);
|
||||||
fprintf(stderr, "%s:%d: mem_get(%p, %lu) -> %p\n", file, line,
|
#ifdef ISC_MEM_TRACKLINES
|
||||||
ctx, (unsigned long)si[-1].u.size, si);
|
if (si != NULL)
|
||||||
|
ADD_TRACE(ctx, si, si[-1].u.size, file, line);
|
||||||
|
#endif
|
||||||
|
UNLOCK(&ctx->lock);
|
||||||
|
|
||||||
return (si);
|
return (si);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__mem_free(isc_mem_t *ctx, void *ptr) {
|
isc__mem_free(isc_mem_t *ctx, void *ptr FLARG) {
|
||||||
size_info *si;
|
size_info *si;
|
||||||
|
|
||||||
si = &(((size_info *)ptr)[-1]);
|
REQUIRE(VALID_CONTEXT(ctx));
|
||||||
isc__mem_put(ctx, si, si->u.size);
|
REQUIRE(ptr != NULL);
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
isc__mem_freedebug(isc_mem_t *ctx, void *ptr, const char *file, int line) {
|
|
||||||
size_info *si;
|
|
||||||
|
|
||||||
si = &(((size_info *)ptr)[-1]);
|
si = &(((size_info *)ptr)[-1]);
|
||||||
if (isc_mem_debugging)
|
LOCK(&ctx->lock);
|
||||||
fprintf(stderr, "%s:%d: mem_put(%p, %p, %lu)\n", file, line,
|
DELETE_TRACE(ctx, ptr, si->u.size, file, line);
|
||||||
ctx, ptr, (unsigned long)si->u.size);
|
mem_putunlocked(ctx, si, si->u.size);
|
||||||
isc__mem_put(ctx, si, si->u.size);
|
UNLOCK(&ctx->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -890,33 +1002,23 @@ isc__mem_freedebug(isc_mem_t *ctx, void *ptr, const char *file, int line) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
char *
|
char *
|
||||||
isc__mem_strdup(isc_mem_t *mctx, const char *s) {
|
isc__mem_strdup(isc_mem_t *mctx, const char *s FLARG) {
|
||||||
size_t len;
|
size_t len;
|
||||||
char *ns;
|
char *ns;
|
||||||
|
|
||||||
|
REQUIRE(VALID_CONTEXT(mctx));
|
||||||
|
REQUIRE(s != NULL);
|
||||||
|
|
||||||
len = strlen(s);
|
len = strlen(s);
|
||||||
ns = isc__mem_allocate(mctx, len + 1);
|
|
||||||
if (ns == NULL)
|
ns = isc__mem_allocate(mctx, len + 1 FLARG_PASS);
|
||||||
return (NULL);
|
|
||||||
strncpy(ns, s, len + 1);
|
if (ns != NULL)
|
||||||
|
strncpy(ns, s, len + 1);
|
||||||
|
|
||||||
return (ns);
|
return (ns);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *
|
|
||||||
isc__mem_strdupdebug(isc_mem_t *mctx, const char *s, const char *file,
|
|
||||||
int line) {
|
|
||||||
char *ptr;
|
|
||||||
size_info *si;
|
|
||||||
|
|
||||||
ptr = isc__mem_strdup(mctx, s);
|
|
||||||
si = &(((size_info *)ptr)[-1]);
|
|
||||||
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
|
void
|
||||||
isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) {
|
isc_mem_setdestroycheck(isc_mem_t *ctx, isc_boolean_t flag) {
|
||||||
REQUIRE(VALID_CONTEXT(ctx));
|
REQUIRE(VALID_CONTEXT(ctx));
|
||||||
@@ -980,92 +1082,6 @@ isc_mem_inuse(isc_mem_t *ctx) {
|
|||||||
return (inuse);
|
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
|
* Memory pool stuff
|
||||||
*/
|
*/
|
||||||
@@ -1168,7 +1184,7 @@ isc_mempool_create(isc_mem_t *mctx, size_t size, isc_mempool_t **mpctxp) {
|
|||||||
mpctx->freemax = 1;
|
mpctx->freemax = 1;
|
||||||
mpctx->fillcount = 1;
|
mpctx->fillcount = 1;
|
||||||
mpctx->gets = 0;
|
mpctx->gets = 0;
|
||||||
#if ISC_MEMPOOL_NAMES
|
#ifdef ISC_MEMPOOL_NAMES
|
||||||
mpctx->name[0] = 0;
|
mpctx->name[0] = 0;
|
||||||
#endif
|
#endif
|
||||||
mpctx->items = NULL;
|
mpctx->items = NULL;
|
||||||
@@ -1186,7 +1202,7 @@ void
|
|||||||
isc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
|
isc_mempool_setname(isc_mempool_t *mpctx, const char *name) {
|
||||||
REQUIRE(name != NULL);
|
REQUIRE(name != NULL);
|
||||||
|
|
||||||
#if ISC_MEMPOOL_NAMES
|
#ifdef ISC_MEMPOOL_NAMES
|
||||||
if (mpctx->lock != NULL)
|
if (mpctx->lock != NULL)
|
||||||
LOCK(mpctx->lock);
|
LOCK(mpctx->lock);
|
||||||
|
|
||||||
@@ -1253,7 +1269,7 @@ isc_mempool_associatelock(isc_mempool_t *mpctx, isc_mutex_t *lock) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
isc__mempool_get(isc_mempool_t *mpctx) {
|
isc__mempool_get(isc_mempool_t *mpctx FLARG) {
|
||||||
element *item;
|
element *item;
|
||||||
isc_mem_t *mctx;
|
isc_mem_t *mctx;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@@ -1317,11 +1333,17 @@ isc__mempool_get(isc_mempool_t *mpctx) {
|
|||||||
if (mpctx->lock != NULL)
|
if (mpctx->lock != NULL)
|
||||||
UNLOCK(mpctx->lock);
|
UNLOCK(mpctx->lock);
|
||||||
|
|
||||||
|
if (item != NULL) {
|
||||||
|
LOCK(&mctx->lock);
|
||||||
|
ADD_TRACE(mctx, item, mpctx->size, file, line);
|
||||||
|
UNLOCK(&mctx->lock);
|
||||||
|
}
|
||||||
|
|
||||||
return (item);
|
return (item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
isc__mempool_put(isc_mempool_t *mpctx, void *mem) {
|
isc__mempool_put(isc_mempool_t *mpctx, void *mem FLARG) {
|
||||||
isc_mem_t *mctx;
|
isc_mem_t *mctx;
|
||||||
element *item;
|
element *item;
|
||||||
|
|
||||||
@@ -1336,11 +1358,15 @@ isc__mempool_put(isc_mempool_t *mpctx, void *mem) {
|
|||||||
INSIST(mpctx->allocated > 0);
|
INSIST(mpctx->allocated > 0);
|
||||||
mpctx->allocated--;
|
mpctx->allocated--;
|
||||||
|
|
||||||
|
DELETE_TRACE(mctx, mem, mpctx->size, file, line);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If our free list is full, return this to the mctx directly.
|
* If our free list is full, return this to the mctx directly.
|
||||||
*/
|
*/
|
||||||
if (mpctx->freecount >= mpctx->freemax) {
|
if (mpctx->freecount >= mpctx->freemax) {
|
||||||
isc__mem_put(mctx, mem, mpctx->size);
|
LOCK(&mctx->lock);
|
||||||
|
mem_putunlocked(mctx, mem, mpctx->size);
|
||||||
|
UNLOCK(&mctx->lock);
|
||||||
if (mpctx->lock != NULL)
|
if (mpctx->lock != NULL)
|
||||||
UNLOCK(mpctx->lock);
|
UNLOCK(mpctx->lock);
|
||||||
return;
|
return;
|
||||||
@@ -1358,28 +1384,6 @@ isc__mempool_put(isc_mempool_t *mpctx, void *mem) {
|
|||||||
UNLOCK(mpctx->lock);
|
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
|
* Quotas
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user