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

📄 ra.c

📁 Lido PXA270平台开发板的最新BSP,包括源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	            
	RETURNS:	span marker boundary tag
	
</function>
-----------------------------------------------------------------------------*/
static BT *
_BuildSpanMarker (RA_ARENA *pArena, IMG_UINTPTR_T base)
{
	BT *pBT;
	PVR_ASSERT (pArena != IMG_NULL);
	PVR_ASSERT (pArena->pState != IMG_NULL);
	
	pBT = POOL_Alloc (pArena->pState->pBTPool);
	if (pBT != IMG_NULL)
    {
		pBT->type = btt_span;
		pBT->base = base;
    };
	return pBT;
}

/*----------------------------------------------------------------------------
<function>
	FUNCTION:   _BuildBT

	PURPOSE:    Construct a boundary tag for a free segment.
	
	PARAMETERS:	In: pArena -
	            In:  base - the base of the resource segment.
	            In:  uSize - the extent of the resouce segment.
	            
	RETURNS:	boundary tag
	
</function>
-----------------------------------------------------------------------------*/
static BT *
_BuildBT (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
{
	BT *pBT;

	PVR_ASSERT (pArena!=IMG_NULL);
	PVR_ASSERT (pArena->pState!=IMG_NULL);

	pBT = POOL_Alloc (pArena->pState->pBTPool);
	if (pBT!=IMG_NULL)
    {
		pBT->type = btt_free;
		pBT->base = base;
		pBT->uSize = uSize;
    }
	return pBT;
}

/*----------------------------------------------------------------------------
<function>
	FUNCTION:   _InsertResource

	PURPOSE:    Add a free resource segment to an arena.
	
	PARAMETERS:	In:  pArena - the arena.
	            In:  base - the base of the resource segment.
	            In:  uSize - the extent of the resource segment.
	RETURNS:	IMG_FALSE failed
	            IMG_TRUE success
	
</function>
-----------------------------------------------------------------------------*/
static IMG_BOOL
_InsertResource (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
{
	BT *pBT;
	PVR_ASSERT (pArena!=IMG_NULL);
	pBT = _BuildBT (pArena, base, uSize);
	if (pBT == IMG_NULL)
		return IMG_FALSE;
	_SegmentListInsert (pArena, pBT);
	_FreeListInsert (pArena, pBT);
#ifdef RA_STATS
	pArena->sStatistics.uTotalResourceCount+=uSize;
	pArena->sStatistics.uFreeResourceCount+=uSize;
	pArena->sStatistics.uSpanCount++;
#endif
	return IMG_TRUE;
}
	  
/*----------------------------------------------------------------------------
<function>
	FUNCTION:   _InsertResourceSpan

	PURPOSE:    Add a free resource span to an arena, complete with span markers.
	
	PARAMETERS:	In:  pArena - the arena.
	            In:  base - the base of the resource segment.
	            In:  uSize - the extent of the resource segment.
	RETURNS:	the boundary tag representing the free resource segment,
	            or IMG_NULL on failure.
</function>
-----------------------------------------------------------------------------*/
static BT *
_InsertResourceSpan (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
{
	BT *pSpanStart;
	BT *pSpanEnd;
	BT *pBT;

	PVR_ASSERT (pArena != IMG_NULL);
	PVR_ASSERT (pArena->pState != IMG_NULL);
	
    PVR_DPF ((PVR_DBG_MESSAGE,
              "ra:_InsertResourceSpan (arena='%s', base=0x%x, size=0x%x)",
              pArena->name, base, uSize));
	
	pSpanStart = _BuildSpanMarker (pArena, base);
	if (pSpanStart == IMG_NULL) goto fail_start;

	pSpanEnd = _BuildSpanMarker (pArena, base + uSize);
	if (pSpanEnd == IMG_NULL) goto fail_end;

	pBT = _BuildBT (pArena, base, uSize);
	if (pBT == IMG_NULL) goto fail_bt;
	  
	_SegmentListInsert (pArena, pSpanStart);
	_SegmentListInsertAfter (pArena, pSpanStart, pBT);
	_FreeListInsert (pArena, pBT);
	_SegmentListInsertAfter (pArena, pBT, pSpanEnd);
#ifdef RA_STATS
	pArena->sStatistics.uTotalResourceCount+=uSize;
/*	pArena->sStatistics.uFreeResourceCount+=uSize; 
	This has got to be wrong as uFreeResourceCount ends 
	up larger than uTotalResourceCount by uTotalResourceCount
	- allocated memory
*/
#endif
	return pBT;

  fail_bt:
	POOL_Free (pArena->pState->pBTPool, pSpanEnd);
  fail_end:
	POOL_Free (pArena->pState->pBTPool, pSpanStart);
  fail_start:
	return IMG_NULL;
}

/*----------------------------------------------------------------------------
<function>
	FUNCTION:   _FreeBT

	PURPOSE:    Free a boundary tag taking care of the segment list and the
	            boundary tag free table. 
	
	PARAMETERS:	In:  pArena - the arena.
	            In:  pBT - the boundary tag to free.
	RETURNS:	None
</function>
------------------------------------------------------------------------------*/
static void
_FreeBT (RA_ARENA *pArena, BT *pBT)
{
	BT *pNeighbour;

	PVR_ASSERT (pArena!=IMG_NULL);
	PVR_ASSERT (pArena->pState!=IMG_NULL);
	PVR_ASSERT (pBT!=IMG_NULL);
	
#ifdef RA_STATS
	pArena->sStatistics.uLiveSegmentCount--;
	pArena->sStatistics.uFreeSegmentCount++;
	pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
#endif

	/* try and coalesce with left neighbour */
	pNeighbour = pBT->pPrevSegment;
	if (pNeighbour!=IMG_NULL
		&& pNeighbour->type == btt_free
		&& pNeighbour->base + pNeighbour->uSize == pBT->base)
    {
		_FreeListRemove (pArena, pNeighbour);
		_SegmentListRemove (pArena, pNeighbour);
		pBT->base = pNeighbour->base;
		pBT->uSize += pNeighbour->uSize;
		POOL_Free (pArena->pState->pBTPool, pNeighbour);
#ifdef RA_STATS
		pArena->sStatistics.uFreeSegmentCount--;
#endif
    }

	/* try to coalesce with right neighbour */
	pNeighbour = pBT->pNextSegment;
	if (pNeighbour!=IMG_NULL
		&& pNeighbour->type == btt_free
		&& pBT->base + pBT->uSize == pNeighbour->base)
    {
		_FreeListRemove (pArena, pNeighbour);
		_SegmentListRemove (pArena, pNeighbour);
		pBT->uSize += pNeighbour->uSize;
		POOL_Free (pArena->pState->pBTPool, pNeighbour);
#ifdef RA_STATS
		pArena->sStatistics.uFreeSegmentCount--;
#endif
    }

	if (pBT->pNextSegment!=IMG_NULL && pBT->pNextSegment->type == btt_span
		&& pBT->pPrevSegment!=IMG_NULL && pBT->pPrevSegment->type == btt_span)
    {
		BT *next = pBT->pNextSegment;
		BT *prev = pBT->pPrevSegment;
		_SegmentListRemove (pArena, next);
		_SegmentListRemove (pArena, prev);
		_SegmentListRemove (pArena, pBT);
		pArena->pImportFree (pArena->pImportHandle, pBT->base, pBT->pRef);
#ifdef RA_STATS
		pArena->sStatistics.uSpanCount--;
		pArena->sStatistics.uExportCount++;
		pArena->sStatistics.uFreeSegmentCount--;
		pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
		pArena->sStatistics.uTotalResourceCount-=pBT->uSize;
#endif
		POOL_Free (pArena->pState->pBTPool, next);
		POOL_Free (pArena->pState->pBTPool, prev);
		POOL_Free (pArena->pState->pBTPool, pBT);
    } 
	else
		_FreeListInsert (pArena, pBT);
}


/*----------------------------------------------------------------------------
<function>
	FUNCTION:   _AttemptAllocAligned

	PURPOSE:    Attempt an allocation from an arena.
	
	PARAMETERS:	In:  pArena - the arena.
	            In:  uSize - the requested allocation size.
	            Out: pRef - the user references associated with the allocated
	                 segment.
	            In:  flags - allocation flags
	            In:  uAlignment - required uAlignment, or 0
	            In:  uAlignmentOffset
	            Out: base - allocated resource base
	RETURNS:	IMG_FALSE failure
	            IMG_TRUE success
</function>
-----------------------------------------------------------------------------*/
static IMG_BOOL
_AttemptAllocAligned (RA_ARENA *pArena,
                      IMG_SIZE_T uSize,
                      void **pRef,
                      IMG_UINT32 uFlags,
                      IMG_UINT32 uAlignment,
                      IMG_UINT32 uAlignmentOffset,
                      IMG_UINTPTR_T *base)
{
	IMG_UINT32 uIndex;
	PVR_ASSERT (pArena!=IMG_NULL);

	UNREFERENCED_PARAMETER (uFlags);

    if (uAlignment>1)
        uAlignmentOffset %= uAlignment;
    
	/* search for a near fit free boundary tag, start looking at the
	   log2 free table for our required size and work on up the
	   table. */
	uIndex = log2 (uSize);

#if 0
	/* If the size required is exactly 2**n then use the n bucket, because
	   we know that every free block in that bucket is larger than 2**n,
	   otherwise start at then next bucket up. */
	if (1u<<uIndex < uSize)
		uIndex++;
#endif
	
	while (uIndex < FREE_TABLE_LIMIT && pArena->aHeadFree[uIndex]==IMG_NULL)
		uIndex++;

	while (uIndex < FREE_TABLE_LIMIT)
	{
		if (pArena->aHeadFree[uIndex]!=IMG_NULL)
		{
			/* we have a cached free boundary tag */
			BT *pBT;

			pBT = pArena->aHeadFree [uIndex];
			while (pBT!=IMG_NULL)
			{
				IMG_UINTPTR_T aligned_base;

				if (uAlignment>1)
					aligned_base = (pBT->base + uAlignmentOffset + uAlignment - 1) / uAlignment * uAlignment - uAlignmentOffset;
				else
					aligned_base = pBT->base;
				PVR_DPF ((PVR_DBG_MESSAGE,
                          "..ra:_AttemptAllocAligned () pBT-base=0x%x "
                          "pBT-size=0x%x alignedbase=0x%x size=0x%x",
						pBT->base, pBT->uSize, aligned_base, uSize));
			
				if (pBT->base + pBT->uSize >= aligned_base + uSize)
				{
					_FreeListRemove (pArena, pBT);
			
					PVR_ASSERT (pBT->type == btt_free);

#ifdef RA_STATS
					pArena->sStatistics.uLiveSegmentCount++;
					pArena->sStatistics.uFreeSegmentCount--;
					pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
#endif

					/* with uAlignment we might need to discard the front of this segment */
					if (aligned_base > pBT->base)
					{
						BT *pNeighbour;
						
						pNeighbour = _SegmentSplit (pArena, pBT, aligned_base-pBT->base);
						/* partition the buffer, create a new boundary tag */
						if (pNeighbour==IMG_NULL)
							return IMG_FALSE;
							
						_FreeListInsert (pArena, pBT);
#ifdef RA_STATS
						pArena->sStatistics.uFreeSegmentCount++;
						pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
#endif
						pBT = pNeighbour;
					}

					/* the segment might be too big, if so, discard the back of the segment */
					if (pBT->uSize > uSize)
					{
						BT *pNeighbour;
						pNeighbour = _SegmentSplit (pArena, pBT, uSize);
						/* partition the buffer, create a new boundary tag */
						if (pNeighbour==IMG_NULL)
							return IMG_FALSE;
							
						_FreeListInsert (pArena, pNeighbour);
#ifdef RA_STATS
						pArena->sStatistics.uFreeSegmentCount++;
						pArena->sStatistics.uFreeResourceCount+=pNeighbour->uSize;
#endif
					}

					pBT->type = btt_live;

					if (!HASH_Insert (pArena->pSegmentHash, pBT->base, (IMG_UINTPTR_T) pBT))
					{
						_FreeBT (pArena, pBT);
						return IMG_FALSE;
					}

					if (pRef!=IMG_NULL)
						*pRef = pBT->pRef;

					*base = pBT->base;
					
					return IMG_TRUE;
				}
				pBT = pBT->pNextFree;
			}
			
		}
		uIndex++;
	}
	
	return IMG_FALSE;
}

/*----------------------------------------------------------------------------
<function>
	FUNCTION:   RA_Initialise

	PURPOSE:    To initialise the ra module. Must be called before any
 	            other ra API function.
	
	PARAMETERS:	In:  pHashState - HASH state pointer (from HASH_Initialise)
	            Out: ppState - Receives the ra state pointer.
	
	RETURNS:	IMG_FALSE - Failure
	            IMG_TRUE - Success
</function>
-----------------------------------------------------------------------------*/
IMG_BOOL
RA_Initialise (HASH_STATE *pHashState, RA_STATE **ppState)
{
	RA_STATE *pState;

    PVR_DPF ((PVR_DBG_MESSAGE, "RA_Initialise()"));

	PVR_ASSERT (pHashState!=IMG_NULL);
	PVR_ASSERT (ppState!=IMG_NULL);
	HostAllocMem (PVRSRV_HOST_PAGEABLE_HEAP, 
                  sizeof (*pState), 
                  (IMG_VOID **)&pState, 0);	
	if (pState == IMG_NULL) goto fail_alloc;
	pState->pHashState = pHashState;
	pState->pArenaPool = POOL_Create ("img-arena", sizeof (RA_ARENA));
	if (pState->pArenaPool == IMG_NULL) goto fail_arena;
	pState->pBTPool = POOL_Create ("img-bt", sizeof (BT));
	if (pState->pBTPool == IMG_NULL) goto fail_bt;
	*ppState = pState;
	return IMG_TRUE;
  fail_bt:
	POOL_Delete (pState->pArenaPool);
  fail_arena:
	HostPageableByteFree (pState);
  fail_alloc:
	return IMG_FALSE;
}

/*----------------------------------------------------------------------------
<function>
	FUNCTION:   RA_Finalise

	PURPOSE:    To finalise the ra module.
	
	PARAMETERS:	pState - pointer to ra state
	
	RETURNS:	None
</function>
-----------------------------------------------------------------------------*/
void
RA_Finalise (RA_STATE *pState)
{

⌨️ 快捷键说明

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