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

📄 heapman.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 4 页
字号:

	/*
		Kernel manager code relies on the fact that calling AllicHostMem()
		with a zero size will pass back a NULL linear address and return PVRSRV_OK
	*/
	if (ui32Size==0)
	{
		return (PVRSRV_OK);
	}

	if (ui32HeapIndex == PVRSRV_HOST_PAGEABLE_HEAP)
	{
		pvLinAddr=HostPageableByteAlloc(ui32Size);
		bAllocDone=TRUE;
	}

	/* If alloc was done by OS function */
	if (bAllocDone == TRUE)
	{
		if (pvLinAddr == NULL)
		{
			PVR_DPF((PVR_DBG_ERROR, "HostAllocMem : OS byte alloc failed, if using special pool on NT then you may need from RAM!!!!\n"));
			return(PVRSRV_ERROR_OUT_OF_MEMORY);
		}

		*ppvLinAddr=pvLinAddr;
		return (PVRSRV_OK);
	}

	/* Check the heap requested is valid, and find which heap we will use */
	if (ui32HeapIndex > PVRSRV_HOST_MAX_HEAP)
	{
		PVR_DPF((PVR_DBG_ERROR, "Invalid heap (%lx) passed to HostAllocMem()\n", ui32HeapIndex));

		return (PVRSRV_ERROR_OUT_OF_MEMORY);
	}

	/* Attempt to alloc memory and store linear address if successful */
	if ((pvLinAddr=MemHeapAlloc(psEnvData->psHeap, ui32Size, 4, NULL, ui32OwnerAddr)) == NULL)	
	{
#ifdef DEBUG
		/* Check heap */
		CheckHostHeaps();
#endif
		return PVRSRV_ERROR_OUT_OF_MEMORY;
	}
	*ppvLinAddr=pvLinAddr;

#ifdef DEBUG
	/*Check heap*/
	CheckHostHeaps();
#endif

	PVR_DPF((PVR_DBG_MESSAGE, "HostAllocMem() alloced the memory at 0x%lx", pvLinAddr));
	return (PVRSRV_OK);
}
	



/*!
******************************************************************************

 @Function		HostFreeMem
 
 @Description	Allocates host memory from one of the host heaps
 
 @Input    pvLinAddr - address to memory to free
 @Input    ui32Flags - allocation flags to identify alloc heap

 @Return   PVRSRV_OK on success else PVRSRV_ERROR_OUT_OF_MEMORY 

******************************************************************************/ 
PVRSRV_ERROR HostFreeMem(IMG_UINT32 ui32Flags, IMG_PVOID pvLinAddr)
{
	IMG_UINT32	ui32HeapIndex=ui32Flags & PVRSRV_HOST_HEAP_MASK;
	IMG_BOOL	bFreeDone=FALSE;

	PVR_DPF((PVR_DBG_MESSAGE, "HostFreeMem() called to free block at 0x%lx with alloc flags of %lx", pvLinAddr, ui32Flags));

#ifdef DEBUG
	/*Check heap*/
	CheckHostHeaps();
#endif

	if (pvLinAddr == NULL)
	{
		PVR_DPF((PVR_DBG_ERROR, "HostFreeMem() Caller tried to free NULL!!!\n"));
		return PVRSRV_ERROR_OUT_OF_MEMORY;
	}

	if (ui32HeapIndex == PVRSRV_HOST_PAGEABLE_HEAP)
	{
		HostPageableByteFree(pvLinAddr);			
		bFreeDone=TRUE;
	}

	if (bFreeDone == TRUE)
	{
		return PVRSRV_OK;
	}	

	/* Free memory */
	if (MemHeapFree(pvLinAddr, NULL) == FALSE)
	{
#ifdef DEBUG
		/*Check heap*/
		CheckHostHeaps();
#endif
		return PVRSRV_ERROR_OUT_OF_MEMORY;
	}

#ifdef DEBUG
	/*Check heap*/
	CheckHostHeaps();
#endif

	return PVRSRV_OK;
}


/**************************************************************************
 * Function Name  : HostNonPageablePageAlloc()
 * Inputs         : ui32NumPages - number of pages to alloc
 *					pvHeapContext - context pointer passed to MemHeapAlloc()
 * Outputs        : None
 * Returns        : Pointer to linear address of allocated non-cached memory 
 *					if success, returns NULL on failure
 * Globals Used   : None
 * Description    : Wrapper function to alloc paged 
 **************************************************************************/
IMG_PVOID HostNonPageablePageAlloc(IMG_UINT32 ui32NumPages, IMG_PVOID pvHeapContext, IMG_PVOID *ppvAllocContext, IMG_PVOID pvLinAddr)
{
	return VirtualAlloc(pvLinAddr, ui32NumPages << 12, MEM_COMMIT, PAGE_READWRITE);
}


/**************************************************************************
 * Function Name  : HostNonPageablePageFree
 * Inputs         : pvLinAddr - linear address of buffer to be freed
 *					ui32NumPages - number of pages to free NOT USED
 *					pvHeapContext - context that was passed to MemHeapFree() NOT USED
 * Outputs        : None
 * Returns        : None
 * Globals Used   : None
 * Description    : Free pages allocated via HostNonPageablePageAlloc()
 **************************************************************************/
IMG_VOID HostNonPageablePageFree(IMG_PVOID pvLinAddr, IMG_UINT32 ui32NumPages, IMG_PVOID pvHeapContext, IMG_PVOID pvAllocContext)
{
	VirtualFree(pvLinAddr, ui32NumPages << 12, MEM_DECOMMIT);
}


/**************************************************************************
 * Function Name  : CheckHostHeaps
 * Inputs         : None
 * Outputs        : None
 * Returns        : None
 * Globals Used   : Reads asHostHeaps table
 * Description    : Walks through all the heaps checking for corruptions
 **************************************************************************/
IMG_VOID CheckHostHeaps(IMG_VOID)
{
	SYS_DATA			*psSysData;
	PVRSRV_ERROR		eError = PVRSRV_OK;

	eError = SysAcquireData(&psSysData);
	if (eError != PVRSRV_OK)
	{
		return;
	}

	CheckSingleHeap((PHOST_HEAP)psSysData->pvEnvSpecificData, FALSE);

	/* Can't check cache coherant heap as its per-device */
	return;
}





IMG_UINT32 AddHostHeapBlockAllocCallback(PFN_HEAPBLOCK_CALLBACK pfnFunc)
{
	SYS_DATA			*psSysData;
	PVRSRV_ERROR		eError = PVRSRV_OK;
	ENV_DATA				*psEnvData;

	eError = SysAcquireData(&psSysData);
	if (eError != PVRSRV_OK)
	{
		return eError;
	}

	psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;

	/* Install callback */
	if (AddBlockAllocCallback(pfnFunc) == FALSE)
	{
		PVR_DPF((PVR_DBG_ERROR, "AddHostHeapBlockAllocCallback : Failed to register callback"));

		return PVRSRV_ERROR_CANT_REGISTER_CALLBACK;
	}

	/* Now create callback for non-paged heap */
	DoBlockCallbacksForHeap(psEnvData->psHeap);

	return PVRSRV_OK;
}


IMG_UINT32 RemoveHostHeapBlockAllocCallback(PFN_HEAPBLOCK_CALLBACK pfnFunc)
{
	RemoveBlockAllocCallback(pfnFunc);
	return PVRSRV_OK;
}


PPAGE_STATE AcquirePages (HOST_HEAP *psHeap, IMG_UINT32 ui32RequiredPages)
{
	PPAGE_STATE	psPageState = psHeap->psPageState;
	IMG_UINT32	i, ui32PageCount = 0;

	for (i=0; i<psHeap->ui32MaxHeapSizeInPages; i++)
	{
		if (psPageState[i].bPageCommitted == IMG_FALSE)
		{
			ui32PageCount++;
			if (ui32PageCount == ui32RequiredPages)
			{
				psPageState = &psPageState[i];
				psPageState -= ui32PageCount-1;
				/* mark in use, walking backwards */
				for(i=0; i<ui32PageCount; i++)
				{
					psPageState[i].bPageCommitted = IMG_TRUE;
				}
				/* return base page */
				return psPageState;
			}
		}
		else
		{
			ui32PageCount = 0;
		}
	}
	
	return NULL;	
}

IMG_VOID ReleasePages (PPAGE_STATE	psPageState, IMG_UINT32 ui32Pages)
{
	while(ui32Pages--)
	{
		psPageState->bPageCommitted = IMG_FALSE;
		psPageState++;
	}
}

/**************************************************************************
 * Function Name  : MemHeapAlloc()
 * Inputs         : psHostHeap - pointer to which host heap to use for alloc
 *					ui32Size - size of block to alloc
 *					ui32Alignment - alignment required for this allocation
 *						must be a power of two
 *					pvHeapContext - context pointer passed onto the page allocate
 *						routine
 *					ui32OwnerAddr - addr of allocating code
 * Outputs        : None
 * Returns        : Linear address of buffer alloced on success else NULL
 * Globals Used   : None
 * Description    : Alloc memory from the given host heap
 **************************************************************************/
IMG_PVOID MemHeapAlloc(HOST_HEAP *psHostHeap, IMG_UINT32 ui32Size, IMG_UINT32 ui32Alignment, IMG_PVOID pvHeapContext, IMG_UINT32 ui32OwnerAddr)
{
	IMG_PVOID	pvLinAddr;

	/*Check for zero sized allocations*/
	if (ui32Size == 0)
	{
		PVR_DPF((PVR_DBG_ERROR, "MemHeapAlloc() got a request for a zero sized allocations!\n"));
		return NULL;
	}
	
	/*Check that alignment is a power of two because calc of alignment
	buffer relies on this, also why should anyone want to do anything else????*/
	if (IsValidAlignment(ui32Alignment) == FALSE)
	{
		PVR_DPF((PVR_DBG_ERROR, "MemHeapAlloc() alignment value is not a power of two!!!!\n"));
		return NULL;
	}

	/*Check if requested size is bigger than we can allow from within the heap*/
	if (ui32Size > psHostHeap->ui32MaxSingleHeapAllocInBytes)
	{
		/*Check if we are allowed to do single allocations*/
		if (psHostHeap->bAllowLargeSingleAllocs == TRUE)
		{
			PGLOB_HEAP_HEAD	psBlock;
			IMG_UINT32			ui32HeaderSize;
			IMG_UINT32			ui32AllocSizeInPages;
			IMG_PVOID			pvAllocContext;
			PPAGE_STATE			psPageState;

			/*Alloc host pages*/
			ui32AllocSizeInPages=(ui32Size + ui32Alignment + sizeof(GLOB_HEAP_HEAD) + HOST_PAGESIZE() - 1) / HOST_PAGESIZE();

			psPageState = AcquirePages(psHostHeap, ui32AllocSizeInPages);
			if (psPageState == NULL)
			{
				PVR_DPF((PVR_DBG_ERROR, "MemHeapAlloc() could not allocate a page block!\n"));
				return(NULL);
			}

			psBlock=(PGLOB_HEAP_HEAD)(psHostHeap->pfnHostAllocPage)(ui32AllocSizeInPages, pvHeapContext, &pvAllocContext, psPageState->pvLinearAddr);
			if (psBlock == NULL)
			{
				PVR_DPF((PVR_DBG_ERROR, "MemHeapAlloc() could not allocate single block!\n"));
				return(NULL);
			}
			
			ProcessAllocCallbacks(TRUE, &psBlock->sGlobHeap, ui32AllocSizeInPages * HOST_PAGESIZE());
		
			/*Set block structure*/
			psBlock->sGlobHeap.ui32Signiture=HOST_HEAP_SIGNITURE;
			psBlock->sGlobHeap.ui32Flags =GHEAP_BLOCK_ALLOCATED | GHEAP_SINGLE;
			psBlock->sGlobHeap.ui32BlockSize = ui32AllocSizeInPages * HOST_PAGESIZE();
			psBlock->sGlobHeap.psNext = (PGLOB_HEAP) 0;
			psBlock->sGlobHeap.psPrev = (PGLOB_HEAP) 0;
			psBlock->sGlobHeap.psHeap = psHostHeap;
			psBlock->sGlobHeap.psPageState = psPageState;
			psBlock->pvBlkAllocContext=pvAllocContext;
			#if defined(DEBUG) && !defined(NO_ALLOC_TRACKING)
			psBlock->sGlobHeap.pfnOwner=(POWNER_FN)ui32OwnerAddr;
			#endif /* #if defined(DEBUG) && !defined(NO_ALLOC_TRACKING) */

			/*Calc alignment buf size so that memory would have correct alignment*/
			CalcBufAlignment((PGLOB_HEAP)&psBlock->sGlobHeap, ui32Alignment, &ui32HeaderSize);

			/*Calc linear address to return to caller*/
			pvLinAddr=(BYTE *)psBlock + ui32HeaderSize;
			
			/*Setup back pointer to point back to begining of the block*/
			*((IMG_UINT32 *)pvLinAddr-1)=(IMG_UINT32)psBlock;

			/* Check that the allocate block is big enough */
			PVR_ASSERT((PBYTE)pvLinAddr+ui32Size <= (PBYTE)psBlock + ui32Size + ui32Alignment + sizeof(GLOB_HEAP_HEAD));

			#ifdef DEBUG
			/*On debug builds init memory to known value (not zero)*/
			HostMemSet(pvLinAddr, (IMG_UINT8)DBG_MEMORY_INITIALIZER, ui32Size);
			#endif /*DEBUG*/

			return pvLinAddr;
		}
		else
		{
			/*Alloc size is too big for alloc from heap BUT we
			are not allowed to use single host allocs*/
			PVR_DPF((PVR_DBG_ERROR, "MemHeapAlloc() Alloc size to big for this heap, and we are not allowed to use single allocs!!!!\n"));
			return NULL;
		}
	}

	/* Traverse existings blocks before allocating any more pages.*/
	pvLinAddr = AllocFromExistingBlocks(psHostHeap, ui32Size, ui32Alignment, ui32OwnerAddr);
	if (pvLinAddr == NULL)
	{
		PGLOB_HEAP_HEAD psNew;
		IMG_PVOID			pvAllocContext;
		PPAGE_STATE			psPageState;

		/*Check if we are allowed to grow the heap again*/
		if (psHostHeap->ui32MaxHeapSizeInPages != 0 && (psHostHeap->ui32CurHeapSizeInPages + psHostHeap->ui32ExpandSizeInPages) > psHostHeap->ui32MaxHeapSizeInPages)
		{
			PVR_DPF((PVR_DBG_ERROR, "MemHeapAlloc() heap size has reached its limit!!!!\n"));
			return NULL;
		}

		psPageState = AcquirePages(psHostHeap, psHostHeap->ui32ExpandSizeInPages);
		if (psPageState == NULL)
		{
			PVR_DPF((PVR_DBG_ERROR, "MemHeapAlloc() could not allocate a page block!\n"));
			return(NULL);
		}

		/*
			If we get to this point we have failed to find space in any existing
			blocks, its time to grow our heap.
		*/
		psNew = (PGLOB_HEAP_HEAD)(psHostHeap->pfnHostAllocPage)(psHostHeap->ui32ExpandSizeInPages, pvHeapContext, &pvAllocContext, psPageState->pvLinearAddr);
		if (psNew == NULL)
		{
			PVR_DPF((PVR_DBG_ERROR, "MemHeapAlloc() failed to expand heap!!\n"));
			return(NULL);
		}

		psHostHeap->ui32CurHeapSizeInPages+=psHostHeap->ui32ExpandSizeInPages;
		ProcessAllocCallbacks(TRUE, &psNew->sGlobHeap, psHostHeap->ui32ExpandSizeInPages * HOST_PAGESIZE());

		#ifdef DEBUG
		/* Init unallocated memory to known value */
		HostMemSet(&psNew->sGlobHeap, (IMG_UINT8)DBG_MEMORY_DEALLOC_INITIALIZER, psHostHeap->ui32ExpandSizeInPages * HOST_PAGESIZE());
		#endif /* #ifdef DEBUG */

		/*
			Set structure up. Well Derr..
		*/
		psNew->sGlobHeap.ui32Signiture=HOST_HEAP_SIGNITURE;
		psNew->sGlobHeap.ui32Flags =GHEAP_BLOCK_HEAD;
		psNew->sGlobHeap.ui32BlockSize = psHostHeap->ui32ExpandSizeInPages * HOST_PAGESIZE();
		psNew->sGlobHeap.psPageState = psPageState;
		psNew->sGlobHeap.psHeap=psHostHeap;
		psNew->pvBlkAllocContext=pvAllocContext;

		/*
			Insert at head of list.
		*/
		psNew->sGlobHeap.psNext = (PGLOB_HEAP) psHostHeap->psHeapStart;
		psNew->sGlobHeap.psPrev = (PGLOB_HEAP) NULL;
		if (psHostHeap->psHeapStart != NULL)
		{
			psHostHeap->psHeapStart->psPrev=(PGLOB_HEAP)psNew;
		}		
		psHostHeap->psHeapStart=(PGLOB_HEAP)psNew;

		/* Insert new block at front of free list */
		HeapAddBlockToFreeList(psHostHeap, (PGLOB_HEAP)psNew);

		/*
			Allocation will succeed this time
		*/
		pvLinAddr = AllocFromExistingBlocks(psHostHeap, ui32Size, ui32Alignment, ui32OwnerAddr);
	}

#ifdef DEBUG
	/*On debug builds init memory to known value (not zero)*/
	if (pvLinAddr != NULL)

⌨️ 快捷键说明

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