⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mem.c

📁 bind 9.3结合mysql数据库
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1997-2003  Internet Software Consortium. * * 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. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS.  IN NO EVENT SHALL ISC 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. *//* $Id: mem.c,v 1.98.2.7.2.5 2004/03/16 05:50:24 marka Exp $ */#include <config.h>#include <stdio.h>#include <stdlib.h>#include <stddef.h>#include <limits.h>#include <isc/magic.h>#include <isc/mem.h>#include <isc/msgs.h>#include <isc/ondestroy.h>#include <isc/string.h>#include <isc/mutex.h>#include <isc/util.h>#ifndef ISC_MEM_DEBUGGING#define ISC_MEM_DEBUGGING 0#endifLIBISC_EXTERNAL_DATA unsigned int isc_mem_debugging = ISC_MEM_DEBUGGING;/* * Define ISC_MEM_USE_INTERNAL_MALLOC=1 to use the internal malloc() * implementation in preference to the system one.  The internal malloc() * is very space-efficient, and quite fast on uniprocessor systems.  It * performs poorly on multiprocessor machines. */#ifndef ISC_MEM_USE_INTERNAL_MALLOC#define ISC_MEM_USE_INTERNAL_MALLOC 0#endif/* * Constants. */#define DEF_MAX_SIZE		1100#define DEF_MEM_TARGET		4096#define ALIGNMENT_SIZE		8		/* must be a power of 2 */#define NUM_BASIC_BLOCKS	64		/* must be > 1 */#define TABLE_INCREMENT		1024#define DEBUGLIST_COUNT		1024/* * Types. */#if ISC_MEM_TRACKLINEStypedef struct debuglink debuglink_t;struct debuglink {	ISC_LINK(debuglink_t)	link;	const void	       *ptr[DEBUGLIST_COUNT];	unsigned int		size[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#endiftypedef struct element element;struct element {	element *		next;};typedef struct {	/*	 * This structure must be ALIGNMENT_SIZE bytes.	 */	union {		size_t		size;		char		bytes[ALIGNMENT_SIZE];	} u;} size_info;struct stats {	unsigned long		gets;	unsigned long		totalgets;#if ISC_MEM_USE_INTERNAL_MALLOC	unsigned long		blocks;	unsigned long		freefrags;#endif /* ISC_MEM_USE_INTERNAL_MALLOC */};#define MEM_MAGIC		ISC_MAGIC('M', 'e', 'm', 'C')#define VALID_CONTEXT(c)	ISC_MAGIC_VALID(c, MEM_MAGIC)#if ISC_MEM_TRACKLINEStypedef ISC_LIST(debuglink_t)	debuglist_t;#endifstruct isc_mem {	unsigned int		magic;	isc_ondestroy_t		ondestroy;	isc_mutex_t		lock;	isc_memalloc_t		memalloc;	isc_memfree_t		memfree;	void *			arg;	size_t			max_size;	isc_boolean_t		checkfree;	struct stats *		stats;	unsigned int		references;	size_t			quota;	size_t			total;	size_t			inuse;	size_t			maxinuse;	size_t			hi_water;	size_t			lo_water;	isc_boolean_t		hi_called;	isc_mem_water_t		water;	void *			water_arg;	ISC_LIST(isc_mempool_t)	pools;#if ISC_MEM_USE_INTERNAL_MALLOC	size_t			mem_target;	element **		freelists;	element *		basic_blocks;	unsigned char **	basic_table;	unsigned int		basic_table_count;	unsigned int		basic_table_size;	unsigned char *		lowest;	unsigned char *		highest;#endif /* ISC_MEM_USE_INTERNAL_MALLOC */#if ISC_MEM_TRACKLINES	debuglist_t *	 	debuglist;#endif	unsigned int		memalloc_failures;};#define MEMPOOL_MAGIC		ISC_MAGIC('M', 'E', 'M', 'p')#define VALID_MEMPOOL(c)	ISC_MAGIC_VALID(c, MEMPOOL_MAGIC)struct isc_mempool {	/* always unlocked */	unsigned int	magic;		/* magic number */	isc_mutex_t    *lock;		/* optional lock */	isc_mem_t      *mctx;		/* our memory context */	/* locked via the memory context's lock */	ISC_LINK(isc_mempool_t)	link;	/* next pool in this mem context */	/* optionally locked from here down */	element	       *items;		/* low water item list */	size_t		size;		/* size of each item on this pool */	unsigned int	maxalloc;	/* max number of items allowed */	unsigned int	allocated;	/* # of items currently given out */	unsigned int	freecount;	/* # of items on reserved list */	unsigned int	freemax;	/* # of items allowed on free list */	unsigned int	fillcount;	/* # of items to fetch on each fill */	/* Stats only. */	unsigned int	gets;		/* # of requests to this pool */	/* Debugging only. */#if ISC_MEMPOOL_NAMES	char		name[16];	/* printed name in stats reports */#endif};/* * Private Inline-able. */#if ! 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) \	do { \		if ((isc_mem_debugging & (ISC_MEM_DEBUGTRACE | \					  ISC_MEM_DEBUGRECORD)) != 0 && \		     b != NULL) \		         add_trace_entry(a, b, c, d, e); \	} while (0)#define DELETE_TRACE(a, b, c, d, e)	delete_trace_entry(a, b, c, d, e)static voidprint_active(isc_mem_t *ctx, FILE *out);/* * mctx must be locked. */static inline voidadd_trace_entry(isc_mem_t *mctx, const void *ptr, unsigned int size		FLARG){	debuglink_t *dl;	unsigned int i;	if ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)		fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,					       ISC_MSG_ADDTRACE,					       "add %p size %u "					       "file %s line %u mctx %p\n"),			ptr, size, file, line, mctx);	if (mctx->debuglist == NULL)		return;	if (size > mctx->max_size)		size = mctx->max_size;	dl = ISC_LIST_HEAD(mctx->debuglist[size]);	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->size[i] = size;				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->size[i] = 0;		dl->file[i] = NULL;		dl->line[i] = 0;	}	dl->ptr[0] = ptr;	dl->size[0] = size;	dl->file[0] = file;	dl->line[0] = line;	dl->count = 1;	ISC_LIST_PREPEND(mctx->debuglist[size], dl, link);}static inline voiddelete_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 ((isc_mem_debugging & ISC_MEM_DEBUGTRACE) != 0)		fprintf(stderr, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,					       ISC_MSG_DELTRACE,					       "del %p size %u "					       "file %s line %u mctx %p\n"),			ptr, size, file, line, mctx);	if (mctx->debuglist == NULL)		return;	if (size > mctx->max_size)		size = mctx->max_size;	dl = ISC_LIST_HEAD(mctx->debuglist[size]);	while (dl != NULL) {		for (i = 0; i < DEBUGLIST_COUNT; i++) {			if (dl->ptr[i] == ptr) {				dl->ptr[i] = NULL;				dl->size[i] = 0;				dl->file[i] = NULL;				dl->line[i] = 0;				INSIST(dl->count > 0);				dl->count--;				if (dl->count == 0) {					ISC_LIST_UNLINK(mctx->debuglist[size],							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 */#if ISC_MEM_USE_INTERNAL_MALLOCstatic inline size_trmsize(size_t size) {	/* 	 * round down to ALIGNMENT_SIZE	 */	return (size & (~(ALIGNMENT_SIZE - 1)));}static inline size_tquantize(size_t size) {	/*	 * Round up the result in order to get a size big	 * enough to satisfy the request and be aligned on ALIGNMENT_SIZE	 * byte boundaries.	 */	if (size == 0)		return (ALIGNMENT_SIZE);	return ((size + ALIGNMENT_SIZE - 1) & (~(ALIGNMENT_SIZE - 1)));}static inline isc_boolean_tmore_basic_blocks(isc_mem_t *ctx) {	void *new;	unsigned char *curr, *next;	unsigned char *first, *last;	unsigned char **table;	unsigned int table_size;	size_t increment;	int i;	/* Require: we hold the context lock. */	/*	 * Did we hit the quota for this context?	 */	increment = NUM_BASIC_BLOCKS * ctx->mem_target;	if (ctx->quota != 0 && ctx->total + increment > ctx->quota)		return (ISC_FALSE);	INSIST(ctx->basic_table_count <= ctx->basic_table_size);	if (ctx->basic_table_count == ctx->basic_table_size) {		table_size = ctx->basic_table_size + TABLE_INCREMENT;		table = (ctx->memalloc)(ctx->arg,					table_size * sizeof(unsigned char *));		if (table == NULL) {			ctx->memalloc_failures++;			return (ISC_FALSE);		}		if (ctx->basic_table_size != 0) {			memcpy(table, ctx->basic_table,			       ctx->basic_table_size *			       sizeof(unsigned char *));			(ctx->memfree)(ctx->arg, ctx->basic_table);		}		ctx->basic_table = table;		ctx->basic_table_size = table_size;	}	new = (ctx->memalloc)(ctx->arg, NUM_BASIC_BLOCKS * ctx->mem_target);	if (new == NULL) {		ctx->memalloc_failures++;		return (ISC_FALSE);	}	ctx->total += increment;	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++) {		((element *)curr)->next = (element *)next;		curr = next;		next += ctx->mem_target;	}	/*	 * curr is now pointing at the last block in the	 * array.	 */	((element *)curr)->next = NULL;	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;	return (ISC_TRUE);}static inline isc_boolean_tmore_frags(isc_mem_t *ctx, size_t new_size) {	int i, frags;	size_t total_size;	void *new;	unsigned char *curr, *next;	/*	 * Try to get more fragments by chopping up a basic block.	 */	if (ctx->basic_blocks == NULL) {		if (!more_basic_blocks(ctx)) {			/*			 * We can't get more memory from the OS, or we've			 * hit the quota for this context.			 */			/*			 * XXXRTH  "At quota" notification here.			 */			return (ISC_FALSE);		}	}	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;	total_size -= new_size;	for (i = 0; i < (frags - 1); i++) {		((element *)curr)->next = (element *)next;		curr = next;		next += new_size;		total_size -= new_size;	}	/*	 * Add the remaining fragment of the basic block to a free list.	 */	total_size = rmsize(total_size);	if (total_size > 0) {		((element *)next)->next = ctx->freelists[total_size];		ctx->freelists[total_size] = (element *)next;		ctx->stats[total_size].freefrags++;	}	/*	 * curr is now pointing at the last block in the	 * array.	 */	((element *)curr)->next = NULL;	ctx->freelists[new_size] = new;	return (ISC_TRUE);}static inline void *mem_getunlocked(isc_mem_t *ctx, size_t size) {	size_t new_size = quantize(size);	void *ret;	if (size >= ctx->max_size || new_size >= ctx->max_size) {		/*		 * memget() was called on something beyond our upper limit.		 */		if (ctx->quota != 0 && ctx->total + size > ctx->quota) {			ret = NULL;			goto done;		}		ret = (ctx->memalloc)(ctx->arg, size);		if (ret == NULL) {			ctx->memalloc_failures++;			goto done;		}		ctx->total += size;		ctx->inuse += size;		ctx->stats[ctx->max_size].gets++;		ctx->stats[ctx->max_size].totalgets++;		/*		 * If we don't set new_size to size, then the		 * ISC_MEM_FILL code might write over bytes we		 * don't own.		 */		new_size = size;		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 && !more_frags(ctx, new_size))		return (NULL);	/*	 * 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--;	ctx->inuse += new_size; done:#if ISC_MEM_FILL	if (ret != NULL)		memset(ret, 0xbe, new_size); /* Mnemonic for "beef". */#endif	return (ret);}#if ISC_MEM_FILL && ISC_MEM_CHECKOVERRUNstatic inline voidcheck_overrun(void *mem, size_t size, size_t new_size) {	unsigned char *cp;	cp = (unsigned char *)mem;	cp += size;	while (size < new_size) {		INSIST(*cp == 0xbe);		cp++;		size++;	}}#endifstatic inline voidmem_putunlocked(isc_mem_t *ctx, void *mem, size_t size) {	size_t new_size = quantize(size);	if (size == ctx->max_size || new_size >= ctx->max_size) {		/*		 * memput() called on something beyond our upper limit.		 */#if ISC_MEM_FILL		memset(mem, 0xde, size); /* Mnemonic for "dead". */#endif		(ctx->memfree)(ctx->arg, mem);		INSIST(ctx->stats[ctx->max_size].gets != 0);		ctx->stats[ctx->max_size].gets--;		INSIST(size <= ctx->total);		ctx->inuse -= size;		ctx->total -= size;		return;	}#if ISC_MEM_FILL#if ISC_MEM_CHECKOVERRUN	check_overrun(mem, size, new_size);#endif	memset(mem, 0xde, new_size); /* Mnemonic for "dead". */#endif	/*	 * The free list uses the "rounded-up" size "new_size".	 */	((element *)mem)->next = ctx->freelists[new_size];	ctx->freelists[new_size] = (element *)mem;	/*	 * 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++;	ctx->inuse -= new_size;}#else /* ISC_MEM_USE_INTERNAL_MALLOC */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -