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

📄 aset.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
字号:
/*------------------------------------------------------------------------- * * aset.c *	  Allocation set definitions. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/utils/mmgr/aset.c,v 1.16.2.1 1999/08/02 05:25:15 scrappy Exp $ * * NOTE: *	This is a new (Feb. 05, 1999) implementation of the allocation set *	routines. AllocSet...() does not use OrderedSet...() any more. *	Instead it manages allocations in a block pool by itself, combining *	many small allocations in a few bigger blocks. AllocSetFree() does *	never free() memory really. It just add's the free'd area to some *	list for later reuse by AllocSetAlloc(). All memory blocks are free()'d *	at once on AllocSetReset(), which happens when the memory context gets *	destroyed. *				Jan Wieck *------------------------------------------------------------------------- */#include "postgres.h"#include "utils/memutils.h"#undef AllocSetReset#undef malloc#undef free#undef realloc/*-------------------- * Chunk freelist k holds chunks of size 1 << (k + ALLOC_MINBITS), * for k = 0 .. ALLOCSET_NUM_FREELISTS-2. * The last freelist holds all larger chunks. * * CAUTION: ALLOC_MINBITS must be large enough so that * 1<<ALLOC_MINBITS is at least MAXALIGN, * or we may fail to align the smallest chunks adequately. * 16-byte alignment is enough on all currently known machines. *-------------------- */#define ALLOC_MINBITS		4	/* smallest chunk size is 16 bytes */#define ALLOC_SMALLCHUNK_LIMIT	(1 << (ALLOCSET_NUM_FREELISTS-2+ALLOC_MINBITS))/* Size of largest chunk that we use a fixed size for *//*-------------------- * The first block allocated for an allocset has size ALLOC_MIN_BLOCK_SIZE. * Each time we have to allocate another block, we double the block size * (if possible, and without exceeding ALLOC_MAX_BLOCK_SIZE), so as to reduce * the load on "malloc". * * Blocks allocated to hold oversize chunks do not follow this rule, however; * they are just however big they need to be. *-------------------- */#define ALLOC_MIN_BLOCK_SIZE	8192#define ALLOC_MAX_BLOCK_SIZE	(8 * 1024 * 1024)#define ALLOC_BLOCKHDRSZ	MAXALIGN(sizeof(AllocBlockData))#define ALLOC_CHUNKHDRSZ	MAXALIGN(sizeof(AllocChunkData))#define AllocPointerGetChunk(ptr)	\					((AllocChunk)(((char *)(ptr)) - ALLOC_CHUNKHDRSZ))#define AllocChunkGetPointer(chk)	\					((AllocPointer)(((char *)(chk)) + ALLOC_CHUNKHDRSZ))#define AllocPointerGetAset(ptr)	((AllocSet)(AllocPointerGetChunk(ptr)->aset))#define AllocPointerGetSize(ptr)	(AllocPointerGetChunk(ptr)->size)/* ---------- * AllocSetFreeIndex - * *		Depending on the size of an allocation compute which freechunk *		list of the alloc set it belongs to. * ---------- */static inline intAllocSetFreeIndex(Size size){	int			idx = 0;	if (size > 0)	{		size = (size - 1) >> ALLOC_MINBITS;		while (size != 0 && idx < ALLOCSET_NUM_FREELISTS - 1)		{			idx++;			size >>= 1;		}	}	return idx;}/* * Public routines *//* *		AllocPointerIsValid(pointer) *		AllocSetIsValid(set) * *				.. are now macros in aset.h -cim 4/27/91 *//* * AllocSetInit *		Initializes given allocation set. * * Note: *		The semantics of the mode are explained above.	Limit is ignored *		for dynamic and static modes. * * Exceptions: *		BadArg if set is invalid pointer. *		BadArg if mode is invalid. */voidAllocSetInit(AllocSet set, AllocMode mode, Size limit){	AssertArg(PointerIsValid(set));	AssertArg((int) DynamicAllocMode <= (int) mode);	AssertArg((int) mode <= (int) BoundedAllocMode);	/*	 * XXX mode is currently ignored and treated as DynamicAllocMode. XXX	 * limit is also ignored.  This affects this whole file.	 */	memset(set, 0, sizeof(AllocSetData));}/* * AllocSetReset *		Frees memory which is allocated in the given set. * * Exceptions: *		BadArg if set is invalid. */voidAllocSetReset(AllocSet set){	AllocBlock	block = set->blocks;	AllocBlock	next;	AssertArg(AllocSetIsValid(set));	while (block != NULL)	{		next = block->next;		free(block);		block = next;	}	memset(set, 0, sizeof(AllocSetData));}/* * AllocSetContains *		True iff allocation set contains given allocation element. * * Exceptions: *		BadArg if set is invalid. *		BadArg if pointer is invalid. */boolAllocSetContains(AllocSet set, AllocPointer pointer){	AssertArg(AllocSetIsValid(set));	AssertArg(AllocPointerIsValid(pointer));	return (AllocPointerGetAset(pointer) == set);}/* * AllocSetAlloc *		Returns pointer to allocated memory of given size; memory is added *		to the set. * * Exceptions: *		BadArg if set is invalid. *		MemoryExhausted if allocation fails. */AllocPointerAllocSetAlloc(AllocSet set, Size size){	AllocBlock	block;	AllocChunk	chunk;	AllocChunk	freeref = NULL;	int			fidx;	Size		chunk_size;	Size		blksize;	AssertArg(AllocSetIsValid(set));	/*	 * Lookup in the corresponding free list if there is a free chunk we	 * could reuse	 *	 */	fidx = AllocSetFreeIndex(size);	for (chunk = set->freelist[fidx]; chunk; chunk = (AllocChunk) chunk->aset)	{		if (chunk->size >= size)			break;		freeref = chunk;	}	/*	 * If one is found, remove it from the free list, make it again a	 * member of the alloc set and return it's data address.	 *	 */	if (chunk != NULL)	{		if (freeref == NULL)			set->freelist[fidx] = (AllocChunk) chunk->aset;		else			freeref->aset = chunk->aset;		chunk->aset = (void *) set;		return AllocChunkGetPointer(chunk);	}	/*	 * Choose the actual chunk size to allocate.	 */	if (size > ALLOC_SMALLCHUNK_LIMIT)		chunk_size = MAXALIGN(size);	else		chunk_size = 1 << (fidx + ALLOC_MINBITS);	Assert(chunk_size >= size);	/*	 * If there is enough room in the active allocation block, always	 * allocate the chunk there.	 */	if ((block = set->blocks) != NULL)	{		Size		have_free = block->endptr - block->freeptr;		if (have_free < (chunk_size + ALLOC_CHUNKHDRSZ))			block = NULL;	}	/*	 * Otherwise, if requested size exceeds smallchunk limit, allocate an	 * entire separate block for this allocation	 *	 */	if (block == NULL && size > ALLOC_SMALLCHUNK_LIMIT)	{		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;		block = (AllocBlock) malloc(blksize);		if (block == NULL)			elog(FATAL, "Memory exhausted in AllocSetAlloc()");		block->aset = set;		block->freeptr = block->endptr = ((char *) block) + blksize;		chunk = (AllocChunk) (((char *) block) + ALLOC_BLOCKHDRSZ);		chunk->aset = set;		chunk->size = chunk_size;		/*		 * Try to stick the block underneath the active allocation block,		 * so that we don't lose the use of the space remaining therein.		 */		if (set->blocks != NULL)		{			block->next = set->blocks->next;			set->blocks->next = block;		}		else		{			block->next = NULL;			set->blocks = block;		}		return AllocChunkGetPointer(chunk);	}	/*	 * Time to create a new regular block?	 */	if (block == NULL)	{		if (set->blocks == NULL)		{			blksize = ALLOC_MIN_BLOCK_SIZE;			block = (AllocBlock) malloc(blksize);		}		else		{			/* Get size of prior block */			blksize = set->blocks->endptr - ((char *) set->blocks);			/*			 * Special case: if very first allocation was for a large			 * chunk, could have a funny-sized top block.  Do something			 * reasonable.			 */			if (blksize < ALLOC_MIN_BLOCK_SIZE)				blksize = ALLOC_MIN_BLOCK_SIZE;			/* Crank it up, but not past max */			blksize <<= 1;			if (blksize > ALLOC_MAX_BLOCK_SIZE)				blksize = ALLOC_MAX_BLOCK_SIZE;			/* Try to allocate it */			block = (AllocBlock) malloc(blksize);			/*			 * We could be asking for pretty big blocks here, so cope if			 * malloc fails.  But give up if there's less than a meg or so			 * available...			 */			while (block == NULL && blksize > 1024 * 1024)			{				blksize >>= 1;				block = (AllocBlock) malloc(blksize);			}		}		if (block == NULL)			elog(FATAL, "Memory exhausted in AllocSetAlloc()");		block->aset = set;		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;		block->endptr = ((char *) block) + blksize;		block->next = set->blocks;		set->blocks = block;	}	/*	 * OK, do the allocation	 */	chunk = (AllocChunk) (block->freeptr);	chunk->aset = (void *) set;	chunk->size = chunk_size;	block->freeptr += (chunk_size + ALLOC_CHUNKHDRSZ);	Assert(block->freeptr <= block->endptr);	return AllocChunkGetPointer(chunk);}/* * AllocSetFree *		Frees allocated memory; memory is removed from the set. * * Exceptions: *		BadArg if set is invalid. *		BadArg if pointer is invalid. *		BadArg if pointer is not member of set. */voidAllocSetFree(AllocSet set, AllocPointer pointer){	int			fidx;	AllocChunk	chunk;	/* AssertArg(AllocSetIsValid(set)); */	/* AssertArg(AllocPointerIsValid(pointer)); */	AssertArg(AllocSetContains(set, pointer));	chunk = AllocPointerGetChunk(pointer);	fidx = AllocSetFreeIndex(chunk->size);	chunk->aset = (void *) set->freelist[fidx];	set->freelist[fidx] = chunk;}/* * AllocSetRealloc *		Returns new pointer to allocated memory of given size; this memory *		is added to the set.  Memory associated with given pointer is copied *		into the new memory, and the old memory is freed. * * Exceptions: *		BadArg if set is invalid. *		BadArg if pointer is invalid. *		BadArg if pointer is not member of set. *		MemoryExhausted if allocation fails. */AllocPointerAllocSetRealloc(AllocSet set, AllocPointer pointer, Size size){	AllocPointer newPointer;	Size		oldsize;	/* AssertArg(AllocSetIsValid(set)); */	/* AssertArg(AllocPointerIsValid(pointer)); */	AssertArg(AllocSetContains(set, pointer));	/*	 * Chunk sizes are aligned to power of 2 on AllocSetAlloc(). Maybe the	 * allocated area already is >= the new size.	 *	 */	oldsize = AllocPointerGetSize(pointer);	if (oldsize >= size)		return pointer;	/* allocate new pointer */	newPointer = AllocSetAlloc(set, size);	/* fill new memory */	memmove(newPointer, pointer, (oldsize < size) ? oldsize : size);	/* free old pointer */	AllocSetFree(set, pointer);	return newPointer;}/* * AllocSetDump *		Displays allocated set. */voidAllocSetDump(AllocSet set){	elog(DEBUG, "Currently unable to dump AllocSet");}

⌨️ 快捷键说明

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