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

📄 heapman.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*****************************************************************************
 Name			: HEAPMAN.C
 
 Title			: Shared memory heap manager. 
 
 C Author 		: Dave Roberts
 
 Created  		: 24 / 10 / 03
 
 Copyright    : 2002-2003 by Imagination Technologies Limited.
                All rights reserved.  No part of this software, either
                material or conceptual may be copied or distributed,
                transmitted, transcribed, stored in a retrieval system
                or translated into any human or computer language in any
                form by any means, electronic, mechanical, manual or
                other-wise, or disclosed to third parties without the
                express written permission of Imagination Technologies
                Limited, Unit 8, HomePark Industrial Estate,
                King's Langley, Hertfordshire, WD4 8LZ, U.K.

 Description 	: heap manager for shared memory
   
 Program Type	: 32-bit DLL

 Modifications	:
 Initial revision
*****************************************************************************/
#include <windows.h>

#include "img_types.h"
#include "services_headers.h"
#include "heapman.h"

#define DPF_NEWLINE
#define DBG_BREAK

/*************************************************************************
	Structure of the blocks in the heap.

	Block header : Structure that holds info about the block
	Aligment buffer : Buffer used to pad out the header so linear address
						returned to the caller is aligned
	Header size : Is the size of the Block header + Alignment buffer and 
					back pointer
	Back pointer : Use so that from the calls linear address we can
					locate the start of the block
7
	-->	-----------------------------   .    <- start of block linear address
	|	|      Block header         |  /|\
	|	|        (GLOB_HEAP)        |   |
	|	-----------------------------   |
	|	|                           |   |
	|	\                           /   |
	|	.      Alignment buffer     .   Header size
	|	/                           \   | 
	|	|                           |   |
	|	-----------------------------   |
	|--	|     Back pointer          |  \|/
		-----------------------------   .    <- aligned linear address passed back to called
		|                           |
		|                           |
		.                           .
		.                           .
		.                           .

  The alignment buffers size is depenant on the required alignment,
  the size of the GLOB_HEAP struct, the size of the back pointer and
  the linear address of the start of the block.
***************************************************************************/


/*****************************************************************************
 Function prototypes
*****************************************************************************/
IMG_VOID CheckHostHeaps(IMG_VOID);
IMG_PVOID HostNonPageablePageAlloc(IMG_UINT32 ui32NumPages, IMG_PVOID pvHeapContext, IMG_PVOID *ppvAllocContext, IMG_PVOID pvLinAddr);
IMG_VOID HostNonPageablePageFree(IMG_PVOID pvLinAddr, IMG_UINT32 ui32NumPages, IMG_PVOID pvHeapContext, IMG_PVOID pvAllocContext);
IMG_VOID NonCachedHeapCheck(PHOST_HEAP psHeap);
IMG_PVOID AllocFromExistingBlocks(HOST_HEAP *psHostHeap, IMG_UINT32 ui32Size, IMG_UINT32 ui32Alignment, IMG_UINT32 ui32OwnerAddr);
IMG_VOID CalcBufAlignment(PGLOB_HEAP psStartOfBlock, IMG_UINT32 ui32Alignment, IMG_UINT32 *pui32HeaderSize);
IMG_BOOL IsValidAlignment(IMG_UINT32 ui32Value);
__inline IMG_VOID HeapAddBlockToFreeList(HOST_HEAP *psHostHeap, PGLOB_HEAP psNewBlock);
__inline IMG_VOID HeapRemoveBlockToFreeList(HOST_HEAP *psHostHeap, PGLOB_HEAP psBlock);
IMG_UINT32 CheckHeapFreeBlock(IMG_PVOID pvStart, IMG_UINT32 ui32Size);
IMG_VOID ProcessAllocCallbacks(IMG_BOOL bAlloc, IMG_PVOID pvAddr, IMG_UINT32 ui32Size);
IMG_BOOL AddBlockAllocCallback(PFN_HEAPBLOCK_CALLBACK pfnFunc);
IMG_VOID RemoveBlockAllocCallback(PFN_HEAPBLOCK_CALLBACK pfnFunc);
IMG_VOID DoBlockCallbacksForHeap(PHOST_HEAP psHeap);



/*****************************************************************************
 Global data
*****************************************************************************/
IMG_UINT32	ui32HeapCheckLevel=HOST_HEAP_DBGCHK_NONE;
IMG_UINT32	aui32ValidAlignments[]={1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 0};
PFN_HEAPBLOCK_CALLBACK	sfnBlockAllocCallbacks[MAX_ALLOC_CALLBACKS]={(PFN_HEAPBLOCK_CALLBACK)NULL, (PFN_HEAPBLOCK_CALLBACK)NULL, (PFN_HEAPBLOCK_CALLBACK)NULL, (PFN_HEAPBLOCK_CALLBACK)NULL, (PFN_HEAPBLOCK_CALLBACK)NULL};

typedef struct
{
	DWORD	dwDbgAllocFlags;
	DWORD	dwFailAllocType;
	DWORD	dwHostAllocDbgLevel;
	DWORD	dwFBAllocDbgLevel;
	DWORD	dwFailAllocThreshold;
	DWORD	dwFailAllocRndSeed;
	DWORD	dwFailAllocRndPercent;
	DWORD	dwFailAllocEveryXAllocs;
	DWORD	dwAllocCount;
}DBG_ALLOCS, *PDBG_ALLOCS;

#define FAILALLOC_TYPE_NONE 0
#define FAILALLOC_TYPE_RANDOM 1
#define FAILALLOC_TYPE_EVERYX 2

#define DBGALLOC_INT3ONFAIL 0x1000

DBG_ALLOCS sGlbDbgAllocs;


/*****************************************************************************
 FUNCTION	: InitHeapman
    
 PURPOSE	: initialises the shared system memory heap

 PARAMETERS	:	ppsHeap	- heap structure
					
 RETURNS	: PVRSRV_ERROR
*****************************************************************************/
PVRSRV_ERROR InitHeapman(HOST_HEAP **ppsHeap) 
{
	IMG_UINT32 i;
	HOST_HEAP	*psHeap;
	psHeap = HostPageableByteAlloc(sizeof(HOST_HEAP));
	if (psHeap == NULL)
	{
		return PVRSRV_ERROR_OUT_OF_MEMORY;
	}

	/* we also need to reserve a shared linear address range (>2Mb) */
	psHeap->pvLinearBase = VirtualAlloc(NULL, SYS_MAX_PAGES * HOST_PAGESIZE(), MEM_RESERVE, PAGE_NOACCESS);
	if (psHeap->pvLinearBase == NULL)
	{
		HostPageableByteFree(psHeap);
		return PVRSRV_ERROR_OUT_OF_MEMORY;
	}

	/* setup heap structure */
	psHeap->ui32Flags = HEAP_ALLOC_CANT_SPLIT_PAGE;
	psHeap->ui32AllocsInHeap=0;
	psHeap->psHeapStart=(PGLOB_HEAP)NULL;
	psHeap->psFreeHeapStart=(PGLOB_HEAP)NULL;
	psHeap->ui32MaxHeapSizeInPages=SYS_MAX_PAGES;
	psHeap->ui32CurHeapSizeInPages=0;
	psHeap->ui32ExpandSizeInPages=8;
	psHeap->ui32MaxSingleHeapAllocInBytes=HOST_PAGESIZE();
	psHeap->bAllowLargeSingleAllocs=TRUE;
	psHeap->pfnHostAllocPage = HostNonPageablePageAlloc;
	psHeap->pfnHostFreePage = HostNonPageablePageFree;

	/* allocate a page block state table */
	psHeap->psPageState = HostPageableByteAlloc (psHeap->ui32MaxHeapSizeInPages * sizeof(PAGE_STATE));
	if (psHeap->psPageState == NULL)
	{
		return PVRSRV_ERROR_OUT_OF_MEMORY;
	}

	/* initialise the state block */
	for (i=0; i<psHeap->ui32MaxHeapSizeInPages; i++)
	{
		psHeap->psPageState[i].bPageCommitted = IMG_FALSE;
		psHeap->psPageState[i].pvLinearAddr = (IMG_PVOID)((IMG_UINT32)psHeap->pvLinearBase + (i * HOST_PAGESIZE()));
	}

	/* copy back */
	*ppsHeap = psHeap;

	return PVRSRV_OK;
}


/*****************************************************************************
 FUNCTION	: DeInitHeapman
    
 PURPOSE	: deinitialises the shared system memory heap

 PARAMETERS	:	psHeap	- heap structure
					
 RETURNS	: PVRSRV_ERROR
*****************************************************************************/
PVRSRV_ERROR DeInitHeapman(HOST_HEAP *psHeap) 
{
	HostPageableByteFree (psHeap->psPageState);

	/* we also need to reserve a shared linear address range (>2Mb) */
	if (VirtualFree(psHeap->pvLinearBase, SYS_MAX_PAGES * HOST_PAGESIZE(), MEM_RELEASE) == 0)
	{
		PVR_DPF((PVR_DBG_ERROR,"VirtualFree : failed to free reserved sysmem linear range\n"));
	}

	HostPageableByteFree(psHeap);

	return PVRSRV_OK;
}

#if 0 /*! @todo */
/**************************************************************************
 * Function Name  : ReadDbgAllocSettings
 * Inputs         : None
 * Outputs        : None
 * Returns        : None
 * Globals Used   : sGlbDbgAllocs - we init this structure
 * Description    : Reads info out of the registry and inits the sGlbDbgAllocs structure
 **************************************************************************/
void ReadDbgAllocSettings(DWORD dwDevCookie)
{
	sGlbDbgAllocs.dwAllocCount=0;
	
	/* Read the debug alloc flags */	
	if (HostReadRegistryDWORDFromString(dwDevCookie, "pmxkern", "DbgAllocFlags", &sGlbDbgAllocs.dwDbgAllocFlags) != PVRSRV_OK)
	{
		DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : Debug alloc flags not present assume 0");
		sGlbDbgAllocs.dwDbgAllocFlags=0;
	}
	else
	{
		DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : Debug alloc flags are 0x%lx", sGlbDbgAllocs.dwDbgAllocFlags);
	}

	/* Get fail alloc type */
	sGlbDbgAllocs.dwFailAllocType=sGlbDbgAllocs.dwDbgAllocFlags & DBGALLOC_FAILALLOC_TYPE_MASK;
	switch (sGlbDbgAllocs.dwFailAllocType)
	{
		case FAILALLOC_TYPE_NONE :
			DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : Alloc failing is disabled");
			break;

		case FAILALLOC_TYPE_RANDOM :
			DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : Random alloc failing is enabled");

			/* Get the alloc fail percentage */
			if (HostReadRegistryDWORDFromString(dwDevCookie, "pmxkern", "FAllocRndPercent", &sGlbDbgAllocs.dwFailAllocRndPercent) != PVRSRV_OK)
			{
				DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : No failing percent was specified, using probability of 50 in 10000");	
				sGlbDbgAllocs.dwFailAllocRndPercent=50;
			}
			else
			{
				DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : Will fail allocs using probability of %ld in 1000", sGlbDbgAllocs.dwFailAllocRndPercent);
			}

			/* Check for seed to use */
			if (HostReadRegistryDWORDFromString(dwDevCookie, "pmxkern", "FAllocRndSeed", &sGlbDbgAllocs.dwFailAllocRndSeed) != PVRSRV_OK)
			{
				DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : No random seed given will use RDTSC for seed");				
			}
			else
			{
				DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : Will use ramdom seed of 0x%lx", sGlbDbgAllocs.dwFailAllocRndSeed);
				dwGlbRandomSeed=sGlbDbgAllocs.dwFailAllocRndSeed;
			}			
			/* Force the seed to be used and then store the seed away */
			GetRandNum();
			sGlbDbgAllocs.dwFailAllocRndSeed=dwGlbRandomSeed;
			break;

		case FAILALLOC_TYPE_EVERYX :
			DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : Failing allocs every X allocs is enabled");

			/* Get the failing frequence */
			if (HostReadRegistryDWORDFromString(dwDevCookie, "pmxkern", "FAllocEveryXAllocs", &sGlbDbgAllocs.dwFailAllocEveryXAllocs) != PVRSRV_OK)
			{
				DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : No failing frequence was specified, using 1 in every 1000 allocs");	
				sGlbDbgAllocs.dwFailAllocEveryXAllocs=1000;
			}
			else
			{
				DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : KM will fail 1 in every %ld allocs", sGlbDbgAllocs.dwFailAllocEveryXAllocs);	
			}
			break;

		default :
			DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : Alloc fail type %ld unknown", sGlbDbgAllocs.dwFailAllocType);
			sGlbDbgAllocs.dwFailAllocType=FAILALLOC_TYPE_NONE;
	}
			
	/* Find the alloc threshold */
	if (sGlbDbgAllocs.dwFailAllocType != FAILALLOC_TYPE_NONE)
	{
		if (HostReadRegistryDWORDFromString(dwDevCookie, "pmxkern", "FAllocThreshold", &sGlbDbgAllocs.dwFailAllocThreshold) != PVRSRV_OK)
		{
			DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : No alloc threshold given, use 250");
			sGlbDbgAllocs.dwFailAllocThreshold=250;
		}
		else
		{
			DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : An alloc threshold of %ld was given", sGlbDbgAllocs.dwFailAllocThreshold);
		}
	}

	/* Get host heap alloc debug checking level */
	sGlbDbgAllocs.dwHostAllocDbgLevel=(sGlbDbgAllocs.dwDbgAllocFlags & DBGALLOC_HOST_DBGLEV_MASK) >> DBGALLOC_HOST_DBGLEV_SHIFT;
	dwHeapCheckLevel=sGlbDbgAllocs.dwHostAllocDbgLevel;
	DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : Host heap debug level is %ld", sGlbDbgAllocs.dwHostAllocDbgLevel);

	/* Get FB heap alloc debug checking level */
	sGlbDbgAllocs.dwFBAllocDbgLevel=(sGlbDbgAllocs.dwDbgAllocFlags & DBGALLOC_FB_DBGLEV_MASK) >> DBGALLOC_FB_DBGLEV_SHIFT;
	DPFLX(DBG_ALLOC_CHK, "ReadDbgAllocSettings : FB heap debug level is %ld", sGlbDbgAllocs.dwFBAllocDbgLevel);

	return;
}	

/**************************************************************************
 * Function Name  : FailAlloc
 * Inputs         : None
 * Outputs        : None
 * Returns        : TRUE if we should fail this alloc and FALSE if we should allow it
 * Globals Used   : sGlbDbgAllocs structure
 * Description    : Check to see if we should fail this alloc
 **************************************************************************/
BOOL FailAlloc(void)
{
	BOOL	bFail=FALSE;
	DWORD	dwGlbRandomSeed=0;

	/* Inc alloc count */
	sGlbDbgAllocs.dwAllocCount++;

	/* Check if threshold has been reached */
	if (sGlbDbgAllocs.dwAllocCount > sGlbDbgAllocs.dwFailAllocThreshold)
	{
		/* Check what type of alloc failing we want */
		switch (sGlbDbgAllocs.dwFailAllocType)
		{
			case FAILALLOC_TYPE_NONE :
				break;

			case FAILALLOC_TYPE_RANDOM :
			{
				WORD wRnd=100;
				
				/* Check if we should fail */
				if (wRnd <= sGlbDbgAllocs.dwFailAllocRndPercent)
				{
					bFail=TRUE;
					PVR_DPF((PVR_DBG_MESSAGE, "FailAlloc : Just about to fail this alloc, random seed was 0x%lx, fail rate %ld in 10000", dwGlbRandomSeed, sGlbDbgAllocs.dwFailAllocRndPercent));
				}
				break;
			}

			case FAILALLOC_TYPE_EVERYX :
				if ((sGlbDbgAllocs.dwAllocCount % sGlbDbgAllocs.dwFailAllocEveryXAllocs) == 0)
				{
					bFail=TRUE;
					PVR_DPF((PVR_DBG_MESSAGE, "FailAlloc : Just about to fail this alloc, we fail every %ldth alloc", sGlbDbgAllocs.dwFailAllocEveryXAllocs));
				}
				break;

			default :
			{			
				PVR_DPF((PVR_DBG_MESSAGE, "FailAlloc : should never have an un supported type (%lx)", sGlbDbgAllocs.dwFailAllocType));
				DBG_BREAK;
			}
		}
	}

	if (bFail==TRUE)
	{
		PVR_DPF((PVR_DBG_MESSAGE, "FailAlloc : We are failing this alloc, alloc count is %ld", sGlbDbgAllocs.dwAllocCount));
		if (sGlbDbgAllocs.dwDbgAllocFlags & DBGALLOC_INT3ONFAIL)
		{
			DBG_BREAK;
		}
	}
				
	return bFail;
}
#endif
										
/*!
******************************************************************************

 @Function		HostAllocMem
 
 @Description	Allocates host memory from one of the host heaps
 
 @Input    ui32Flags - flags for allocation, this includes the heap to be 
 						used for this allocation (PVRSRV_HOST_xxx_HEAP)
 @Input    ui32Size - number of bytes to alloc
 @Input    ui32OwnerAddr	- addr of caller
 @Output    ppvLinAddr - pointer to variable that receives the linear 
 						address of allocated memory

 @Return   PVRSRV_OK on success else PVRSRV_ERROR_OUT_OF_MEMORY 

******************************************************************************/ 
PVRSRV_ERROR HostAllocMem(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvLinAddr, IMG_UINT32 ui32OwnerAddr)
{
	IMG_PVOID				pvLinAddr=NULL;
	IMG_UINT32				ui32HeapIndex=ui32Flags & PVRSRV_HOST_HEAP_MASK;
	SYS_DATA				*psSysData;
	PVRSRV_ERROR			eRetCode=PVRSRV_OK;
	IMG_BOOL				bAllocDone=FALSE;
	ENV_DATA				*psEnvData;

	if (SysAcquireData(&psSysData) != PVRSRV_OK)
	{
		return 0;
	}
	
	psEnvData = (ENV_DATA*)psSysData->pvEnvSpecificData;

	#if 0 /*! @todo implement on DEBUG */
	/* Check we should fail this alloc */
	if (FailAlloc() == TRUE)
	{
		PVR_DPF((PVR_DBG_ERROR, "MemHeapAlloc : We have been asked to fail this alloc"));		
		return (PVRSRV_ERROR_OUT_OF_MEMORY);
	}
	#endif

	#if 0 /*! @todo implement on DEBUG && !defined(NO_ALLOC_TRACKING)*/
	/* Get calls return addr if not already given */
	if (ui32OwnerAddr == 0)
	{
		GetReturnAddress(ui32OwnerAddr);
	}
	#endif /* #if defined(DEBUG) && !defined(NO_ALLOC_TRACKING) */

	PVR_DPF((PVR_DBG_MESSAGE, "HostAllocMem() size %lu (%lu Kb), flags 0x%lx, caller 0x%lx", ui32Size, ui32Size/1024, ui32Flags, ui32OwnerAddr));

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

	/*Set lin addr to NULL*/
	*ppvLinAddr=NULL;

⌨️ 快捷键说明

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