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

📄 aset.c

📁 PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* Test for someone scribbling on unused space in chunk */	if (chunk->requested_size < chunk->size)		if (((char *) pointer)[chunk->requested_size] != 0x7E)			elog(WARNING, "detected write past chunk end in %s %p",				 set->header.name, chunk);#endif	if (chunk->size > ALLOC_CHUNK_LIMIT)	{		/*		 * Big chunks are certain to have been allocated as single-chunk		 * blocks.	Find the containing block and return it to malloc().		 */		AllocBlock	block = set->blocks;		AllocBlock	prevblock = NULL;		while (block != NULL)		{			if (chunk == (AllocChunk) (((char *) block) + ALLOC_BLOCKHDRSZ))				break;			prevblock = block;			block = block->next;		}		if (block == NULL)			elog(ERROR, "could not find block containing chunk %p", chunk);		/* let's just make sure chunk is the only one in the block */		Assert(block->freeptr == ((char *) block) +			   (chunk->size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ));		/* OK, remove block from aset's list and free it */		if (prevblock == NULL)			set->blocks = block->next;		else			prevblock->next = block->next;#ifdef CLOBBER_FREED_MEMORY		/* Wipe freed memory for debugging purposes */		memset(block, 0x7F, block->freeptr - ((char *) block));#endif		free(block);	}	else	{		/* Normal case, put the chunk into appropriate freelist */		int			fidx = AllocSetFreeIndex(chunk->size);		chunk->aset = (void *) set->freelist[fidx];#ifdef CLOBBER_FREED_MEMORY		/* Wipe freed memory for debugging purposes */		memset(pointer, 0x7F, chunk->size);#endif#ifdef MEMORY_CONTEXT_CHECKING		/* Reset requested_size to 0 in chunks that are on freelist */		chunk->requested_size = 0;#endif		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. */static void *AllocSetRealloc(MemoryContext context, void *pointer, Size size){	AllocSet	set = (AllocSet) context;	AllocChunk	chunk = AllocPointerGetChunk(pointer);	Size		oldsize = chunk->size;#ifdef MEMORY_CONTEXT_CHECKING	/* Test for someone scribbling on unused space in chunk */	if (chunk->requested_size < oldsize)		if (((char *) pointer)[chunk->requested_size] != 0x7E)			elog(WARNING, "detected write past chunk end in %s %p",				 set->header.name, chunk);#endif	/* isReset must be false already */	Assert(!set->isReset);	/*	 * Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the	 * allocated area already is >= the new size.  (In particular, we always	 * fall out here if the requested size is a decrease.)	 */	if (oldsize >= size)	{#ifdef MEMORY_CONTEXT_CHECKING		chunk->requested_size = size;		/* set mark to catch clobber of "unused" space */		if (size < oldsize)			((char *) pointer)[size] = 0x7E;#endif		return pointer;	}	if (oldsize > ALLOC_CHUNK_LIMIT)	{		/*		 * The chunk must been allocated as a single-chunk block.  Find the		 * containing block and use realloc() to make it bigger with minimum		 * space wastage.		 */		AllocBlock	block = set->blocks;		AllocBlock	prevblock = NULL;		Size		chksize;		Size		blksize;		while (block != NULL)		{			if (chunk == (AllocChunk) (((char *) block) + ALLOC_BLOCKHDRSZ))				break;			prevblock = block;			block = block->next;		}		if (block == NULL)			elog(ERROR, "could not find block containing chunk %p", chunk);		/* let's just make sure chunk is the only one in the block */		Assert(block->freeptr == ((char *) block) +			   (chunk->size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ));		/* Do the realloc */		chksize = MAXALIGN(size);		blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;		block = (AllocBlock) realloc(block, 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->freeptr = block->endptr = ((char *) block) + blksize;		/* Update pointers since block has likely been moved */		chunk = (AllocChunk) (((char *) block) + ALLOC_BLOCKHDRSZ);		if (prevblock == NULL)			set->blocks = block;		else			prevblock->next = block;		chunk->size = chksize;#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		return AllocChunkGetPointer(chunk);	}	else	{		/*		 * Small-chunk case.  If the chunk is the last one in its block, there		 * might be enough free space after it that we can just enlarge the		 * chunk in-place.	It's relatively painful to find the containing		 * block in the general case, but we can detect last-ness quite		 * cheaply for the typical case where the chunk is in the active		 * (topmost) allocation block.	(At least with the regression tests		 * and code as of 1/2001, realloc'ing the last chunk of a non-topmost		 * block hardly ever happens, so it's not worth scanning the block		 * list to catch that case.)		 *		 * NOTE: must be careful not to create a chunk of a size that		 * AllocSetAlloc would not create, else we'll get confused later.		 */		AllocPointer newPointer;		if (size <= ALLOC_CHUNK_LIMIT)		{			AllocBlock	block = set->blocks;			char	   *chunk_end;			chunk_end = (char *) chunk + (oldsize + ALLOC_CHUNKHDRSZ);			if (chunk_end == block->freeptr)			{				/* OK, it's last in block ... is there room? */				Size		freespace = block->endptr - block->freeptr;				int			fidx;				Size		newsize;				Size		delta;				fidx = AllocSetFreeIndex(size);				newsize = 1 << (fidx + ALLOC_MINBITS);				Assert(newsize >= oldsize);				delta = newsize - oldsize;				if (freespace >= delta)				{					/* Yes, so just enlarge the chunk. */					block->freeptr += delta;					chunk->size += delta;#ifdef MEMORY_CONTEXT_CHECKING					chunk->requested_size = size;					/* set mark to catch clobber of "unused" space */					if (size < chunk->size)						((char *) pointer)[size] = 0x7E;#endif					return pointer;				}			}		}		/* Normal small-chunk case: just do it by brute force. */		/* allocate new chunk */		newPointer = AllocSetAlloc((MemoryContext) set, size);		/* transfer existing data (certain to fit) */		memcpy(newPointer, pointer, oldsize);		/* free old chunk */		AllocSetFree((MemoryContext) set, pointer);		return newPointer;	}}/* * AllocSetGetChunkSpace *		Given a currently-allocated chunk, determine the total space *		it occupies (including all memory-allocation overhead). */static SizeAllocSetGetChunkSpace(MemoryContext context, void *pointer){	AllocChunk	chunk = AllocPointerGetChunk(pointer);	return chunk->size + ALLOC_CHUNKHDRSZ;}/* * AllocSetIsEmpty *		Is an allocset empty of any allocated space? */static boolAllocSetIsEmpty(MemoryContext context){	AllocSet	set = (AllocSet) context;	/*	 * For now, we say "empty" only if the context is new or just reset. We	 * could examine the freelists to determine if all space has been freed,	 * but it's not really worth the trouble for present uses of this	 * functionality.	 */	if (set->isReset)		return true;	return false;}/* * AllocSetStats *		Displays stats about memory consumption of an allocset. */static voidAllocSetStats(MemoryContext context){	AllocSet	set = (AllocSet) context;	long		nblocks = 0;	long		nchunks = 0;	long		totalspace = 0;	long		freespace = 0;	AllocBlock	block;	AllocChunk	chunk;	int			fidx;	for (block = set->blocks; block != NULL; block = block->next)	{		nblocks++;		totalspace += block->endptr - ((char *) block);		freespace += block->endptr - block->freeptr;	}	for (fidx = 0; fidx < ALLOCSET_NUM_FREELISTS; fidx++)	{		for (chunk = set->freelist[fidx]; chunk != NULL;			 chunk = (AllocChunk) chunk->aset)		{			nchunks++;			freespace += chunk->size + ALLOC_CHUNKHDRSZ;		}	}	fprintf(stderr,			"%s: %ld total in %ld blocks; %ld free (%ld chunks); %ld used\n",			set->header.name, totalspace, nblocks, freespace, nchunks,			totalspace - freespace);}#ifdef MEMORY_CONTEXT_CHECKING/* * AllocSetCheck *		Walk through chunks and check consistency of memory. * * NOTE: report errors as WARNING, *not* ERROR or FATAL.  Otherwise you'll * find yourself in an infinite loop when trouble occurs, because this * routine will be entered again when elog cleanup tries to release memory! */static voidAllocSetCheck(MemoryContext context){	AllocSet	set = (AllocSet) context;	char	   *name = set->header.name;	AllocBlock	block;	for (block = set->blocks; block != NULL; block = block->next)	{		char	   *bpoz = ((char *) block) + ALLOC_BLOCKHDRSZ;		long		blk_used = block->freeptr - bpoz;		long		blk_data = 0;		long		nchunks = 0;		/*		 * Empty block - empty can be keeper-block only		 */		if (!blk_used)		{			if (set->keeper != block)				elog(WARNING, "problem in alloc set %s: empty block %p",					 name, block);		}		/*		 * Chunk walker		 */		while (bpoz < block->freeptr)		{			AllocChunk	chunk = (AllocChunk) bpoz;			Size		chsize,						dsize;			char	   *chdata_end;			chsize = chunk->size;		/* aligned chunk size */			dsize = chunk->requested_size;		/* real data */			chdata_end = ((char *) chunk) + (ALLOC_CHUNKHDRSZ + dsize);			/*			 * Check chunk size			 */			if (dsize > chsize)				elog(WARNING, "problem in alloc set %s: req size > alloc size for chunk %p in block %p",					 name, chunk, block);			if (chsize < (1 << ALLOC_MINBITS))				elog(WARNING, "problem in alloc set %s: bad size %lu for chunk %p in block %p",					 name, (unsigned long) chsize, chunk, block);			/* single-chunk block? */			if (chsize > ALLOC_CHUNK_LIMIT &&				chsize + ALLOC_CHUNKHDRSZ != blk_used)				elog(WARNING, "problem in alloc set %s: bad single-chunk %p in block %p",					 name, chunk, block);			/*			 * If chunk is allocated, check for correct aset pointer. (If it's			 * free, the aset is the freelist pointer, which we can't check as			 * easily...)			 */			if (dsize > 0 && chunk->aset != (void *) set)				elog(WARNING, "problem in alloc set %s: bogus aset link in block %p, chunk %p",					 name, block, chunk);			/*			 * Check for overwrite of "unallocated" space in chunk			 */			if (dsize > 0 && dsize < chsize && *chdata_end != 0x7E)				elog(WARNING, "problem in alloc set %s: detected write past chunk end in block %p, chunk %p",					 name, block, chunk);			blk_data += chsize;			nchunks++;			bpoz += ALLOC_CHUNKHDRSZ + chsize;		}		if ((blk_data + (nchunks * ALLOC_CHUNKHDRSZ)) != blk_used)			elog(WARNING, "problem in alloc set %s: found inconsistent memory block %p",				 name, block);	}}#endif   /* MEMORY_CONTEXT_CHECKING */

⌨️ 快捷键说明

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