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

📄 mem.c

📁 bind-3.2.
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Perform a malloc, doing memory filling and overrun detection as necessary. */static inline void *mem_get(isc_mem_t *ctx, size_t size) {	char *ret;#if ISC_MEM_CHECKOVERRUN	size += 1;#endif	ret = (ctx->memalloc)(ctx->arg, size);	if (ret == NULL)		ctx->memalloc_failures++;	#if ISC_MEM_FILL	if (ret != NULL)		memset(ret, 0xbe, size); /* Mnemonic for "beef". */#else#  if ISC_MEM_CHECKOVERRUN	if (ret != NULL)		ret[size-1] = 0xbe;#  endif#endif	return (ret);}/* * Perform a free, doing memory filling and overrun detection as necessary. */static inline voidmem_put(isc_mem_t *ctx, void *mem, size_t size) {#if ISC_MEM_CHECKOVERRUN	INSIST(((unsigned char *)mem)[size] == 0xbe);#endif#if ISC_MEM_FILL	memset(mem, 0xde, size); /* Mnemonic for "dead". */#else	UNUSED(size);#endif	(ctx->memfree)(ctx->arg, mem);}/* * Update internal counters after a memory get. */static inline voidmem_getstats(isc_mem_t *ctx, size_t size) {	ctx->total += size;	ctx->inuse += size;	if (size > ctx->max_size) {		ctx->stats[ctx->max_size].gets++;		ctx->stats[ctx->max_size].totalgets++;	} else {		ctx->stats[size].gets++;		ctx->stats[size].totalgets++;	}}/* * Update internal counters after a memory put. */static inline voidmem_putstats(isc_mem_t *ctx, void *ptr, size_t size) {	UNUSED(ptr);	INSIST(ctx->inuse >= size);	ctx->inuse -= size;	if (size > ctx->max_size) {		INSIST(ctx->stats[ctx->max_size].gets > 0U);		ctx->stats[ctx->max_size].gets--;	} else {		INSIST(ctx->stats[size].gets > 0U);		ctx->stats[size].gets--;	}}#endif /* ISC_MEM_USE_INTERNAL_MALLOC *//* * Private. */static void *default_memalloc(void *arg, size_t size) {	UNUSED(arg);	if (size == 0U)		size = 1;	return (malloc(size));}static voiddefault_memfree(void *arg, void *ptr) {	UNUSED(arg);	free(ptr);}/* * Public. */isc_result_tisc_mem_createx(size_t init_max_size, size_t target_size,		isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,		isc_mem_t **ctxp){	isc_mem_t *ctx;	isc_result_t result;	REQUIRE(ctxp != NULL && *ctxp == NULL);	REQUIRE(memalloc != NULL);	REQUIRE(memfree != NULL);	INSIST((ALIGNMENT_SIZE & (ALIGNMENT_SIZE - 1)) == 0);#if !ISC_MEM_USE_INTERNAL_MALLOC	UNUSED(target_size);#endif	ctx = (memalloc)(arg, sizeof *ctx);	if (ctx == NULL)		return (ISC_R_NOMEMORY);	if (init_max_size == 0U)		ctx->max_size = DEF_MAX_SIZE;	else		ctx->max_size = init_max_size;	ctx->references = 1;	ctx->quota = 0;	ctx->total = 0;	ctx->inuse = 0;	ctx->maxinuse = 0;	ctx->hi_water = 0;	ctx->lo_water = 0;	ctx->hi_called = ISC_FALSE;	ctx->water = NULL;	ctx->water_arg = NULL;	ctx->magic = MEM_MAGIC;	isc_ondestroy_init(&ctx->ondestroy);	ctx->memalloc = memalloc;	ctx->memfree = memfree;	ctx->arg = arg;	ctx->stats = NULL;	ctx->checkfree = ISC_TRUE;	ISC_LIST_INIT(ctx->pools);#if ISC_MEM_USE_INTERNAL_MALLOC	ctx->freelists = NULL;#endif /* ISC_MEM_USE_INTERNAL_MALLOC */	ctx->stats = (memalloc)(arg,				(ctx->max_size+1) * sizeof (struct stats));	if (ctx->stats == NULL) {		result = ISC_R_NOMEMORY;		goto error;	}	memset(ctx->stats, 0, (ctx->max_size + 1) * sizeof (struct stats));#if ISC_MEM_USE_INTERNAL_MALLOC	if (target_size == 0)		ctx->mem_target = DEF_MEM_TARGET;	else		ctx->mem_target = target_size;	ctx->freelists = (memalloc)(arg, ctx->max_size * sizeof (element *));	if (ctx->freelists == NULL) {		result = ISC_R_NOMEMORY;		goto error;	}	memset(ctx->freelists, 0,	       ctx->max_size * sizeof (element *));	ctx->basic_blocks = NULL;	ctx->basic_table = NULL;	ctx->basic_table_count = 0;	ctx->basic_table_size = 0;	ctx->lowest = NULL;	ctx->highest = NULL;#endif /* ISC_MEM_USE_INTERNAL_MALLOC */	if (isc_mutex_init(&ctx->lock) != ISC_R_SUCCESS) {		UNEXPECTED_ERROR(__FILE__, __LINE__,				 "isc_mutex_init() %s",				 isc_msgcat_get(isc_msgcat, ISC_MSGSET_GENERAL,						ISC_MSG_FAILED, "failed"));		result = ISC_R_UNEXPECTED;		goto error;	}#if ISC_MEM_TRACKLINES	ISC_LIST_INIT(ctx->debuglist);	ctx->debugging = isc_mem_debugging;#endif	ctx->memalloc_failures = 0;	*ctxp = ctx;	return (ISC_R_SUCCESS);  error:	if (ctx) {		if (ctx->stats)			(memfree)(arg, ctx->stats);#if ISC_MEM_USE_INTERNAL_MALLOC		if (ctx->freelists)			(memfree)(arg, ctx->freelists);#endif /* ISC_MEM_USE_INTERNAL_MALLOC */		(memfree)(arg, ctx);	}	return (result);}isc_result_tisc_mem_create(size_t init_max_size, size_t target_size,	       isc_mem_t **ctxp){	return (isc_mem_createx(init_max_size, target_size,				default_memalloc, default_memfree, NULL,				ctxp));}static voiddestroy(isc_mem_t *ctx) {	unsigned int i;	isc_ondestroy_t ondest;	ctx->magic = 0;#if ISC_MEM_USE_INTERNAL_MALLOC	INSIST(ISC_LIST_EMPTY(ctx->pools));#endif /* ISC_MEM_USE_INTERNAL_MALLOC */#if ISC_MEM_TRACKLINES	if (ctx->checkfree) {		if (!ISC_LIST_EMPTY(ctx->debuglist))			print_active(ctx, stderr);		INSIST(ISC_LIST_EMPTY(ctx->debuglist));	} else {		debuglink_t *dl;		for (dl = ISC_LIST_HEAD(ctx->debuglist);		     dl != NULL;		     dl = ISC_LIST_HEAD(ctx->debuglist)) {			ISC_LIST_UNLINK(ctx->debuglist, dl, link);			free(dl);		}	}#endif	INSIST(ctx->references == 0);	if (ctx->checkfree) {		for (i = 0; i <= ctx->max_size; i++) {#if ISC_MEM_TRACKLINES			if (ctx->stats[i].gets != 0)				print_active(ctx, stderr);#endif			INSIST(ctx->stats[i].gets == 0U);		}	}	(ctx->memfree)(ctx->arg, ctx->stats);#if ISC_MEM_USE_INTERNAL_MALLOC	for (i = 0; i < ctx->basic_table_count; i++)		(ctx->memfree)(ctx->arg, ctx->basic_table[i]);	(ctx->memfree)(ctx->arg, ctx->freelists);	(ctx->memfree)(ctx->arg, ctx->basic_table);#endif /* ISC_MEM_USE_INTERNAL_MALLOC */	ondest = ctx->ondestroy;	DESTROYLOCK(&ctx->lock);	(ctx->memfree)(ctx->arg, ctx);	isc_ondestroy_notify(&ondest, ctx);}voidisc_mem_attach(isc_mem_t *source, isc_mem_t **targetp) {	REQUIRE(VALID_CONTEXT(source));	REQUIRE(targetp != NULL && *targetp == NULL);	LOCK(&source->lock);	source->references++;	UNLOCK(&source->lock);	*targetp = source;}voidisc_mem_detach(isc_mem_t **ctxp) {	isc_mem_t *ctx;	isc_boolean_t want_destroy = ISC_FALSE;	REQUIRE(ctxp != NULL);	ctx = *ctxp;	REQUIRE(VALID_CONTEXT(ctx));	LOCK(&ctx->lock);	INSIST(ctx->references > 0);	ctx->references--;	if (ctx->references == 0)		want_destroy = ISC_TRUE;	UNLOCK(&ctx->lock);	if (want_destroy)		destroy(ctx);	*ctxp = NULL;}/* * isc_mem_putanddetach() is the equivalent of: * * mctx = NULL; * isc_mem_attach(ptr->mctx, &mctx); * isc_mem_detach(&ptr->mctx); * isc_mem_put(mctx, ptr, sizeof(*ptr); * isc_mem_detach(&mctx); */voidisc__mem_putanddetach(isc_mem_t **ctxp, void *ptr, size_t size FLARG) {	isc_mem_t *ctx;	isc_boolean_t want_destroy = ISC_FALSE;	REQUIRE(ctxp != NULL);	ctx = *ctxp;	REQUIRE(VALID_CONTEXT(ctx));	REQUIRE(ptr != NULL);	/*	 * Must be before mem_putunlocked() as ctxp is usually within	 * [ptr..ptr+size).	 */	*ctxp = NULL;#if ISC_MEM_USE_INTERNAL_MALLOC	LOCK(&ctx->lock);	mem_putunlocked(ctx, ptr, size);#else /* ISC_MEM_USE_INTERNAL_MALLOC */	mem_put(ctx, ptr, size);	LOCK(&ctx->lock);	mem_putstats(ctx, ptr, size);#endif /* ISC_MEM_USE_INTERNAL_MALLOC */	DELETE_TRACE(ctx, ptr, size, file, line);	INSIST(ctx->references > 0);	ctx->references--;	if (ctx->references == 0)		want_destroy = ISC_TRUE;	UNLOCK(&ctx->lock);	if (want_destroy)		destroy(ctx);}voidisc_mem_destroy(isc_mem_t **ctxp) {	isc_mem_t *ctx;	/*	 * This routine provides legacy support for callers who use mctxs	 * without attaching/detaching.	 */	REQUIRE(ctxp != NULL);	ctx = *ctxp;	REQUIRE(VALID_CONTEXT(ctx));	LOCK(&ctx->lock);#if ISC_MEM_TRACKLINES	if (ctx->references != 1)		print_active(ctx, stderr);#endif	REQUIRE(ctx->references == 1);	ctx->references--;	UNLOCK(&ctx->lock);	destroy(ctx);	*ctxp = NULL;}isc_result_tisc_mem_ondestroy(isc_mem_t *ctx, isc_task_t *task, isc_event_t **event) {	isc_result_t res;	LOCK(&ctx->lock);	res = isc_ondestroy_register(&ctx->ondestroy, task, event);	UNLOCK(&ctx->lock);	return (res);}void *isc__mem_get(isc_mem_t *ctx, size_t size FLARG) {	void *ptr;	isc_boolean_t call_water = ISC_FALSE;	REQUIRE(VALID_CONTEXT(ctx));#if ISC_MEM_USE_INTERNAL_MALLOC	LOCK(&ctx->lock);	ptr = mem_getunlocked(ctx, size);#else /* ISC_MEM_USE_INTERNAL_MALLOC */	ptr = mem_get(ctx, size);	LOCK(&ctx->lock);	if (ptr)		mem_getstats(ctx, size);#endif /* ISC_MEM_USE_INTERNAL_MALLOC */	ADD_TRACE(ctx, ptr, size, file, line);	if (ctx->hi_water != 0U && !ctx->hi_called &&	    ctx->inuse > ctx->hi_water) {		ctx->hi_called = ISC_TRUE;		call_water = ISC_TRUE;	}	if (ctx->inuse > ctx->maxinuse) {		ctx->maxinuse = ctx->inuse;		if (ctx->hi_water != 0U && ctx->inuse > ctx->hi_water &&		    (isc_mem_debugging & ISC_MEM_DEBUGUSAGE) != 0)			fprintf(stderr, "maxinuse = %lu\n",				(unsigned long)ctx->inuse);	}	UNLOCK(&ctx->lock);	if (call_water) {		(ctx->water)(ctx->water_arg, ISC_MEM_HIWATER);	}	return (ptr);}voidisc__mem_put(isc_mem_t *ctx, void *ptr, size_t size FLARG){	isc_boolean_t call_water = ISC_FALSE;	REQUIRE(VALID_CONTEXT(ctx));	REQUIRE(ptr != NULL);#if ISC_MEM_USE_INTERNAL_MALLOC	LOCK(&ctx->lock);	mem_putunlocked(ctx, ptr, size);#else /* ISC_MEM_USE_INTERNAL_MALLOC */	mem_put(ctx, ptr, size);	LOCK(&ctx->lock);	mem_putstats(ctx, ptr, size);#endif /* ISC_MEM_USE_INTERNAL_MALLOC */	DELETE_TRACE(ctx, ptr, size, file, line);	/*	 * The check against ctx->lo_water == 0 is for the condition	 * when the context was pushed over hi_water but then had	 * isc_mem_setwater() called with 0 for hi_water and lo_water.	 */	if (ctx->hi_called && 	    (ctx->inuse < ctx->lo_water || ctx->lo_water == 0U)) {		ctx->hi_called = ISC_FALSE;		if (ctx->water != NULL)			call_water = ISC_TRUE;	}	UNLOCK(&ctx->lock);	if (call_water) {		(ctx->water)(ctx->water_arg, ISC_MEM_LOWATER);	}}#if ISC_MEM_TRACKLINESstatic voidprint_active(isc_mem_t *mctx, FILE *out) {	if (MEM_RECORD) {		debuglink_t *dl;		unsigned int i;		fprintf(out, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,					    ISC_MSG_DUMPALLOC,					    "Dump of all outstanding "					    "memory allocations:\n"));		dl = ISC_LIST_HEAD(mctx->debuglist);		if (dl == NULL)			fprintf(out, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,						    ISC_MSG_NONE,						    "\tNone.\n"));		while (dl != NULL) {			for (i = 0 ; i < DEBUGLIST_COUNT ; i++)				if (dl->ptr[i] != NULL)					fprintf(out,						isc_msgcat_get(isc_msgcat,							   ISC_MSGSET_MEM,							   ISC_MSG_PTRFILELINE,							   "\tptr %p "							   "file %s "							   "line %u\n"),						dl->ptr[i], dl->file[i],						dl->line[i]);			dl = ISC_LIST_NEXT(dl, link);		}	}}#endif/* * Print the stats[] on the stream "out" with suitable formatting. */voidisc_mem_stats(isc_mem_t *ctx, FILE *out) {	size_t i;	const struct stats *s;	const isc_mempool_t *pool;	REQUIRE(VALID_CONTEXT(ctx));	LOCK(&ctx->lock);	for (i = 0; i <= ctx->max_size; i++) {		s = &ctx->stats[i];		if (s->totalgets == 0U && s->gets == 0U)			continue;		fprintf(out, "%s%5lu: %11lu gets, %11lu rem",			(i == ctx->max_size) ? ">=" : "  ",			(unsigned long) i, s->totalgets, s->gets);#if ISC_MEM_USE_INTERNAL_MALLOC		if (s->blocks != 0 || s->freefrags != 0)			fprintf(out, " (%lu bl, %lu ff)",				s->blocks, s->freefrags);#endif /* ISC_MEM_USE_INTERNAL_MALLOC */		fputc('\n', out);	}	/*	 * Note that since a pool can be locked now, these stats might be	 * somewhat off if the pool is in active use at the time the stats	 * are dumped.  The link fields are protected by the isc_mem_t's	 * lock, however, so walking this list and extracting integers from	 * stats fields is always safe.	 */	pool = ISC_LIST_HEAD(ctx->pools);	if (pool != NULL) {		fprintf(out, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,					    ISC_MSG_POOLSTATS,					    "[Pool statistics]\n"));		fprintf(out, "%15s %10s %10s %10s %10s %10s %10s %10s %1s\n",			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,				       ISC_MSG_POOLNAME, "name"),			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,				       ISC_MSG_POOLSIZE, "size"),			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,				       ISC_MSG_POOLMAXALLOC, "maxalloc"),			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,				       ISC_MSG_POOLALLOCATED, "allocated"),			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,				       ISC_MSG_POOLFREECOUNT, "freecount"),			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,				       ISC_MSG_POOLFREEMAX, "freemax"),			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,				       ISC_MSG_POOLFILLCOUNT, "fillcount"),			isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,				       ISC_MSG_POOLGETS, "gets"),			"L");	}	while (pool != NULL) {		fprintf(out, "%15s %10lu %10u %10u %10u %10u %10u %10u %s\n",			pool->name, (unsigned long) pool->size, pool->maxalloc,			pool->allocated, pool->freecount, pool->freemax,			pool->fillcount, pool->gets,			(pool->lock == NULL ? "N" : "Y"));

⌨️ 快捷键说明

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