예제 #1
0
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);
}
예제 #2
0
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;
}
예제 #3
0
파일: ra.c 프로젝트: AdiPat/i9003_Kernel
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;
}