static void _FreeBT(struct RA_ARENA *pArena, struct BT *pBT, IMG_BOOL bFreeBackingStore) { struct BT *pNeighbour; u32 uOrigBase; size_t uOrigSize; PVR_ASSERT(pArena != NULL); PVR_ASSERT(pBT != NULL); if ((pArena == NULL) || (pBT == NULL)) { PVR_DPF(PVR_DBG_ERROR, "_FreeBT: invalid parameter"); return; } #ifdef RA_STATS pArena->sStatistics.uLiveSegmentCount--; pArena->sStatistics.uFreeSegmentCount++; pArena->sStatistics.uFreeResourceCount += pBT->uSize; #endif uOrigBase = pBT->base; uOrigSize = pBT->uSize; pNeighbour = pBT->pPrevSegment; if (pNeighbour != 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; OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), pNeighbour, NULL); #ifdef RA_STATS pArena->sStatistics.uFreeSegmentCount--; #endif } pNeighbour = pBT->pNextSegment; if (pNeighbour != NULL && pNeighbour->type == btt_free && pBT->base + pBT->uSize == pNeighbour->base) { _FreeListRemove(pArena, pNeighbour); _SegmentListRemove(pArena, pNeighbour); pBT->uSize += pNeighbour->uSize; OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), pNeighbour, NULL); #ifdef RA_STATS pArena->sStatistics.uFreeSegmentCount--; #endif } if (pArena->pBackingStoreFree != NULL && bFreeBackingStore) { u32 uRoundedStart, uRoundedEnd; uRoundedStart = (uOrigBase / pArena->uQuantum) * pArena->uQuantum; if (uRoundedStart < pBT->base) uRoundedStart += pArena->uQuantum; uRoundedEnd = ((uOrigBase + uOrigSize + pArena->uQuantum - 1) / pArena->uQuantum) * pArena->uQuantum; if (uRoundedEnd > (pBT->base + pBT->uSize)) uRoundedEnd -= pArena->uQuantum; if (uRoundedStart < uRoundedEnd) pArena->pBackingStoreFree(pArena->pImportHandle, uRoundedStart, uRoundedEnd, (void *) 0); } if (pBT->pNextSegment != NULL && pBT->pNextSegment->type == btt_span && pBT->pPrevSegment != NULL && pBT->pPrevSegment->type == btt_span) { struct BT *next = pBT->pNextSegment; struct BT *prev = pBT->pPrevSegment; _SegmentListRemove(pArena, next); _SegmentListRemove(pArena, prev); _SegmentListRemove(pArena, pBT); pArena->pImportFree(pArena->pImportHandle, pBT->base, pBT->psMapping); #ifdef RA_STATS pArena->sStatistics.uSpanCount--; pArena->sStatistics.uExportCount++; pArena->sStatistics.uFreeSegmentCount--; pArena->sStatistics.uFreeResourceCount -= pBT->uSize; pArena->sStatistics.uTotalResourceCount -= pBT->uSize; #endif OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), next, NULL); OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), prev, NULL); OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(struct BT), pBT, NULL); } else _FreeListInsert(pArena, pBT); }
static int alloc_from_bt(struct RA_ARENA *arena, struct BT *bt, u32 start, size_t size, u32 align, struct BM_MAPPING **new_mapping, u32 *new_base) { _FreeListRemove(arena, bt); PVR_ASSERT(bt->type == btt_free); #ifdef RA_STATS arena->sStatistics.uLiveSegmentCount++; arena->sStatistics.uFreeSegmentCount--; arena->sStatistics.uFreeResourceCount -= bt->uSize; #endif if (start > bt->base) { struct BT *next_bt; next_bt = _SegmentSplit(arena, bt, start - bt->base); if (!next_bt) { PVR_DPF(PVR_DBG_ERROR, "_AttemptAllocAligned: " "Front split failed"); _FreeListInsert(arena, bt); return -1; } _FreeListInsert(arena, bt); #ifdef RA_STATS arena->sStatistics.uFreeSegmentCount++; arena->sStatistics.uFreeResourceCount += bt->uSize; #endif bt = next_bt; } if (bt->uSize > size) { struct BT *next_bt; next_bt = _SegmentSplit(arena, bt, size); if (!next_bt) { PVR_DPF(PVR_DBG_ERROR, "_AttemptAllocAligned: " "Back split failed"); _FreeListInsert(arena, bt); return -1; } _FreeListInsert(arena, next_bt); #ifdef RA_STATS arena->sStatistics.uFreeSegmentCount++; arena->sStatistics.uFreeResourceCount += next_bt->uSize; #endif } bt->type = btt_live; if (!HASH_Insert(arena->pSegmentHash, bt->base, (u32)bt)) { _FreeBT(arena, bt, IMG_FALSE); return -1; } if (new_mapping) *new_mapping = bt->psMapping; *new_base = bt->base; return 0; }
static IMG_BOOL _AttemptAllocAligned (RA_ARENA *pArena, IMG_SIZE_T uSize, BM_MAPPING **ppsMapping, IMG_UINT32 uFlags, IMG_UINT32 uAlignment, IMG_UINT32 uAlignmentOffset, IMG_UINTPTR_T *base) { IMG_UINT32 uIndex; PVR_ASSERT (pArena!=IMG_NULL); if (pArena == IMG_NULL) { PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: invalid parameter - pArena")); return IMG_FALSE; } if (uAlignment>1) uAlignmentOffset %= uAlignment; uIndex = pvr_log2 (uSize); #if 0 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) { 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) { if(!pBT->psMapping || pBT->psMapping->ui32Flags == uFlags) { _FreeListRemove (pArena, pBT); PVR_ASSERT (pBT->type == btt_free); #ifdef RA_STATS pArena->sStatistics.uLiveSegmentCount++; pArena->sStatistics.uFreeSegmentCount--; pArena->sStatistics.uFreeResourceCount-=pBT->uSize; #endif if (aligned_base > pBT->base) { BT *pNeighbour; pNeighbour = _SegmentSplit (pArena, pBT, (IMG_SIZE_T)(aligned_base - pBT->base)); if (pNeighbour==IMG_NULL) { PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Front split failed")); _FreeListInsert (pArena, pBT); return IMG_FALSE; } _FreeListInsert (pArena, pBT); #ifdef RA_STATS pArena->sStatistics.uFreeSegmentCount++; pArena->sStatistics.uFreeResourceCount+=pBT->uSize; #endif pBT = pNeighbour; } if (pBT->uSize > uSize) { BT *pNeighbour; pNeighbour = _SegmentSplit (pArena, pBT, uSize); if (pNeighbour==IMG_NULL) { PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Back split failed")); _FreeListInsert (pArena, pBT); return IMG_FALSE; } _FreeListInsert (pArena, pNeighbour); #ifdef RA_STATS pArena->sStatistics.uFreeSegmentCount++; pArena->sStatistics.uFreeResourceCount+=pNeighbour->uSize; #endif } pBT->type = btt_live; #if defined(VALIDATE_ARENA_TEST) if (pBT->eResourceType == IMPORTED_RESOURCE_TYPE) { pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_LIVE; } else if (pBT->eResourceType == NON_IMPORTED_RESOURCE_TYPE) { pBT->eResourceSpan = RESOURCE_SPAN_LIVE; } else { PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned ERROR: pBT->eResourceType unrecognized")); PVR_DBG_BREAK; } #endif if (!HASH_Insert (pArena->pSegmentHash, pBT->base, (IMG_UINTPTR_T) pBT)) { _FreeBT (pArena, pBT, IMG_FALSE); return IMG_FALSE; } if (ppsMapping!=IMG_NULL) *ppsMapping = pBT->psMapping; *base = pBT->base; return IMG_TRUE; } else { PVR_DPF ((PVR_DBG_MESSAGE, "AttemptAllocAligned: mismatch in flags. Import has %x, request was %x", pBT->psMapping->ui32Flags, uFlags)); } } pBT = pBT->pNextFree; } } uIndex++; } return IMG_FALSE; }