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

📄 heapman.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	{
		HostMemSet(pvLinAddr, (IMG_UINT8)DBG_MEMORY_INITIALIZER, ui32Size);
	}
#endif /*DEBUG*/

	return(pvLinAddr);
}



/**************************************************************************
 * Function Name  : AllocFromExistingBlocks()
 * Inputs         : psHostHeap - pointer the host heap
 *					ui32Size - size of block to alloc
 *					ui32Alignment - alignment required for this allocation
 *						must be a power of two
 *					ui32OwnerAddr - addr of allocater
 * Outputs        : None
 * Returns        : Linear address of buffer alloced on success else NULL
 * Globals Used   : None
 * Description    : Walk through the heap looking for free blocks big enough
 *					for this alloc
 **************************************************************************/
IMG_PVOID AllocFromExistingBlocks(HOST_HEAP *psHostHeap, IMG_UINT32 ui32Size, IMG_UINT32 ui32Alignment, IMG_UINT32 ui32OwnerAddr)
{
	PGLOB_HEAP	psCurHeapBlock;
	PGLOB_HEAP	psNewHeapBlock;
	IMG_UINT32		ui32HeaderSize;
	IMG_PVOID		pvCallerBufStart;

	if (ui32OwnerAddr);

	psCurHeapBlock = psHostHeap->psFreeHeapStart;

	/*Look at each block*/
	while (psCurHeapBlock != NULL)
	{
		/*Check if block is already used*/
		if ((psCurHeapBlock->ui32Flags & GHEAP_BLOCK_ALLOCATED) == 0)
		{
			/* Quick check to if block size is anywhere near big enough */
			if (psCurHeapBlock->ui32BlockSize > (ui32Size + sizeof(GLOB_HEAP)))
			{
				/*Check if this block will be big enough*/
				CalcBufAlignment(psCurHeapBlock, ui32Alignment, &ui32HeaderSize);

				/* Check if alloc is allowed to split page */
				if ((psHostHeap->ui32Flags & HEAP_ALLOC_CANT_SPLIT_PAGE) != 0)
				{
					PBYTE	pbyBufFirstByte=(PBYTE)psCurHeapBlock + ui32HeaderSize;
					PBYTE	pbyBufLastByte=pbyBufFirstByte + ui32Size - 1;

					if (((IMG_UINT32)pbyBufFirstByte & ~0xfff) != ((IMG_UINT32)pbyBufLastByte & ~0xfff))
					{
						/* Ensure that alloc comes from same page */
						ui32HeaderSize+=0x1000 - ((IMG_UINT32)pbyBufFirstByte & 0xfff);
					}
				}

				if ((ui32HeaderSize + ui32Size) <= psCurHeapBlock->ui32BlockSize)
				{
					/*Setup block header*/
					psCurHeapBlock->ui32Flags |= GHEAP_BLOCK_ALLOCATED;
					pvCallerBufStart=(BYTE *)psCurHeapBlock + ui32HeaderSize;
					*((IMG_UINT32 *)pvCallerBufStart-1)=(IMG_UINT32)psCurHeapBlock;

					#if defined(DEBUG) && !defined(NO_ALLOC_TRACKING)
					psCurHeapBlock->pfnOwner=(POWNER_FN)ui32OwnerAddr;
					#endif /* #if defined(DEBUG) && !defined(NO_ALLOC_TRACKING) */

					/* Inc count of allocations in the heap */
					psHostHeap->ui32AllocsInHeap++;

					/* Remove block from free list */
					HeapRemoveBlockToFreeList(psHostHeap, psCurHeapBlock);

					/*
						Exact size, don't need to allocate new heap struct.
					*/
					if ((ui32HeaderSize + ui32Size) == psCurHeapBlock->ui32BlockSize)
					{
						return(pvCallerBufStart);
					}
			
					/*
						Not exact size, if we have space for another heap structure 
						in the remains of the block set it up as a new one, otherwise 
						leave orignal block at its full size.
					*/
					if ((psCurHeapBlock->ui32BlockSize - (ui32HeaderSize + ui32Size)) > (sizeof(GLOB_HEAP) + sizeof(IMG_PVOID)))
					{
						psNewHeapBlock=(PGLOB_HEAP)((PBYTE)psCurHeapBlock + (ui32HeaderSize + ui32Size));
						psNewHeapBlock->ui32Signiture=HOST_HEAP_SIGNITURE;
						psNewHeapBlock->ui32Flags = psCurHeapBlock->ui32Flags & ~(GHEAP_BLOCK_ALLOCATED | GHEAP_BLOCK_HEAD);
						psNewHeapBlock->ui32BlockSize = psCurHeapBlock->ui32BlockSize - (ui32HeaderSize + ui32Size);
						psNewHeapBlock->psHeap=psHostHeap;
						psCurHeapBlock->ui32BlockSize = (ui32HeaderSize + ui32Size);

						/*
							Insert new block into list.
						*/
						if (psCurHeapBlock->psNext != NULL)
						{
							psCurHeapBlock->psNext->psPrev = psNewHeapBlock;
						}

						psNewHeapBlock->psNext = psCurHeapBlock->psNext;
						psNewHeapBlock->psPrev = psCurHeapBlock;
						psCurHeapBlock->psNext = psNewHeapBlock;
					
						/* Insert new block at front of free list */
						HeapAddBlockToFreeList(psHostHeap, psNewHeapBlock);
					}

					/* Chech does not split page if is should not */
					PVR_ASSERT(((psHostHeap->ui32Flags & HEAP_ALLOC_CANT_SPLIT_PAGE) == 0) || ((IMG_UINT32)(pvCallerBufStart) & ~0xfff) == (((IMG_UINT32)(pvCallerBufStart)+ui32Size-1) & ~0xfff));

					/* And return pointer to allocate memory. */
					return(pvCallerBufStart);
				}/* End check if this block will be big enough*/		
			}/* End of quick check of block size */
		}/* End checking if block is already used*/

		/*Onto next heap block*/
		psCurHeapBlock = psCurHeapBlock->psNextFree;
	}/*End looking at each block*/

	return(NULL);
}



/**************************************************************************
 * Function Name  : MemHeapFree
 * Inputs         : psHostHeap - pointer to heap to free from
 *					pvMemPtr - linear address of buffer to free
 *					pvHeapContext - context pointer passed onto the page free
 *						routine
 * Outputs        : None
 * Returns        : TRUE on success, FALSE on failure
 * Globals Used   : None
 * Description    : Frees a block that was alloced using MemHeapAlloc()
 **************************************************************************/
IMG_BOOL MemHeapFree(IMG_PVOID pvMemPtr, IMG_PVOID pvHeapContext)
{
	PGLOB_HEAP	psHeapBlock;
	PGLOB_HEAP	psNext;
	PGLOB_HEAP	psPrev;
	HOST_HEAP	*psHostHeap;

	/*Check for NULL*/
	if (pvMemPtr == NULL)
	{
		PVR_DPF((PVR_DBG_ERROR, "HostFreeMem() Caller tried to free NULL!!!\n"));
		return FALSE;
	}
																	    
	/*Go back from memory pointer to heap block.*/
	psHeapBlock = (PGLOB_HEAP) *((IMG_UINT32 *)pvMemPtr - 1);
	psHostHeap=psHeapBlock->psHeap;

	/*Check this is a valid block*/
	if (psHeapBlock == NULL || psHeapBlock->ui32Signiture != HOST_HEAP_SIGNITURE)
	{
		PVR_DPF((PVR_DBG_ERROR, "HostFreeMem() Caller tried to free a block (0x%lx) that is not valid!!!\n", pvMemPtr));
		DBG_BREAK;
		return FALSE;
	}

	/* Check next block sign */
	PVR_ASSERT(psHeapBlock->psNext == NULL || psHeapBlock->psNext->ui32Signiture == HOST_HEAP_SIGNITURE);

	/*Check this is a allocated block*/
	if ((psHeapBlock->ui32Flags & GHEAP_BLOCK_ALLOCATED) == 0)
	{
		PVR_DPF((PVR_DBG_ERROR, "HostFreeMem() Caller tried to free block (0x%lx) has not been allocated!!!\n", pvMemPtr));
		DBG_BREAK;
		return FALSE;
	}

	/*Indicate that this block is now free*/
	psHeapBlock->ui32Flags &= ~GHEAP_BLOCK_ALLOCATED;

	#if defined(DEBUG) && !defined(NO_ALLOC_TRACKING)
	psHeapBlock->pfnOwner=(POWNER_FN)NULL;
	#endif /* #if defined(DEBUG) && !defined(NO_ALLOC_TRACKING) */

	/*Free memory if it was a single allocation*/
	if (psHeapBlock->ui32Flags & GHEAP_SINGLE)
	{
		/*Single allocation heap, just need to free pages.*/
		ProcessAllocCallbacks(FALSE, psHeapBlock, psHeapBlock->ui32BlockSize / HOST_PAGESIZE());
		ReleasePages(psHeapBlock->psPageState, psHeapBlock->ui32BlockSize / HOST_PAGESIZE());
		(psHostHeap->pfnHostFreePage)((IMG_PVOID)psHeapBlock, psHeapBlock->ui32BlockSize / HOST_PAGESIZE(), pvHeapContext, ((PGLOB_HEAP_HEAD)psHeapBlock)->pvBlkAllocContext);
		return TRUE;
	}

	/* Decrease count of allocations in the heap */
	psHostHeap->ui32AllocsInHeap--;

	/*
		Traverse forward through list contatenating free blocks until we either,
		* come to the end of the list,
		* come to an allocated block,
		* come to a new page allocation block (defined by GHEAP_BLOCK_HEAD) 
	*/
	psNext = psHeapBlock->psNext;
	while	(
				(psNext != NULL) && 
				!(psNext->ui32Flags & GHEAP_BLOCK_ALLOCATED) && 
				!(psNext->ui32Flags & GHEAP_BLOCK_HEAD)
			)
	{
		psHeapBlock->ui32BlockSize += psNext->ui32BlockSize;

		/*
			Remove block from list.
		*/
		if (psNext->psNext != NULL)
		{
			psNext->psNext->psPrev = psHeapBlock;
		}
		psHeapBlock->psNext = psNext->psNext;

		/* Remove block from free list */
		HeapRemoveBlockToFreeList(psHostHeap, psNext);

		/*
			To be safe zero concatenated blocks link pointers.
		*/
		psNext->psNext = (PGLOB_HEAP) 0;
		psNext->psPrev = (PGLOB_HEAP) 0;

		/*
			Move to next block.
		*/
		psNext = psHeapBlock->psNext;
	}

	/*
		Same again but traverse back from block...
	*/
	psPrev = psHeapBlock->psPrev;

	while	(
				(psPrev != NULL) && 
				!(psPrev->ui32Flags & GHEAP_BLOCK_ALLOCATED) &&
				!(psHeapBlock->ui32Flags & GHEAP_BLOCK_HEAD)
			)
	{
		psNext = psHeapBlock;
		psHeapBlock = psPrev;

		psHeapBlock->ui32BlockSize += psNext->ui32BlockSize;

		/*
			Remove block from list.
		*/
		if (psNext->psNext != NULL)
		{
			psNext->psNext->psPrev = psHeapBlock;
		}
		psHeapBlock->psNext = psNext->psNext;

		/* Remove block from free list */
		HeapRemoveBlockToFreeList(psHostHeap, psHeapBlock);

		/*
			Move to next block.
		*/
		psPrev = psHeapBlock->psPrev;

		/*
			To be safe zero concatenated blocks link pointers.
		*/
		psNext->psNext = (PGLOB_HEAP) 0;
		psNext->psPrev = (PGLOB_HEAP) 0;
	}

	#ifdef DEBUG
	/* On a free set memory to known state */
	if ((psHeapBlock->ui32Flags & GHEAP_BLOCK_HEAD) == 0)
	{		
 		HostMemSet((IMG_PVOID)(psHeapBlock+1), (IMG_UINT8)DBG_MEMORY_DEALLOC_INITIALIZER, psHeapBlock->ui32BlockSize - sizeof(GLOB_HEAP));
	}
	else
	{
		HostMemSet((IMG_PVOID)(((PGLOB_HEAP_HEAD)psHeapBlock)+1), (IMG_UINT8)DBG_MEMORY_DEALLOC_INITIALIZER, psHeapBlock->ui32BlockSize - sizeof(GLOB_HEAP_HEAD));
	}
	#endif /* #ifdef DEBUG */

	/*
		If this block is a block head and it either points to another block
		head or the end of the heap list, remove from heap list and free the 
		pages allocated within it.
	*/
	if (psHeapBlock->ui32Flags & GHEAP_BLOCK_HEAD)
	{
		if (psHeapBlock->psNext == NULL)
		{
			if (psHeapBlock->psPrev == NULL)
			{
				/*This is heap head, so heap will be empty*/
				psHostHeap->psHeapStart=(PGLOB_HEAP)NULL;
			}
			else
			{
				psHeapBlock->psPrev->psNext = (PGLOB_HEAP)NULL;
			}

			/*Free allocated pages*/
			ProcessAllocCallbacks(FALSE, psHeapBlock, psHostHeap->ui32ExpandSizeInPages * HOST_PAGESIZE());
			ReleasePages(psHeapBlock->psPageState, psHostHeap->ui32ExpandSizeInPages);
			(psHostHeap->pfnHostFreePage)((IMG_PVOID)psHeapBlock, psHostHeap->ui32ExpandSizeInPages, pvHeapContext, ((PGLOB_HEAP_HEAD)psHeapBlock)->pvBlkAllocContext);
			psHostHeap->ui32CurHeapSizeInPages-=psHostHeap->ui32ExpandSizeInPages;
			psHeapBlock=(PGLOB_HEAP)NULL;
		}
		else
		{
			if (psHeapBlock->psNext->ui32Flags & GHEAP_BLOCK_HEAD)
			{
				if (psHeapBlock->psPrev == NULL)
				{
					/*Is heap head, next block becomes head*/
					psHostHeap->psHeapStart=psHeapBlock->psNext;
				}
				else
				{
					psHeapBlock->psPrev->psNext = psHeapBlock->psNext;
				}

				psHeapBlock->psNext->psPrev = psHeapBlock->psPrev;

				/*Free allocated pages.*/
				ProcessAllocCallbacks(FALSE, psHeapBlock, psHostHeap->ui32ExpandSizeInPages * HOST_PAGESIZE());
				ReleasePages(psHeapBlock->psPageState, psHostHeap->ui32ExpandSizeInPages);
				(psHostHeap->pfnHostFreePage)((IMG_PVOID)psHeapBlock, psHostHeap->ui32ExpandSizeInPages, pvHeapContext, ((PGLOB_HEAP_HEAD)psHeapBlock)->pvBlkAllocContext);
				psHostHeap->ui32CurHeapSizeInPages-=psHostHeap->ui32ExpandSizeInPages;
				psHeapBlock=(PGLOB_HEAP)NULL;
			}
		}
	}

	/* If we did not free that block of memory add it so the free list */
	if (psHeapBlock != NULL)
	{
		HeapAddBlockToFreeList(psHostHeap, psHeapBlock);
	}

	return TRUE;			
}



/**************************************************************************
 * Function Name  : CalcBufAlignment
 * Inputs         : pvStartOfBlock - linear address of the start of block
 *					ui32Alignment - required alignment of buffer
 * Outputs        : pui32HeaderSize - pointer to varable that will receive the
 *						header size for the given block
 * Returns        : None
 * Globals Used   : None
 * Description    : Given the start of the block and required alignment this
 *					routine will calculate the header size and alignment			
 *					buffer size to that the address passed back to the caller
 *					is aligned correctly
 **************************************************************************/
IMG_VOID CalcBufAlignment(PGLOB_HEAP psStartOfBlock, IMG_UINT32 ui32Alignment, IMG_UINT32 *pui32HeaderSize)
{
	IMG_PVOID	pvEndOfHeader;
	IMG_UINT32	ui32SizeOfStruct=sizeof(GLOB_HEAP);
	
	if ((psStartOfBlock->ui32Flags & GHEAP_BLOCK_HEAD) != 0)
	{
		ui32SizeOfStruct=sizeof(GLOB_HEAP_HEAD);
	}

	/*Calc end of header*/
	pvEndOfHeader=(IMG_PVOID)((IMG_UINT32)((BYTE *)psStartOfBlock + ui32SizeOfStruct + sizeof(IMG_PVOID) + ui32Alignment - 1) & ~(ui32Alignment-1));
	
	/*Calc header size and aligmnent buffer size*/
	*pui32HeaderSize=(BYTE *)pvEndOfHeader - (BYTE *)psStartOfBlock;
	
	PVR_ASSERT((*pui32HeaderSize - (ui32SizeOfStruct + sizeof(IMG_PVOID))) < ui32Alignment);
	return;
}



/**************************************************************************
 * Function Name  : IsValidAlignment
 * Inputs         : ui32Value - the requested alignment
 * Outputs        : None
 * Returns        : TRUE if alignment is valid, else FALSE
 * Globals Used   : aui32ValidAlignments - read values from table
 * Description    : Check if the requested alignment is valid (has to be power
 *					of two) by looking for it in the valid alignments table			
 **************************************************************************/
IMG_BOOL IsValidAlignment(IMG_UINT32 ui32Value)
{
	IMG_UINT32	*pui32ValidAlignment=aui32ValidAlignments;

	while (*pui32ValidAlignment != 0)
	{
		if (ui32Value == *(pui32ValidAlignment++))
		{
			return TRUE;
		}
	}

	return FALSE;
}



/**************************************************************************
 * Function Name  : HeapAddBlockToFreeList
 * Inputs         : psHostHeap - ptr to host heap this block belongs to
 *					psNewBlock - new block to be added to free list
 * Outputs        : None
 * Returns        : None
 * Globals Used   : None
 * Description    : Insert a block at the front of the free list
 **************************************************************************/
__inline IMG_VOID HeapAddBlockToFreeList(HOST_HEAP *psHostHeap, PGLOB_HEAP psNewBlock)
{
	/* Insert new block at front of free list */
	psNewBlock->psNextFree=psHostHeap->psFreeHeapStart;
	psNewBlock->psPrevFree=(PGLOB_HEAP)NULL;
	if (psHostHeap->psFreeHeapStart != NULL)
	{
		psHostHeap->psFreeHeapStart->psPrevFree=psNewBlock;
	}
	psHostHeap->psFreeHeapStart=psNewBlock;
}



⌨️ 快捷键说明

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