📄 ra.c
字号:
PVR_DPF ((PVR_DBG_MESSAGE, "RA_Finalise()"));
PVR_ASSERT (pState!=IMG_NULL);
if (pState != IMG_NULL)
{
if (pState->pArenaPool!=IMG_NULL)
POOL_Delete (pState->pArenaPool);
if (pState->pBTPool!=IMG_NULL)
POOL_Delete (pState->pBTPool);
HostFreeMem (PVRSRV_HOST_PAGEABLE_HEAP, pState);
}
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: RA_Create
PURPOSE: To create a resource arena.
PARAMETERS: In: pState - pointer to ra state created by RA_Initialise
In: name - the name of the arena for diagnostic purposes.
In: base - the base of an initial resource span or 0.
In: uSize - the size of an initial resource span or 0.
In: uQuantum - the arena allocation quantum.
In: alloc - a resource allocation callback or 0.
In: free - a resource de-allocation callback or 0.
In: pImportHandle - handle passed to alloc and free or 0.
RETURNS: arena handle, or IMG_NULL.
</function>
-----------------------------------------------------------------------------*/
RA_ARENA *
RA_Create (RA_STATE *pState,
IMG_CHAR *name,
IMG_UINTPTR_T base,
IMG_SIZE_T uSize,
IMG_SIZE_T uQuantum,
IMG_BOOL (*alloc)(IMG_VOID *, IMG_SIZE_T uSize, IMG_SIZE_T *pActualSize,
IMG_VOID **pRef, IMG_UINT32 _flags, IMG_UINTPTR_T *pBase),
IMG_VOID (*free) (IMG_VOID *, IMG_UINTPTR_T, IMG_VOID *pRef),
IMG_VOID *pImportHandle)
{
RA_ARENA *pArena;
int i;
PVR_DPF ((PVR_DBG_MESSAGE,
"RA_Create(name=%s, base=%x, uSize=%x, alloc=0x%x, free=0x%x)",
name, base, uSize, alloc, free));
PVR_ASSERT (pState!=IMG_NULL);
pArena = POOL_Alloc (pState->pArenaPool);
if (pArena==IMG_NULL) goto arena_fail;
pArena->name = name;
pArena->pImportAlloc = alloc!=IMG_NULL ? alloc : _RequestAllocFail;
pArena->pImportFree = free;
pArena->pImportHandle = pImportHandle;
for (i=0; i<FREE_TABLE_LIMIT; i++)
pArena->aHeadFree[i] = IMG_NULL;
pArena->pHeadSegment = IMG_NULL;
pArena->pTailSegment = IMG_NULL;
pArena->uQuantum = uQuantum;
pArena->pState = pState;
#ifdef RA_STATS
pArena->sStatistics.uSpanCount = 0;
pArena->sStatistics.uLiveSegmentCount = 0;
pArena->sStatistics.uFreeSegmentCount = 0;
pArena->sStatistics.uFreeResourceCount = 0;
pArena->sStatistics.uTotalResourceCount = 0;
pArena->sStatistics.uCumulativeAllocs = 0;
pArena->sStatistics.uCumulativeFrees = 0;
pArena->sStatistics.uImportCount = 0;
pArena->sStatistics.uExportCount = 0;
#endif
pArena->pSegmentHash = HASH_Create (pState->pHashState, MINIMUM_HASH_SIZE);
if (pArena->pSegmentHash==IMG_NULL) goto hash_fail;
if (uSize>0)
{
uSize = (uSize + uQuantum - 1) / uQuantum * uQuantum;
if (!_InsertResource (pArena, base, uSize)) goto insert_fail;
}
return pArena;
insert_fail:
HASH_Delete (pArena->pSegmentHash);
hash_fail:
POOL_Free (pState->pArenaPool, pArena);
arena_fail:
return IMG_NULL;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: RA_Delete
PURPOSE: To delete a resource arena. All resources allocated from
the arena must be freed before deleting the arena.
PARAMETERS: In: pArena - the arena to delete.
RETURNS: None
</function>
-----------------------------------------------------------------------------*/
void
RA_Delete (RA_ARENA *pArena)
{
if (pArena!=IMG_NULL)
{
IMG_UINT32 uIndex;
PVR_DPF ((PVR_DBG_MESSAGE,
"RA_Delete: name=%s", pArena->name));
PVR_ASSERT (pArena->pState!=IMG_NULL);
for (uIndex=0; uIndex<FREE_TABLE_LIMIT; uIndex++)
pArena->aHeadFree[uIndex] = IMG_NULL;
while (pArena->pHeadSegment != IMG_NULL)
{
BT *pBT = pArena->pHeadSegment;
PVR_ASSERT (pBT->type == btt_free);
_SegmentListRemove (pArena, pBT);
POOL_Free (pArena->pState->pBTPool, pBT);
#ifdef RA_STATS
pArena->sStatistics.uSpanCount--;
#endif
}
HASH_Delete (pArena->pSegmentHash);
POOL_Free (pArena->pState->pArenaPool, pArena);
}
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: RA_Add
PURPOSE: To add a resource span to an arena. The span must not
overlapp with any span previously added to the arena.
PARAMETERS: In: pArena - the arena to add a span into.
In: base - the base of the span.
In: uSize - the extent of the span.
RETURNS: IMG_TRUE - Success
IMG_FALSE - failure
</function>
-----------------------------------------------------------------------------*/
IMG_BOOL
RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
{
PVR_ASSERT (pArena != IMG_NULL);
PVR_DPF ((PVR_DBG_MESSAGE,
"RA_Add: name=%s, base=%x, size=%x", pArena->name, base, uSize));
uSize = (uSize + pArena->uQuantum - 1) / pArena->uQuantum * pArena->uQuantum;
return _InsertResource (pArena, base, uSize);
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: RA_Alloc
PURPOSE: To allocate resource from an arena.
PARAMETERS: In: pArena - the arena
In: uRequestSize - the size of resource segment requested.
Out: pActualSize - the actual size of resource segment
allocated, typcially rounded up by quantum.
Out: pRef - the user reference associated with allocated resource span.
In: uFlags - flags influencing allocation policy.
In: uAlignment - the uAlignment constraint required for the
allocated segment, use 0 if uAlignment not required.
In: uAlignmentOffset
Out: base - allocated base resource
RETURNS: IMG_TRUE - success
IMG_FALSE - failure
</function>
-----------------------------------------------------------------------------*/
IMG_BOOL
RA_Alloc (RA_ARENA *pArena,
IMG_SIZE_T uRequestSize,
IMG_SIZE_T *pActualSize,
void **pRef,
IMG_UINT32 uFlags,
IMG_UINT32 uAlignment,
IMG_UINT32 uAlignmentOffset,
IMG_UINTPTR_T *base)
{
IMG_BOOL bResult = IMG_FALSE;
IMG_SIZE_T uSize = uRequestSize;
PVR_ASSERT (pArena!=IMG_NULL);
uSize = ((uSize + pArena->uQuantum - 1)/pArena->uQuantum)*pArena->uQuantum;
if (pActualSize != IMG_NULL)
*pActualSize = uSize;
PVR_DPF ((PVR_DBG_MESSAGE,
"RA_Alloc (arena='%s', size=0x%lx(0x%lx), uAlignment=0x%x, uAlignmentOffset=0x%x)...",
pArena->name, uSize, uRequestSize, uAlignment, uAlignmentOffset));
/* if allocation failed then we might have an import source which
can provide more resource, else we will have to fail the
allocation to the caller. */
bResult = _AttemptAllocAligned (pArena, uSize, pRef, uFlags,
uAlignment, uAlignmentOffset, base);
if (!bResult)
{
void *pImportRef;
IMG_UINTPTR_T import_base;
IMG_SIZE_T uImportSize = uSize;
/* ensure that we allocate sufficient space to meet the uAlignment
constraint */
if (uAlignment>0)
uImportSize += uAlignment;
bResult =
pArena->pImportAlloc (pArena->pImportHandle, uImportSize, &uImportSize,
&pImportRef, uFlags, &import_base);
if (bResult)
{
BT *pBT;
pBT = _InsertResourceSpan (pArena, import_base, uImportSize);
/* successfully import more resource, create a span to
represent it and retry the allocation attempt */
if (pBT == IMG_NULL)
{
/* insufficient resources to insert the newly acquired span,
so free it back again */
pArena->pImportFree (pArena->pImportHandle, import_base,
pImportRef);
PVR_DPF ((PVR_DBG_MESSAGE,
"...RA_Alloc (name='%s', size=0x%x) failed",
pArena->name, uSize));
/* RA_Dump (arena); */
return IMG_FALSE;
}
pBT->pRef = pImportRef;
#ifdef RA_STATS
pArena->sStatistics.uFreeSegmentCount++;
pArena->sStatistics.uFreeResourceCount += uImportSize;
pArena->sStatistics.uImportCount++;
pArena->sStatistics.uSpanCount++;
#endif
bResult = _AttemptAllocAligned (pArena, uSize, pRef, uFlags,
uAlignment, uAlignmentOffset,
base);
if (!bResult)
{
PVR_DPF ((PVR_DBG_MESSAGE,
"...RA_Alloc(name='%s') failed (uAlignment)",
pArena->name));
}
}
}
#ifdef RA_STATS
if (bResult)
pArena->sStatistics.uCumulativeAllocs++;
#endif
PVR_DPF ((PVR_DBG_MESSAGE,
" RA_Alloc (name=%s, size=0x%lx, *base=0x%lx) = %d",
pArena->name, uSize, *base, bResult));
/* RA_Dump (pArena);
ra_stats (pArena);
*/
return bResult;
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: RA_Free
PURPOSE: To free a resource segment.
PARAMETERS: In: pArena - the arena the segment was originally allocated from.
In: base - the base of the resource span to free.
In: pRef - TODO check why we still need this.
RETURNS: None
</function>
-----------------------------------------------------------------------------*/
void
RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, void *pRef)
{
BT *pBT;
PVR_ASSERT (pArena != IMG_NULL);
UNREFERENCED_PARAMETER (pRef);
PVR_DPF ((PVR_DBG_MESSAGE,
"RA_Free: name=%s base=0x%lx", pArena->name, base));
pBT = (BT *) HASH_Remove (pArena->pSegmentHash, base);
PVR_ASSERT (pBT != IMG_NULL);
if (pBT)
{
PVR_ASSERT (pBT->base == base);
#ifdef RA_STATS
pArena->sStatistics.uCumulativeFrees++;
#endif
_FreeBT (pArena, pBT);
}
}
#ifdef RA_STATS
/*----------------------------------------------------------------------------
<function>
FUNCTION: RA_Statistics
PURPOSE: To query an arena's statistics.
PARAMETERS: In: pArena - the arena.
Out: ppStats - receives a pointer to the arena statistics.
RETURNS: None
</function>
-----------------------------------------------------------------------------*/
void
RA_Statistics (RA_ARENA *pArena, RA_STATISTICS **ppStats)
{
PVR_ASSERT (pArena != IMG_NULL);
PVR_ASSERT (ppStats != IMG_NULL);
*ppStats = &(pArena->sStatistics);
}
#endif
#ifdef NEVER
static char *
_BTType (enum _BTType eType)
{
switch (eType)
{
case btt_span: return "span";
case btt_free: return "free";
case btt_live: return "live";
}
return "junk";
}
/*----------------------------------------------------------------------------
<function>
FUNCTION: RA_Dump
PURPOSE: To dump a readable description of an arena. Diagnostic only.
PARAMETERS: In: pArena - the arena to dump.
RETURNS: None
</function>
-----------------------------------------------------------------------------*/
void
RA_Dump (RA_ARENA *pArena)
{
BT *pBT;
PVR_ASSERT (pArena != IMG_NULL);
PVR_DPF ((PVR_DBG_MESSAGE,"Arena %s", pArena->name));
PVR_DPF ((PVR_DBG_MESSAGE," alloc=%p free=%p handle=%p quantum=%d",
pArena->pImportAlloc, pArena->pImportFree, pArena->pImportHandle,
pArena->uQuantum));
PVR_DPF ((PVR_DBG_MESSAGE," segment Chain:"));
if (pArena->pHeadSegment != IMG_NULL &&
pArena->pHeadSegment->pPrevSegment != IMG_NULL)
PVR_DPF ((PVR_DBG_MESSAGE," error: head boundary tag has invalid pPrevSegment"));
if (pArena->pTailSegment != IMG_NULL &&
pArena->pTailSegment->pNextSegment != IMG_NULL)
PVR_DPF ((PVR_DBG_MESSAGE," error: tail boundary tag has invalid pNextSegment"));
for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
{
PVR_DPF ((PVR_DBG_MESSAGE,"\tbase=0x%lx size=%ld type=%s ref=%p",
(unsigned long) pBT->base, pBT->uSize, _BTType (pBT->type),
pBT->pRef));
}
#ifdef HASH_TRACE
HASH_Dump (pArena->pSegmentHash);
#endif
}
#endif
#if NEVER
/*----------------------------------------------------------------------------
<function>
FUNCTION: RA_Stats
PURPOSE: To dump the statistics associated with an arena.
PARAMETERS: In: pArena - the arena to print statistics for.
RETURNS: None
</function>
-----------------------------------------------------------------------------*/
void
RA_Stats (RA_ARENA *pArena)
{
PVR_ASSERT (pArena!=IMG_NULL);
PVR_DPF ((PVR_DBG_MESSAGE,"Arena %s",
pArena->name));
PVR_DPF ((PVR_DBG_MESSAGE,"\tspan count = %d",
pArena->sStatistics.uSpanCount));
PVR_DPF ((PVR_DBG_MESSAGE,"\tlive segment count = %d",
pArena->sStatistics.uLiveSegmentCount));
PVR_DPF ((PVR_DBG_MESSAGE,"\tfree segment count = %d",
pArena->sStatistics.uFreeSegmentCount));
PVR_DPF ((PVR_DBG_MESSAGE,"\tfree resource count = %d",
pArena->sStatistics.uFreeResourceCount));
PVR_DPF ((PVR_DBG_MESSAGE,"\ttotal allocs = %d",
pArena->sStatistics.uCumulativeAllocs));
PVR_DPF ((PVR_DBG_MESSAGE,"\ttotal frees = %d",
pArena->sStatistics.uCumulativeFrees));
PVR_DPF ((PVR_DBG_MESSAGE,"\timport count = %d",
pArena->sStatistics.uImportCount));
PVR_DPF ((PVR_DBG_MESSAGE,"\texport count = %d",
pArena->sStatistics.uExportCount));
PVR_DPF ((PVR_DBG_MESSAGE,""));
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -