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

📄 mpralloc.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 3 页
字号:
/** *	@file mprAlloc.c  *	@brief Memory Allocation *	@overview  *//* *	@copy	default *	 *	Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. *	 *	This software is distributed under commercial and open source licenses. *	You may use the GPL open source license described below or you may acquire  *	a commercial license from Mbedthis Software. You agree to be fully bound  *	by the terms of either license. Consult the LICENSE.TXT distributed with  *	this software for full details. *	 *	This software is open source; you can redistribute it and/or modify it  *	under the terms of the GNU General Public License as published by the  *	Free Software Foundation; either version 2 of the License, or (at your  *	option) any later version. See the GNU General Public License for more  *	details at: http://www.mbedthis.com/downloads/gplLicense.html *	 *	This program is distributed WITHOUT ANY WARRANTY; without even the  *	implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  *	 *	This GPL license does NOT permit incorporating this software into  *	proprietary programs. If you are unable to comply with the GPL, you must *	acquire a commercial license to use this software. Commercial licenses  *	for this software and support services are available from Mbedthis  *	Software at http://www.mbedthis.com  *	 *	@end *//********************************* Includes ***********************************/#define 	UNSAFE_FUNCTIONS_OK 1#include	"mpr.h"/******************************* Local Defines ********************************//* *	Set to 1 to disable slab based allocations */#define NO_SLAB 				0/* *	Validation mode is quite slow */#define VALIDATE_ALLOC			0#if VALIDATE_ALLOC#define VALIDATE_BLOCK(ptr)		mprValidateBlock(ptr)#else#define VALIDATE_BLOCK(ptr) 			#endif/* *	Align on 4 bytes if squeeze, Otherwize on 16 bytes. */#define HDR_SIZE 				MPR_BLK_HDR_SIZE#define APP_MAGIC 				0xa571cb80#define ALLOC_MAGIC 			0xe814ecc0/* *	This must be at least one word to ensure that the smallest allocation is *	4 bytes. Slab allocations need at least one word to store their next ptr. */#define ALLOC_ALIGN(x) 			(((x)+3)&~3)#define GET_HDR(ptr) 			((MprBlk*) (((char*) (ptr)) - HDR_SIZE))#define GET_PTR(bp) 			((void*) (((char*) (bp)) + HDR_SIZE))#define VALID_HDR(bp) 			(((bp)->flags & ~0x3F) == ALLOC_MAGIC)#define VALID_BLK(ptr) 			(VALID_HDR(GET_HDR(ptr)))/* *	In production releases, mprAssert will compile out (not be included) *	but CHECK_HDR will remain even in production builds. */#define CHECK_HDR(bp) \	if (1) { if (! VALID_HDR(bp)) { mprAllocAbort(); } } else/* *	Chunk the slabs into 32 byte increments. *	This allows for allocations up to 512 bytes via slabs and maximizes *	sharing of slab allocations. * *	Index map: *	 	 0 ==  32  bytes *		 1 ==  64  bytes *		 2 ==  96  bytes *		 3 ==  128 bytes *		 4 ==  160 bytes *		 5 ==  192 bytes *		 6 ==  224 bytes *		 7 ==  256 bytes *		 8 ==  288 bytes *		 9 ==  320 bytes *		10 ==  352 bytes *		11 ==  384 bytes *		12 ==  416 bytes *		13 ==  448 bytes *		14 ==  480 bytes *		15 ==  512 bytes */#define SLAB_ALIGN(size) 		((size + 31) & ~31)#define GET_SLAB(size)			(size >> 6)/* *	Block flags */#define ALLOC_FLAGS_FREE			0x1		/* Block is free */#define ALLOC_FLAGS_FREEING			0x2		/* Block is being freed */#define ALLOC_FLAGS_SLAB_BLOCK		0x4		/* Block was allocated from slab */#define ALLOC_FLAGS_REQUIRED		0x8		/* Block is required by alloc */#define ALLOC_FLAGS_KEEP			0x10	/* Keep block - don't mprFree */#define ALLOC_FLAGS_DONT_OS_FREE	0x20	/* Don't return mem to O/S */#define ALLOC_FLAGS_IS_SLAB			0x40	/* Block is a slab */#if BLD_DEBUG && !BREW/* *	Set this address to break when this address is allocated or freed. This is *	a block address (not a user ptr). */static MprBlk *stopAlloc;#endif#if !BREWstatic MprCtx rootCtx;						/* Root context if none supplied */#endif/***************************** Forward Declarations ***************************/static int mprAllocException(MPR_LOC_DEC(ptr, loc), uint size, bool granted);static void slabFree(MprBlk *bp);static int	growSlab(MPR_LOC_DEC(ctx, loc), MprSlab *slab, uint size, uint inc);/******************************************************************************//* *	Put first in file so it is easy to locate in a debugger */void mprBreakpoint(const char *loc, const char *msg){}/******************************************************************************/#if (WIN || BREW_SIMULATOR) && BLD_DEBUGint crtReportHook(int type, char *msg, int *retval){	printf("%s\n", msg);	*retval = 0;	return TRUE;}#endif/******************************************************************************//* *	Initialize the memory subsystem */MprApp *mprAllocInit(MprAllocCback cback){	MprAllocStats	*stats;	MprApp			*app;	MprSlab			*slab;	MprBlk			*bp, *sp;	int				i;	bp = malloc(sizeof(MprApp) + HDR_SIZE);	mprAssert(bp);	if (bp == 0) {		if (cback) {			(*cback)(0, sizeof(MprApp), 0, 0);		}		return 0;	}	memset(bp, 0, sizeof(MprApp) + HDR_SIZE);	bp->parent = bp;	bp->size = sizeof(MprApp);	bp->flags = ALLOC_MAGIC;	bp->next = bp->prev = bp;#if BLD_FEATURE_ALLOC_LEAK_TRACK	bp->location = MPR_LOC;#endif	app = (MprApp*) GET_PTR(bp);	app->magic = APP_MAGIC;	app->alloc.cback = cback;	app->stackStart = (void*) &app;	bp->app = app;	app->alloc.slabs = mprAllocZeroedBlock(MPR_LOC_PASS(app, MPR_LOC), 		sizeof(MprSlab) * MPR_MAX_SLAB);	if (app->alloc.slabs == 0) {		mprFree(app);		return 0;	}	/*	 *	The slab control structures must not be freed. Set keep to safeguard	 *	against accidents.	 */	sp = GET_HDR(app->alloc.slabs);	sp->flags |= ALLOC_FLAGS_KEEP;	for (i = 0; i < MPR_MAX_SLAB; i++) {		/*		 *	This is overriden by requestors calling slabAlloc		 */		slab = &app->alloc.slabs[i];		slab->preAllocateIncr = MPR_SLAB_DEFAULT_INC;	}	/*	 *	Keep aggregated stats even in production code	 */	stats = &app->alloc.stats;	stats->bytesAllocated += sizeof(MprApp);	if (stats->bytesAllocated > stats->peakAllocated) {		stats->peakAllocated = stats->bytesAllocated;	}	stats->allocCount++;#if !BREW	rootCtx = app;#endif#if (WIN || BREW_SIMULATOR) && BLD_DEBUG	_CrtSetReportHook(crtReportHook);#endif	return app;}/******************************************************************************//* *	Terminate the alloc module */void mprAllocTerm(MprApp *app){	MprSlab		*slabs;	MprBlk		*appBlk, *slabBlk;	/* 	 *	Must do a carefully ordered cleanup. Need to free all children blocks	 *	before freeing the slab memory. Save a local pointer to the slabs.	 */	slabs = app->alloc.slabs;	/*	 *	Free the app and all children. Set DONT_OS_FREE to prevent free() being	 *	called on app itself. We need that so we can free the slabs below.	 */	appBlk = GET_HDR(app);	appBlk->flags |= ALLOC_FLAGS_DONT_OS_FREE;	mprFree(app);	/*	 *	Slabs are initially marked don't free. We must preserve them while all	 *	other blocks are freed. Then we clear the don't free flag and free. 	 *	Now we don't have an app structure which is used by mprFree. We must	 *	fake it.	 */	slabBlk = GET_HDR(slabs);	slabBlk->flags &= ~ALLOC_FLAGS_KEEP;	mprFree(slabs);	/*	 *	Now we can finally free the memory for the app structure	 */	free(appBlk);}/******************************************************************************//* *	Allocate a block */void *mprAllocBlock(MPR_LOC_DEC(ctx, loc), uint size){	MprAllocStats	*stats;	MprBlk			*bp, *parent;	MprApp			*app;	int				diff;	mprAssert(size > 0);	if (ctx == 0) {#if BREW		mprAssert(ctx);		return 0;#else		ctx = rootCtx;#endif	}	if (size == 0) {		size = 1;	}	mprAssert(VALID_BLK(ctx));	parent = GET_HDR(ctx);	mprAssert(VALID_HDR(parent));	CHECK_HDR(parent);	size = ALLOC_ALIGN(size);	app = parent->app;	stats = &app->alloc.stats;	mprLock(app->allocLock);	stats->bytesAllocated += size + HDR_SIZE;	if (stats->bytesAllocated > stats->peakAllocated) {		stats->peakAllocated = stats->bytesAllocated;	}	/*	 *	Prevent allocation if over the maximum 	 */	if (stats->maxMemory && stats->bytesAllocated > stats->maxMemory) {		stats->bytesAllocated -= (size + HDR_SIZE);		mprUnlock(app->allocLock);		if (mprAllocException(MPR_LOC_PASS(ctx, loc), size, 0) < 0) {			return 0;		}		mprLock(app->allocLock);	}	if ((bp = malloc(size + HDR_SIZE)) == 0) {		mprAssert(bp);		stats->errors++;		mprUnlock(app->allocLock);		mprAllocException(MPR_LOC_PASS(ctx, loc), size, 0);		return 0;	}#if BLD_DEBUG	memset(bp, 0xf7, size + HDR_SIZE);#endif#if BLD_DEBUG && !BREW	if (bp == stopAlloc) {		mprBreakpoint(MPR_LOC, "breakOnAddr");	}#endif	/*	 *	Warn if allocation puts us over the red line 	 */	if (stats->redLine && stats->bytesAllocated > stats->redLine) {		mprUnlock(app->allocLock);		if (mprAllocException(MPR_LOC_PASS(ctx, loc), size, 1) < 0) {			return 0;		}		mprLock(app->allocLock);	}	bp->size = size;	bp->flags = ALLOC_MAGIC;	bp->destructor = 0;	bp->parent = parent;	if (parent->children == 0) {		parent->children = bp;		bp->next = bp->prev = bp;	} else {		/*		 *	Append to the end of the list. Preserve alloc order		 */		bp->next = parent->children;		bp->prev = parent->children->prev;		parent->children->prev->next = bp;		parent->children->prev = bp;	}	bp->children = 0;#if BLD_FEATURE_ALLOC_LEAK_TRACK	bp->location = loc;#endif	bp->app = parent->app;	VALIDATE_BLOCK(GET_PTR(bp));	stats->allocCount++;	/* 	 *	Monitor stack usage 	 */	diff = (int) bp->app->stackStart - (int) &stats;	if (diff < 0) {		app->maxStack -= diff;		app->stackStart = (void*) &stats;		diff = 0;	}	if ((uint) diff > app->maxStack) {		app->maxStack = diff;	}	mprUnlock(app->allocLock);	return GET_PTR(bp);}/******************************************************************************//* *	Allocate and zero a block */void *mprAllocZeroedBlock(MPR_LOC_DEC(ctx, loc), uint size){	void	*newBlock;	MprBlk	*bp;	bp = GET_HDR(ctx);	mprAssert(VALID_BLK(ctx));	newBlock = mprAllocBlock(MPR_LOC_PASS(ctx, loc), size);	if (newBlock) {		memset(newBlock, 0, size);	}	return newBlock;}/******************************************************************************//* *	Free a block of memory. Free all children recursively. */int mprFree(void *ptr){	MprAllocStats	*stats;	MprBlk			*bp, *parent, *cp, *firstChild, *prev;	MprApp			*app;	if (ptr == 0) {		return 0;	}	mprAssert(VALID_BLK(ptr));	VALIDATE_BLOCK(ptr);	bp = GET_HDR(ptr);#if BLD_DEBUG && !BREW	if (bp == stopAlloc) {		mprBreakpoint(MPR_LOC, "breakOnAddr");	}#endif	mprAssert(bp);	mprAssert(VALID_HDR(bp));	CHECK_HDR(bp);	/* 	 *	Test if already freed 	 */	mprAssert(! (bp->flags & ALLOC_FLAGS_FREE));	if (bp->flags & ALLOC_FLAGS_FREE) {		return 0;	}	/*	 *	Return if recursive freeing or this is a permanent block	 */	app = bp->app;	mprLock(app->allocLock);	if (bp->flags & (ALLOC_FLAGS_FREEING | ALLOC_FLAGS_KEEP)) {		mprUnlock(app->allocLock);		return 0;	}	bp->flags |= ALLOC_FLAGS_FREEING;	/* 	 *	Call any destructors	 */	if (bp->destructor) {		mprUnlock(app->allocLock);		if ((bp->destructor)(ptr) < 0) {			return -1;		}		mprLock(app->allocLock);		bp->destructor = 0;	}	/*	 *	Free the children. Free in reverse order so firstChild is preserved 	 *	during the list scan as an end of list marker.	 */	if ((firstChild = bp->children) != 0) {		cp = firstChild->prev;		while (cp != firstChild) {			mprAssert(VALID_HDR(cp));			VALIDATE_BLOCK(GET_PTR(cp));			prev = cp->prev;			/*			 *	FUTURE - OPT. Make this inline 			 */			mprFree(GET_PTR(cp));			cp = prev;		}		mprFree(GET_PTR(firstChild));		/*		 *	Just for clarity		 */		bp->children = 0;	}	parent = bp->parent;	mprAssert(VALID_HDR(parent));	/*	 *	Unlink from the parent	 */	if (parent->children == bp) {		if (bp->next == bp) {			parent->children = 0;		} else {			parent->children = bp->next;		}	}	/*	 *	Remove from the sibling chain	 */	bp->prev->next = bp->next;	bp->next->prev = bp->prev;	bp->flags |= ALLOC_FLAGS_FREE;	/*	 *	Release the memory. If from a slab, return to the slab. Otherwise, 	 *	return to the O/S.	 */	if (bp->flags & ALLOC_FLAGS_SLAB_BLOCK) {		slabFree(bp);	} else {		mprAssert(bp);		/*		 *	Update the stats		 */		stats = &bp->app->alloc.stats;		stats->bytesAllocated -= (bp->size + HDR_SIZE);		mprAssert(stats->bytesAllocated >= 0);		stats->allocCount--;		mprAssert(stats->allocCount >= 0);#if BLD_DEBUG && !BREW		if (bp == stopAlloc) {			mprBreakpoint(MPR_LOC, "breakOnAddr");		}#endif		/*		 *	Return to the O/S		 */		if (! (bp->flags & ALLOC_FLAGS_DONT_OS_FREE)) {			free(bp);		}	}	/* OPT */	if (app != ptr) {		mprUnlock(app->allocLock);	}	return 0;}/******************************************************************************/

⌨️ 快捷键说明

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