mem.c

来自「非常好的dns解析软件」· C语言 代码 · 共 1,955 行 · 第 1/3 页

C
1,955
字号
/*! * 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--;	}}/* * 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);}static voidinitialize_action(void) {        RUNTIME_CHECK(isc_mutex_init(&lock) == ISC_R_SUCCESS);}/* * 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){	return (isc_mem_createx2(init_max_size, target_size, memalloc, memfree,				 arg, ctxp, ISC_MEMFLAG_DEFAULT));				 }isc_result_tisc_mem_createx2(size_t init_max_size, size_t target_size,		 isc_memalloc_t memalloc, isc_memfree_t memfree, void *arg,		 isc_mem_t **ctxp, unsigned int flags){	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);	RUNTIME_CHECK(isc_once_do(&once, initialize_action) == ISC_R_SUCCESS);	ctx = (memalloc)(arg, sizeof(*ctx));	if (ctx == NULL)		return (ISC_R_NOMEMORY);	if ((flags & ISC_MEMFLAG_NOLOCK) == 0) {		result = isc_mutex_init(&ctx->lock);		if (result != ISC_R_SUCCESS) {			(memfree)(arg, ctx);			return (result);		}	}	if (init_max_size == 0U)		ctx->max_size = DEF_MAX_SIZE;	else		ctx->max_size = init_max_size;	ctx->flags = flags;	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;#if ISC_MEM_TRACKLINES	ctx->debuglist = NULL;#endif	ISC_LIST_INIT(ctx->pools);	ctx->freelists = NULL;	ctx->basic_blocks = NULL;	ctx->basic_table = NULL;	ctx->basic_table_count = 0;	ctx->basic_table_size = 0;	ctx->lowest = NULL;	ctx->highest = NULL;	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 ((flags & ISC_MEMFLAG_INTERNAL) != 0) {		if (target_size == 0U)			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 *));	}#if ISC_MEM_TRACKLINES	if ((isc_mem_debugging & ISC_MEM_DEBUGRECORD) != 0) {		unsigned int i;		ctx->debuglist = (memalloc)(arg,				      (ctx->max_size+1) * sizeof(debuglist_t));		if (ctx->debuglist == NULL) {			result = ISC_R_NOMEMORY;			goto error;		}		for (i = 0; i <= ctx->max_size; i++)			ISC_LIST_INIT(ctx->debuglist[i]);	}#endif	ctx->memalloc_failures = 0;	LOCK(&lock);	ISC_LIST_INITANDAPPEND(contexts, ctx, link);	UNLOCK(&lock);	*ctxp = ctx;	return (ISC_R_SUCCESS);  error:	if (ctx != NULL) {		if (ctx->stats != NULL)			(memfree)(arg, ctx->stats);		if (ctx->freelists != NULL)			(memfree)(arg, ctx->freelists);#if ISC_MEM_TRACKLINES		if (ctx->debuglist != NULL)			(ctx->memfree)(ctx->arg, ctx->debuglist);#endif /* ISC_MEM_TRACKLINES */		if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)			DESTROYLOCK(&ctx->lock);		(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_createx2(init_max_size, target_size,				 default_memalloc, default_memfree, NULL,				 ctxp, ISC_MEMFLAG_DEFAULT));}isc_result_tisc_mem_create2(size_t init_max_size, size_t target_size,		isc_mem_t **ctxp, unsigned int flags){	return (isc_mem_createx2(init_max_size, target_size,				 default_memalloc, default_memfree, NULL,				 ctxp, flags));}static voiddestroy(isc_mem_t *ctx) {	unsigned int i;	isc_ondestroy_t ondest;	ctx->magic = 0;	LOCK(&lock);	ISC_LIST_UNLINK(contexts, ctx, link);	UNLOCK(&lock);	INSIST(ISC_LIST_EMPTY(ctx->pools));#if ISC_MEM_TRACKLINES	if (ctx->debuglist != NULL) {		if (ctx->checkfree) {			for (i = 0; i <= ctx->max_size; i++) {				if (!ISC_LIST_EMPTY(ctx->debuglist[i]))					print_active(ctx, stderr);				INSIST(ISC_LIST_EMPTY(ctx->debuglist[i]));			}		} else {			debuglink_t *dl;			for (i = 0; i <= ctx->max_size; i++)				for (dl = ISC_LIST_HEAD(ctx->debuglist[i]);				     dl != NULL;				     dl = ISC_LIST_HEAD(ctx->debuglist[i])) {					ISC_LIST_UNLINK(ctx->debuglist[i],						 	dl, link);					free(dl);				}		}		(ctx->memfree)(ctx->arg, ctx->debuglist);	}#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 != 0U)				print_active(ctx, stderr);#endif			INSIST(ctx->stats[i].gets == 0U);		}	}	(ctx->memfree)(ctx->arg, ctx->stats);	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {		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);	}	ondest = ctx->ondestroy;	if ((ctx->flags & ISC_MEMFLAG_NOLOCK) == 0)		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);	MCTXLOCK(source, &source->lock);	source->references++;	MCTXUNLOCK(source, &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));	MCTXLOCK(ctx, &ctx->lock);	INSIST(ctx->references > 0);	ctx->references--;	if (ctx->references == 0)		want_destroy = ISC_TRUE;	MCTXUNLOCK(ctx, &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;	size_info *si;	size_t oldsize;	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_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) {		if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) {			si = &(((size_info *)ptr)[-1]);			oldsize = si->u.size - ALIGNMENT_SIZE;			if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)				oldsize -= ALIGNMENT_SIZE;			INSIST(oldsize == size);		}		isc__mem_free(ctx, ptr FLARG_PASS);		MCTXLOCK(ctx, &ctx->lock);		ctx->references--;		if (ctx->references == 0)			want_destroy = ISC_TRUE;		MCTXUNLOCK(ctx, &ctx->lock);		if (want_destroy)			destroy(ctx);		return;	}	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {		MCTXLOCK(ctx, &ctx->lock);		mem_putunlocked(ctx, ptr, size);	} else {		mem_put(ctx, ptr, size);		MCTXLOCK(ctx, &ctx->lock);		mem_putstats(ctx, ptr, size);	}	DELETE_TRACE(ctx, ptr, size, file, line);	INSIST(ctx->references > 0);	ctx->references--;	if (ctx->references == 0)		want_destroy = ISC_TRUE;	MCTXUNLOCK(ctx, &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));	MCTXLOCK(ctx, &ctx->lock);#if ISC_MEM_TRACKLINES	if (ctx->references != 1)		print_active(ctx, stderr);#endif	REQUIRE(ctx->references == 1);	ctx->references--;	MCTXUNLOCK(ctx, &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;	MCTXLOCK(ctx, &ctx->lock);	res = isc_ondestroy_register(&ctx->ondestroy, task, event);	MCTXUNLOCK(ctx, &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_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0)		return (isc__mem_allocate(ctx, size FLARG_PASS));	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {		MCTXLOCK(ctx, &ctx->lock);		ptr = mem_getunlocked(ctx, size);	} else {		ptr = mem_get(ctx, size);		MCTXLOCK(ctx, &ctx->lock);		if (ptr != NULL)			mem_getstats(ctx, size);	}	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);	}	MCTXUNLOCK(ctx, &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;	size_info *si;	size_t oldsize;	REQUIRE(VALID_CONTEXT(ctx));	REQUIRE(ptr != NULL);	if ((isc_mem_debugging & (ISC_MEM_DEBUGSIZE|ISC_MEM_DEBUGCTX)) != 0) {		if ((isc_mem_debugging & ISC_MEM_DEBUGSIZE) != 0) {			si = &(((size_info *)ptr)[-1]);			oldsize = si->u.size - ALIGNMENT_SIZE;			if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)				oldsize -= ALIGNMENT_SIZE;			INSIST(oldsize == size);		}		isc__mem_free(ctx, ptr FLARG_PASS);		return;	}	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0) {		MCTXLOCK(ctx, &ctx->lock);		mem_putunlocked(ctx, ptr, size);	} else {		mem_put(ctx, ptr, size);		MCTXLOCK(ctx, &ctx->lock);		mem_putstats(ctx, ptr, size);	}	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;	}	MCTXUNLOCK(ctx, &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 (mctx->debuglist != NULL) {		debuglink_t *dl;		unsigned int i, j;		const char *format;		isc_boolean_t found;		fprintf(out, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,					    ISC_MSG_DUMPALLOC,					    "Dump of all outstanding "					    "memory allocations:\n"));		found = ISC_FALSE;		format = isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,				        ISC_MSG_PTRFILELINE,					"\tptr %p size %u file %s line %u\n");		for (i = 0; i <= mctx->max_size; i++) {			dl = ISC_LIST_HEAD(mctx->debuglist[i]);						if (dl != NULL)				found = ISC_TRUE;			while (dl != NULL) {				for (j = 0; j < DEBUGLIST_COUNT; j++)					if (dl->ptr[j] != NULL)						fprintf(out, format,							dl->ptr[j],							dl->size[j],							dl->file[j],							dl->line[j]);				dl = ISC_LIST_NEXT(dl, link);			}		}		if (!found)			fprintf(out, isc_msgcat_get(isc_msgcat, ISC_MSGSET_MEM,						    ISC_MSG_NONE, "\tNone.\n"));	}}#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));	MCTXLOCK(ctx, &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 ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0 &&		    (s->blocks != 0U || s->freefrags != 0U))			fprintf(out, " (%lu bl, %lu ff)",				s->blocks, s->freefrags);		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"));		pool = ISC_LIST_NEXT(pool, link);	}#if ISC_MEM_TRACKLINES	print_active(ctx, out);#endif	MCTXUNLOCK(ctx, &ctx->lock);}/* * Replacements for malloc() and free() -- they implicitly remember the * size of the object allocated (with some additional overhead). */static void *isc__mem_allocateunlocked(isc_mem_t *ctx, size_t size) {	size_info *si;	size += ALIGNMENT_SIZE;	if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0)		size += ALIGNMENT_SIZE;	if ((ctx->flags & ISC_MEMFLAG_INTERNAL) != 0)		si = mem_getunlocked(ctx, size);	else		si = mem_get(ctx, size);	if (si == NULL)		return (NULL);	if ((isc_mem_debugging & ISC_MEM_DEBUGCTX) != 0) {		si->u.ctx = ctx;		si++;	}	si->u.size = size;	return (&si[1]);}void *isc__mem_allocate(isc_mem_t *ctx, size_t size FLARG) {	size_info *si;	isc_boolean_t call_water = ISC_FALSE;	REQUIRE(VALID_CONTEXT(ctx));

⌨️ 快捷键说明

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