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

📄 aset.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
 */static voidAllocSetReset(MemoryContext context){	AllocSet	set = (AllocSet) context;	AllocBlock	block;	AssertArg(AllocSetIsValid(set));	/* Nothing to do if no pallocs since startup or last reset */	if (set->isReset)		return;#ifdef MEMORY_CONTEXT_CHECKING	/* Check for corruption and leaks before freeing */	AllocSetCheck(context);#endif	/* Clear chunk freelists */	MemSetAligned(set->freelist, 0, sizeof(set->freelist));	block = set->blocks;	/* New blocks list is either empty or just the keeper block */	set->blocks = set->keeper;	while (block != NULL)	{		AllocBlock	next = block->next;		if (block == set->keeper)		{			/* Reset the block, but don't return it to malloc */			char	   *datastart = ((char *) block) + ALLOC_BLOCKHDRSZ;#ifdef CLOBBER_FREED_MEMORY			/* Wipe freed memory for debugging purposes */			memset(datastart, 0x7F, block->freeptr - datastart);#endif			block->freeptr = datastart;			block->next = NULL;		}		else		{			/* Normal case, release the block */#ifdef CLOBBER_FREED_MEMORY			/* Wipe freed memory for debugging purposes */			memset(block, 0x7F, block->freeptr - ((char *) block));#endif			free(block);		}		block = next;	}	set->isReset = true;}/* * AllocSetDelete *		Frees all memory which is allocated in the given set, *		in preparation for deletion of the set. * * Unlike AllocSetReset, this *must* free all resources of the set. * But note we are not responsible for deleting the context node itself. */static voidAllocSetDelete(MemoryContext context){	AllocSet	set = (AllocSet) context;	AllocBlock	block = set->blocks;	AssertArg(AllocSetIsValid(set));#ifdef MEMORY_CONTEXT_CHECKING	/* Check for corruption and leaks before freeing */	AllocSetCheck(context);#endif	/* Make it look empty, just in case... */	MemSetAligned(set->freelist, 0, sizeof(set->freelist));	set->blocks = NULL;	set->keeper = NULL;	while (block != NULL)	{		AllocBlock	next = block->next;#ifdef CLOBBER_FREED_MEMORY		/* Wipe freed memory for debugging purposes */		memset(block, 0x7F, block->freeptr - ((char *) block));#endif		free(block);		block = next;	}}/* * AllocSetAlloc *		Returns pointer to allocated memory of given size; memory is added *		to the set. */static void *AllocSetAlloc(MemoryContext context, Size size){	AllocSet	set = (AllocSet) context;	AllocBlock	block;	AllocChunk	chunk;	AllocChunk	priorfree;	int			fidx;	Size		chunk_size;	Size		blksize;	AssertArg(AllocSetIsValid(set));	/*	 * If requested size exceeds maximum for chunks, allocate an entire block	 * for this request.	 */	if (size > ALLOC_CHUNK_LIMIT)	{		chunk_size = MAXALIGN(size);		blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;		block = (AllocBlock) malloc(blksize);		if (block == NULL)		{			MemoryContextStats(TopMemoryContext);			ereport(ERROR,					(errcode(ERRCODE_OUT_OF_MEMORY),					 errmsg("out of memory"),					 errdetail("Failed on request of size %lu.",							   (unsigned long) size)));		}		block->aset = set;		block->freeptr = block->endptr = ((char *) block) + blksize;		chunk = (AllocChunk) (((char *) block) + ALLOC_BLOCKHDRSZ);		chunk->aset = set;		chunk->size = chunk_size;#ifdef MEMORY_CONTEXT_CHECKING		chunk->requested_size = size;		/* set mark to catch clobber of "unused" space */		if (size < chunk_size)			((char *) AllocChunkGetPointer(chunk))[size] = 0x7E;#endif		/*		 * Stick the new 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;		}		set->isReset = false;		AllocAllocInfo(set, chunk);		return AllocChunkGetPointer(chunk);	}	/*	 * Request is small enough to be treated as a chunk.  Look in the	 * corresponding free list to see if there is a free chunk we could reuse.	 */	fidx = AllocSetFreeIndex(size);	priorfree = NULL;	for (chunk = set->freelist[fidx]; chunk; chunk = (AllocChunk) chunk->aset)	{		if (chunk->size >= size)			break;		priorfree = chunk;	}	/*	 * If one is found, remove it from the free list, make it again a member	 * of the alloc set and return its data address.	 */	if (chunk != NULL)	{		if (priorfree == NULL)			set->freelist[fidx] = (AllocChunk) chunk->aset;		else			priorfree->aset = chunk->aset;		chunk->aset = (void *) set;#ifdef MEMORY_CONTEXT_CHECKING		chunk->requested_size = size;		/* set mark to catch clobber of "unused" space */		if (size < chunk->size)			((char *) AllocChunkGetPointer(chunk))[size] = 0x7E;#endif		/* isReset must be false already */		Assert(!set->isReset);		AllocAllocInfo(set, chunk);		return AllocChunkGetPointer(chunk);	}	/*	 * Choose the actual chunk size to allocate.	 */	chunk_size = 1 << (fidx + ALLOC_MINBITS);	Assert(chunk_size >= size);	/*	 * If there is enough room in the active allocation block, we will put the	 * chunk into that block.  Else must start a new one.	 */	if ((block = set->blocks) != NULL)	{		Size		availspace = block->endptr - block->freeptr;		if (availspace < (chunk_size + ALLOC_CHUNKHDRSZ))		{			/*			 * The existing active (top) block does not have enough room for			 * the requested allocation, but it might still have a useful			 * amount of space in it.  Once we push it down in the block list,			 * we'll never try to allocate more space from it. So, before we			 * do that, carve up its free space into chunks that we can put on			 * the set's freelists.			 *			 * Because we can only get here when there's less than			 * ALLOC_CHUNK_LIMIT left in the block, this loop cannot iterate			 * more than ALLOCSET_NUM_FREELISTS-1 times.			 */			while (availspace >= ((1 << ALLOC_MINBITS) + ALLOC_CHUNKHDRSZ))			{				Size		availchunk = availspace - ALLOC_CHUNKHDRSZ;				int			a_fidx = AllocSetFreeIndex(availchunk);				/*				 * In most cases, we'll get back the index of the next larger				 * freelist than the one we need to put this chunk on.	The				 * exception is when availchunk is exactly a power of 2.				 */				if (availchunk != (1 << (a_fidx + ALLOC_MINBITS)))				{					a_fidx--;					Assert(a_fidx >= 0);					availchunk = (1 << (a_fidx + ALLOC_MINBITS));				}				chunk = (AllocChunk) (block->freeptr);				block->freeptr += (availchunk + ALLOC_CHUNKHDRSZ);				availspace -= (availchunk + ALLOC_CHUNKHDRSZ);				chunk->size = availchunk;#ifdef MEMORY_CONTEXT_CHECKING				chunk->requested_size = 0;		/* mark it free */#endif				chunk->aset = (void *) set->freelist[a_fidx];				set->freelist[a_fidx] = chunk;			}			/* Mark that we need to create a new block */			block = NULL;		}	}	/*	 * Time to create a new regular (multi-chunk) block?	 */	if (block == NULL)	{		Size		required_size;		if (set->blocks == NULL)		{			/* First block of the alloc set, use initBlockSize */			blksize = set->initBlockSize;		}		else		{			/*			 * Use first power of 2 that is larger than previous block, but			 * not more than the allowed limit.  (We don't simply double the			 * prior block size, because in some cases this could be a funny			 * size, eg if very first allocation was for an odd-sized large			 * chunk.)			 */			Size		pblksize = set->blocks->endptr - ((char *) set->blocks);			blksize = set->initBlockSize;			while (blksize <= pblksize)				blksize <<= 1;			if (blksize > set->maxBlockSize)				blksize = set->maxBlockSize;		}		/*		 * If initBlockSize is less than ALLOC_CHUNK_LIMIT, we could need more		 * space... but try to keep it a power of 2.		 */		required_size = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;		while (blksize < required_size)			blksize <<= 1;		/* 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;			if (blksize < required_size)				break;			block = (AllocBlock) malloc(blksize);		}		if (block == NULL)		{			MemoryContextStats(TopMemoryContext);			ereport(ERROR,					(errcode(ERRCODE_OUT_OF_MEMORY),					 errmsg("out of memory"),					 errdetail("Failed on request of size %lu.",							   (unsigned long) size)));		}		block->aset = set;		block->freeptr = ((char *) block) + ALLOC_BLOCKHDRSZ;		block->endptr = ((char *) block) + blksize;		/*		 * If this is the first block of the set, make it the "keeper" block.		 * Formerly, a keeper block could only be created during context		 * creation, but allowing it to happen here lets us have fast reset		 * cycling even for contexts created with minContextSize = 0; that way		 * we don't have to force space to be allocated in contexts that might		 * never need any space.  Don't mark an oversize block as a keeper,		 * however.		 */		if (set->blocks == NULL && blksize == set->initBlockSize)		{			Assert(set->keeper == NULL);			set->keeper = block;		}		block->next = set->blocks;		set->blocks = block;	}	/*	 * OK, do the allocation	 */	chunk = (AllocChunk) (block->freeptr);	block->freeptr += (chunk_size + ALLOC_CHUNKHDRSZ);	Assert(block->freeptr <= block->endptr);	chunk->aset = (void *) set;	chunk->size = chunk_size;#ifdef MEMORY_CONTEXT_CHECKING	chunk->requested_size = size;	/* set mark to catch clobber of "unused" space */	if (size < chunk->size)		((char *) AllocChunkGetPointer(chunk))[size] = 0x7E;#endif	set->isReset = false;	AllocAllocInfo(set, chunk);	return AllocChunkGetPointer(chunk);}/* * AllocSetFree *		Frees allocated memory; memory is removed from the set. */static voidAllocSetFree(MemoryContext context, void *pointer){	AllocSet	set = (AllocSet) context;	AllocChunk	chunk = AllocPointerGetChunk(pointer);	AllocFreeInfo(set, chunk);#ifdef MEMORY_CONTEXT_CHECKING

⌨️ 快捷键说明

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