1 /**********************************************************************
3 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful but, except
10 * as otherwise stated in writing, without any warranty; without even the
11 * implied warranty of merchantability or fitness for a particular purpose.
12 * See the GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
21 * Contact Information:
22 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
25 ******************************************************************************/
27 #include "services_headers.h"
30 #include "buffer_manager.h"
34 #include <linux/kernel.h>
38 #ifdef USE_BM_FREESPACE_CHECK
42 #define MINIMUM_HASH_SIZE (64)
54 struct _BT_ *pNextSegment;
55 struct _BT_ *pPrevSegment;
57 struct _BT_ *pNextFree;
58 struct _BT_ *pPrevFree;
60 BM_MAPPING *psMapping;
62 typedef struct _BT_ BT;
70 IMG_BOOL(*pImportAlloc) (void *,
72 IMG_SIZE_T * pActualSize,
73 BM_MAPPING ** ppsMapping,
74 IMG_UINT32 uFlags, IMG_UINTPTR_T * pBase);
75 void (*pImportFree) (void *, IMG_UINTPTR_T, BM_MAPPING * psMapping);
76 void (*pBackingStoreFree) (void *, IMG_UINT32, IMG_UINT32, IMG_HANDLE);
80 #define FREE_TABLE_LIMIT 32
82 BT *aHeadFree[FREE_TABLE_LIMIT];
87 HASH_TABLE *pSegmentHash;
90 RA_STATISTICS sStatistics;
93 #if defined(CONFIG_PROC_FS) && defined(DEBUG)
94 #define PROC_NAME_SIZE 32
95 char szProcInfoName[PROC_NAME_SIZE];
96 char szProcSegsName[PROC_NAME_SIZE];
100 void RA_Dump(RA_ARENA * pArena);
102 #if defined(CONFIG_PROC_FS) && defined(DEBUG)
104 RA_DumpSegs(char *page, char **start, off_t off, int count, int *eof,
106 static int RA_DumpInfo(char *page, char **start, off_t off, int count, int *eof,
110 #ifdef USE_BM_FREESPACE_CHECK
111 void CheckBMFreespace(void);
115 _RequestAllocFail(void *_h,
117 IMG_SIZE_T * _pActualSize,
118 BM_MAPPING ** _ppsMapping,
119 IMG_UINT32 _uFlags, IMG_UINTPTR_T * _pBase)
121 PVR_UNREFERENCED_PARAMETER(_h);
122 PVR_UNREFERENCED_PARAMETER(_uSize);
123 PVR_UNREFERENCED_PARAMETER(_pActualSize);
124 PVR_UNREFERENCED_PARAMETER(_ppsMapping);
125 PVR_UNREFERENCED_PARAMETER(_uFlags);
126 PVR_UNREFERENCED_PARAMETER(_pBase);
131 static IMG_UINT32 pvr_log2(IMG_SIZE_T n)
143 _SegmentListInsertAfter(RA_ARENA * pArena, BT * pInsertionPoint, BT * pBT)
145 PVR_ASSERT(pArena != IMG_NULL);
146 PVR_ASSERT(pInsertionPoint != IMG_NULL);
148 pBT->pNextSegment = pInsertionPoint->pNextSegment;
149 pBT->pPrevSegment = pInsertionPoint;
150 if (pInsertionPoint->pNextSegment == IMG_NULL)
151 pArena->pTailSegment = pBT;
153 pInsertionPoint->pNextSegment->pPrevSegment = pBT;
154 pInsertionPoint->pNextSegment = pBT;
157 static void _SegmentListInsert(RA_ARENA * pArena, BT * pBT)
160 if (pArena->pHeadSegment == IMG_NULL) {
161 pArena->pHeadSegment = pArena->pTailSegment = pBT;
162 pBT->pNextSegment = pBT->pPrevSegment = IMG_NULL;
165 pBTScan = pArena->pHeadSegment;
166 while (pBTScan->pNextSegment != IMG_NULL
167 && pBT->base >= pBTScan->pNextSegment->base)
168 pBTScan = pBTScan->pNextSegment;
169 _SegmentListInsertAfter(pArena, pBTScan, pBT);
173 static void _SegmentListRemove(RA_ARENA * pArena, BT * pBT)
175 if (pBT->pPrevSegment == IMG_NULL)
176 pArena->pHeadSegment = pBT->pNextSegment;
178 pBT->pPrevSegment->pNextSegment = pBT->pNextSegment;
180 if (pBT->pNextSegment == IMG_NULL)
181 pArena->pTailSegment = pBT->pPrevSegment;
183 pBT->pNextSegment->pPrevSegment = pBT->pPrevSegment;
186 static BT *_SegmentSplit(RA_ARENA * pArena, BT * pBT, IMG_SIZE_T uSize)
190 PVR_ASSERT(pArena != IMG_NULL);
192 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
194 (IMG_VOID **) & pNeighbour, IMG_NULL) != PVRSRV_OK) {
198 pNeighbour->pPrevSegment = pBT;
199 pNeighbour->pNextSegment = pBT->pNextSegment;
200 if (pBT->pNextSegment == IMG_NULL)
201 pArena->pTailSegment = pNeighbour;
203 pBT->pNextSegment->pPrevSegment = pNeighbour;
204 pBT->pNextSegment = pNeighbour;
206 pNeighbour->type = btt_free;
207 pNeighbour->uSize = pBT->uSize - uSize;
208 pNeighbour->base = pBT->base + uSize;
209 pNeighbour->psMapping = pBT->psMapping;
214 static void _FreeListInsert(RA_ARENA * pArena, BT * pBT)
217 uIndex = pvr_log2(pBT->uSize);
218 pBT->type = btt_free;
219 pBT->pNextFree = pArena->aHeadFree[uIndex];
220 pBT->pPrevFree = IMG_NULL;
221 if (pArena->aHeadFree[uIndex] != IMG_NULL)
222 pArena->aHeadFree[uIndex]->pPrevFree = pBT;
223 pArena->aHeadFree[uIndex] = pBT;
226 static void _FreeListRemove(RA_ARENA * pArena, BT * pBT)
229 uIndex = pvr_log2(pBT->uSize);
230 if (pBT->pNextFree != IMG_NULL)
231 pBT->pNextFree->pPrevFree = pBT->pPrevFree;
232 if (pBT->pPrevFree == IMG_NULL)
233 pArena->aHeadFree[uIndex] = pBT->pNextFree;
235 pBT->pPrevFree->pNextFree = pBT->pNextFree;
238 static BT *_BuildSpanMarker(IMG_UINTPTR_T base, IMG_SIZE_T uSize)
242 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
244 (IMG_VOID **) & pBT, IMG_NULL) != PVRSRV_OK) {
248 pBT->type = btt_span;
251 pBT->psMapping = IMG_NULL;
256 static BT *_BuildBT(IMG_UINTPTR_T base, IMG_SIZE_T uSize)
260 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
262 (IMG_VOID **) & pBT, IMG_NULL) != PVRSRV_OK) {
266 pBT->type = btt_free;
273 static BT *_InsertResource(RA_ARENA * pArena, IMG_UINTPTR_T base,
277 PVR_ASSERT(pArena != IMG_NULL);
278 pBT = _BuildBT(base, uSize);
279 if (pBT != IMG_NULL) {
280 _SegmentListInsert(pArena, pBT);
281 _FreeListInsert(pArena, pBT);
283 pArena->sStatistics.uTotalResourceCount += uSize;
284 pArena->sStatistics.uFreeResourceCount += uSize;
285 pArena->sStatistics.uSpanCount++;
291 static BT *_InsertResourceSpan(RA_ARENA * pArena, IMG_UINTPTR_T base,
298 PVR_ASSERT(pArena != IMG_NULL);
300 PVR_DPF((PVR_DBG_MESSAGE,
301 "RA_InsertResourceSpan: arena='%s', base=0x%x, size=0x%x",
302 pArena->name, base, uSize));
304 pSpanStart = _BuildSpanMarker(base, uSize);
305 if (pSpanStart == IMG_NULL) {
308 pSpanEnd = _BuildSpanMarker(base + uSize, 0);
309 if (pSpanEnd == IMG_NULL) {
313 pBT = _BuildBT(base, uSize);
314 if (pBT == IMG_NULL) {
318 _SegmentListInsert(pArena, pSpanStart);
319 _SegmentListInsertAfter(pArena, pSpanStart, pBT);
320 _FreeListInsert(pArena, pBT);
321 _SegmentListInsertAfter(pArena, pBT, pSpanEnd);
323 pArena->sStatistics.uTotalResourceCount += uSize;
328 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanEnd, IMG_NULL);
330 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanStart, IMG_NULL);
335 static void _FreeBT(RA_ARENA * pArena, BT * pBT, IMG_BOOL bFreeBackingStore)
338 IMG_UINTPTR_T uOrigBase;
339 IMG_SIZE_T uOrigSize;
341 PVR_ASSERT(pArena != IMG_NULL);
342 PVR_ASSERT(pBT != IMG_NULL);
345 pArena->sStatistics.uLiveSegmentCount--;
346 pArena->sStatistics.uFreeSegmentCount++;
347 pArena->sStatistics.uFreeResourceCount += pBT->uSize;
350 uOrigBase = pBT->base;
351 uOrigSize = pBT->uSize;
353 pNeighbour = pBT->pPrevSegment;
354 if (pNeighbour != IMG_NULL
355 && pNeighbour->type == btt_free
356 && pNeighbour->base + pNeighbour->uSize == pBT->base) {
357 _FreeListRemove(pArena, pNeighbour);
358 _SegmentListRemove(pArena, pNeighbour);
359 pBT->base = pNeighbour->base;
360 pBT->uSize += pNeighbour->uSize;
361 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour,
364 pArena->sStatistics.uFreeSegmentCount--;
368 pNeighbour = pBT->pNextSegment;
369 if (pNeighbour != IMG_NULL
370 && pNeighbour->type == btt_free
371 && pBT->base + pBT->uSize == pNeighbour->base) {
372 _FreeListRemove(pArena, pNeighbour);
373 _SegmentListRemove(pArena, pNeighbour);
374 pBT->uSize += pNeighbour->uSize;
375 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour,
378 pArena->sStatistics.uFreeSegmentCount--;
382 if (pArena->pBackingStoreFree != IMG_NULL && bFreeBackingStore) {
383 IMG_UINTPTR_T uRoundedStart, uRoundedEnd;
386 (uOrigBase / pArena->uQuantum) * pArena->uQuantum;
388 if (uRoundedStart < pBT->base) {
389 uRoundedStart += pArena->uQuantum;
393 ((uOrigBase + uOrigSize + pArena->uQuantum -
394 1) / pArena->uQuantum) * pArena->uQuantum;
396 if (uRoundedEnd > (pBT->base + pBT->uSize)) {
397 uRoundedEnd -= pArena->uQuantum;
400 if (uRoundedStart < uRoundedEnd) {
401 pArena->pBackingStoreFree(pArena->pImportHandle,
402 uRoundedStart, uRoundedEnd,
407 if (pBT->pNextSegment != IMG_NULL && pBT->pNextSegment->type == btt_span
408 && pBT->pPrevSegment != IMG_NULL
409 && pBT->pPrevSegment->type == btt_span) {
410 BT *next = pBT->pNextSegment;
411 BT *prev = pBT->pPrevSegment;
412 _SegmentListRemove(pArena, next);
413 _SegmentListRemove(pArena, prev);
414 _SegmentListRemove(pArena, pBT);
415 pArena->pImportFree(pArena->pImportHandle, pBT->base,
418 pArena->sStatistics.uSpanCount--;
419 pArena->sStatistics.uExportCount++;
420 pArena->sStatistics.uFreeSegmentCount--;
421 pArena->sStatistics.uFreeResourceCount -= pBT->uSize;
422 pArena->sStatistics.uTotalResourceCount -= pBT->uSize;
424 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), next, IMG_NULL);
425 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), prev, IMG_NULL);
426 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
428 _FreeListInsert(pArena, pBT);
432 _AttemptAllocAligned(RA_ARENA * pArena,
434 BM_MAPPING ** ppsMapping,
436 IMG_UINT32 uAlignment,
437 IMG_UINT32 uAlignmentOffset, IMG_UINTPTR_T * base)
440 PVR_ASSERT(pArena != IMG_NULL);
442 PVR_UNREFERENCED_PARAMETER(uFlags);
445 uAlignmentOffset %= uAlignment;
447 uIndex = pvr_log2(uSize);
451 if (1u << uIndex < uSize)
455 while (uIndex < FREE_TABLE_LIMIT
456 && pArena->aHeadFree[uIndex] == IMG_NULL)
459 while (uIndex < FREE_TABLE_LIMIT) {
460 if (pArena->aHeadFree[uIndex] != IMG_NULL) {
464 pBT = pArena->aHeadFree[uIndex];
465 while (pBT != IMG_NULL) {
466 IMG_UINTPTR_T aligned_base;
470 (pBT->base + uAlignmentOffset +
472 1) / uAlignment * uAlignment -
475 aligned_base = pBT->base;
476 PVR_DPF((PVR_DBG_MESSAGE,
477 "RA_AttemptAllocAligned: pBT-base=0x%x "
478 "pBT-size=0x%x alignedbase=0x%x size=0x%x",
479 pBT->base, pBT->uSize, aligned_base,
482 if (pBT->base + pBT->uSize >=
483 aligned_base + uSize) {
485 || pBT->psMapping->ui32Flags ==
487 _FreeListRemove(pArena, pBT);
489 PVR_ASSERT(pBT->type ==
498 uFreeResourceCount -=
502 if (aligned_base > pBT->base) {
513 PVR_DPF((PVR_DBG_ERROR, "_AttemptAllocAligned: Front split failed"));
522 _FreeListInsert(pArena,
534 if (pBT->uSize > uSize) {
543 PVR_DPF((PVR_DBG_ERROR, "_AttemptAllocAligned: Back split failed"));
552 _FreeListInsert(pArena,
564 pBT->type = btt_live;
567 (pArena->pSegmentHash,
569 (IMG_UINTPTR_T) pBT)) {
575 if (ppsMapping != IMG_NULL)
583 PVR_DPF((PVR_DBG_MESSAGE,
584 "AttemptAllocAligned: mismatch in flags. Import has %x, request was %x",
590 pBT = pBT->pNextFree;
600 RA_ARENA *RA_Create(IMG_CHAR * name,
603 BM_MAPPING * psMapping,
605 IMG_BOOL(*alloc) (IMG_VOID *, IMG_SIZE_T uSize,
606 IMG_SIZE_T * pActualSize,
607 BM_MAPPING ** ppsMapping,
608 IMG_UINT32 _flags, IMG_UINTPTR_T * pBase),
609 IMG_VOID(*free) (IMG_VOID *, IMG_UINTPTR_T,
610 BM_MAPPING * psMapping),
611 IMG_VOID(*backingstore_free) (IMG_VOID *, IMG_UINT32,
612 IMG_UINT32, IMG_HANDLE),
613 IMG_VOID * pImportHandle)
619 PVR_DPF((PVR_DBG_MESSAGE,
620 "RA_Create: name='%s', base=0x%x, uSize=0x%x, alloc=0x%x, free=0x%x",
621 name, base, uSize, alloc, free));
623 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
625 (IMG_VOID **) & pArena, IMG_NULL) != PVRSRV_OK) {
630 pArena->pImportAlloc = alloc != IMG_NULL ? alloc : _RequestAllocFail;
631 pArena->pImportFree = free;
632 pArena->pBackingStoreFree = backingstore_free;
633 pArena->pImportHandle = pImportHandle;
634 for (i = 0; i < FREE_TABLE_LIMIT; i++)
635 pArena->aHeadFree[i] = IMG_NULL;
636 pArena->pHeadSegment = IMG_NULL;
637 pArena->pTailSegment = IMG_NULL;
638 pArena->uQuantum = uQuantum;
641 pArena->sStatistics.uSpanCount = 0;
642 pArena->sStatistics.uLiveSegmentCount = 0;
643 pArena->sStatistics.uFreeSegmentCount = 0;
644 pArena->sStatistics.uFreeResourceCount = 0;
645 pArena->sStatistics.uTotalResourceCount = 0;
646 pArena->sStatistics.uCumulativeAllocs = 0;
647 pArena->sStatistics.uCumulativeFrees = 0;
648 pArena->sStatistics.uImportCount = 0;
649 pArena->sStatistics.uExportCount = 0;
652 #if defined(CONFIG_PROC_FS) && defined(DEBUG)
653 if (strcmp(pArena->name, "") != 0) {
654 sprintf(pArena->szProcInfoName, "ra_info_%s", pArena->name);
655 CreateProcEntry(pArena->szProcInfoName, RA_DumpInfo, 0, pArena);
656 sprintf(pArena->szProcSegsName, "ra_segs_%s", pArena->name);
657 CreateProcEntry(pArena->szProcSegsName, RA_DumpSegs, 0, pArena);
661 pArena->pSegmentHash = HASH_Create(MINIMUM_HASH_SIZE);
662 if (pArena->pSegmentHash == IMG_NULL) {
666 uSize = (uSize + uQuantum - 1) / uQuantum * uQuantum;
667 pBT = _InsertResource(pArena, base, uSize);
668 if (pBT == IMG_NULL) {
671 pBT->psMapping = psMapping;
677 HASH_Delete(pArena->pSegmentHash);
679 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
684 void RA_Delete(RA_ARENA * pArena)
688 PVR_ASSERT(pArena != IMG_NULL);
689 PVR_DPF((PVR_DBG_MESSAGE, "RA_Delete: name='%s'", pArena->name));
691 for (uIndex = 0; uIndex < FREE_TABLE_LIMIT; uIndex++)
692 pArena->aHeadFree[uIndex] = IMG_NULL;
694 while (pArena->pHeadSegment != IMG_NULL) {
695 BT *pBT = pArena->pHeadSegment;
696 PVR_ASSERT(pBT->type == btt_free);
697 _SegmentListRemove(pArena, pBT);
698 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
700 pArena->sStatistics.uSpanCount--;
703 #if defined(CONFIG_PROC_FS) && defined(DEBUG)
704 RemoveProcEntry(pArena->szProcInfoName);
705 RemoveProcEntry(pArena->szProcSegsName);
707 HASH_Delete(pArena->pSegmentHash);
708 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
711 IMG_BOOL RA_Add(RA_ARENA * pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
713 PVR_ASSERT(pArena != IMG_NULL);
715 PVR_DPF((PVR_DBG_MESSAGE,
716 "RA_Add: name='%s', base=0x%x, size=0x%x", pArena->name, base,
720 (uSize + pArena->uQuantum -
721 1) / pArena->uQuantum * pArena->uQuantum;
722 return ((IMG_BOOL) (_InsertResource(pArena, base, uSize) != IMG_NULL));
726 RA_Alloc(RA_ARENA * pArena,
727 IMG_SIZE_T uRequestSize,
728 IMG_SIZE_T * pActualSize,
729 BM_MAPPING ** ppsMapping,
731 IMG_UINT32 uAlignment,
732 IMG_UINT32 uAlignmentOffset, IMG_UINTPTR_T * base)
734 IMG_BOOL bResult = IMG_FALSE;
735 IMG_SIZE_T uSize = uRequestSize;
737 PVR_ASSERT(pArena != IMG_NULL);
739 #ifdef USE_BM_FREESPACE_CHECK
743 if (pActualSize != IMG_NULL)
744 *pActualSize = uSize;
746 PVR_DPF((PVR_DBG_MESSAGE,
747 "RA_Alloc: arena='%s', size=0x%x(0x%x), alignment=0x%x, offset=0x%x",
748 pArena->name, uSize, uRequestSize, uAlignment,
751 bResult = _AttemptAllocAligned(pArena, uSize, ppsMapping, uFlags,
752 uAlignment, uAlignmentOffset, base);
754 BM_MAPPING *psImportMapping;
755 IMG_UINTPTR_T import_base;
756 IMG_SIZE_T uImportSize = uSize;
758 if (uAlignment > pArena->uQuantum) {
759 uImportSize += (uAlignment - 1);
763 ((uImportSize + pArena->uQuantum -
764 1) / pArena->uQuantum) * pArena->uQuantum;
767 pArena->pImportAlloc(pArena->pImportHandle, uImportSize,
768 &uImportSize, &psImportMapping, uFlags,
773 _InsertResourceSpan(pArena, import_base,
776 if (pBT == IMG_NULL) {
778 pArena->pImportFree(pArena->pImportHandle,
781 PVR_DPF((PVR_DBG_MESSAGE,
782 "RA_Alloc: name='%s', size=0x%x failed!",
783 pArena->name, uSize));
787 pBT->psMapping = psImportMapping;
789 pArena->sStatistics.uFreeSegmentCount++;
790 pArena->sStatistics.uFreeResourceCount += uImportSize;
791 pArena->sStatistics.uImportCount++;
792 pArena->sStatistics.uSpanCount++;
795 _AttemptAllocAligned(pArena, uSize, ppsMapping,
797 uAlignmentOffset, base);
799 PVR_DPF((PVR_DBG_MESSAGE,
800 "RA_Alloc: name='%s' uAlignment failed!",
807 pArena->sStatistics.uCumulativeAllocs++;
810 PVR_DPF((PVR_DBG_MESSAGE,
811 "RA_Alloc: name='%s', size=0x%x, *base=0x%x = %d",
812 pArena->name, uSize, *base, bResult));
817 void RA_Free(RA_ARENA * pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore)
821 PVR_ASSERT(pArena != IMG_NULL);
823 #ifdef USE_BM_FREESPACE_CHECK
827 PVR_DPF((PVR_DBG_MESSAGE,
828 "RA_Free: name='%s', base=0x%x", pArena->name, base));
830 pBT = (BT *) HASH_Remove(pArena->pSegmentHash, base);
831 PVR_ASSERT(pBT != IMG_NULL);
834 PVR_ASSERT(pBT->base == base);
837 pArena->sStatistics.uCumulativeFrees++;
840 #ifdef USE_BM_FREESPACE_CHECK
845 p = (unsigned char *)pBT->base +
846 SysGetDevicePhysOffset();
847 endp = (unsigned char *)((IMG_UINT32) (p + pBT->uSize));
848 while ((IMG_UINT32) p & 3) {
852 (unsigned char *)((IMG_UINT32) endp &
854 *(IMG_UINT32 *) p = 0xAAAAAAAA;
855 p += sizeof(IMG_UINT32);
860 PVR_DPF((PVR_DBG_MESSAGE,
861 "BM_FREESPACE_CHECK: RA_Free Cleared %08X to %08X (size=0x%x)",
862 (unsigned char *)pBT->base +
863 SysGetDevicePhysOffset(), endp - 1,
867 _FreeBT(pArena, pBT, bFreeBackingStore);
871 IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena,
872 RA_SEGMENT_DETAILS * psSegDetails)
876 if (psSegDetails->hSegment) {
877 pBT = (BT *) psSegDetails->hSegment;
879 RA_ARENA *pArena = (RA_ARENA *) hArena;
881 pBT = pArena->pHeadSegment;
884 while (pBT != IMG_NULL) {
885 if (pBT->type == btt_live) {
886 psSegDetails->uiSize = pBT->uSize;
887 psSegDetails->sCpuPhyAddr.uiAddr = pBT->base;
888 psSegDetails->hSegment = (IMG_HANDLE) pBT->pNextSegment;
893 pBT = pBT->pNextSegment;
896 psSegDetails->uiSize = 0;
897 psSegDetails->sCpuPhyAddr.uiAddr = 0;
898 psSegDetails->hSegment = (IMG_HANDLE) - 1;
903 #ifdef USE_BM_FREESPACE_CHECK
904 RA_ARENA *pJFSavedArena = IMG_NULL;
906 void CheckBMFreespace(void)
912 if (pJFSavedArena != IMG_NULL) {
913 for (pBT = pJFSavedArena->pHeadSegment; pBT != IMG_NULL;
914 pBT = pBT->pNextSegment) {
915 if (pBT->type == btt_free) {
916 p = (unsigned char *)pBT->base +
917 SysGetDevicePhysOffset();
921 pBT->uSize) & 0xfffffffc);
923 while ((IMG_UINT32) p & 3) {
926 "BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",
927 p, *(unsigned long *)p);
933 if (*(unsigned long *)p != 0xAAAAAAAA) {
935 "BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",
936 p, *(unsigned long *)p);
948 #if (defined(CONFIG_PROC_FS) && defined(DEBUG)) || defined (RA_STATS)
949 static char *_BTType(int eType)
963 #if defined(CONFIG_PROC_FS) && defined(DEBUG)
965 RA_DumpSegs(char *page, char **start, off_t off, int count, int *eof,
970 RA_ARENA *pArena = (RA_ARENA *) data;
979 return printAppend(page, count, 0,
980 "Arena \"%s\"\nBase Size Type Ref\n",
983 for (pBT = pArena->pHeadSegment; --off && pBT;
984 pBT = pBT->pNextSegment) ;
986 len = printAppend(page, count, 0, "%08x %8x %4s %08x\n",
987 (unsigned int)pBT->base,
988 (unsigned int)pBT->uSize, _BTType(pBT->type),
989 (unsigned int)pBT->psMapping);
997 RA_DumpInfo(char *page, char **start, off_t off, int count, int *eof,
1001 RA_ARENA *pArena = (RA_ARENA *) data;
1011 printAppend(page, count, 0, "quantum\t\t\t%lu\n",
1016 printAppend(page, count, 0, "import_handle\t\t%08X\n",
1017 (unsigned int)pArena->pImportHandle);
1022 printAppend(page, count, 0, "span count\t\t%lu\n",
1023 pArena->sStatistics.uSpanCount);
1027 printAppend(page, count, 0, "live segment count\t%lu\n",
1028 pArena->sStatistics.uLiveSegmentCount);
1032 printAppend(page, count, 0, "free segment count\t%lu\n",
1033 pArena->sStatistics.uFreeSegmentCount);
1037 printAppend(page, count, 0,
1038 "free resource count\t%lu (0x%x)\n",
1039 pArena->sStatistics.uFreeResourceCount,
1040 (unsigned int)pArena->sStatistics.
1041 uFreeResourceCount);
1045 printAppend(page, count, 0, "total allocs\t\t%lu\n",
1046 pArena->sStatistics.uCumulativeAllocs);
1050 printAppend(page, count, 0, "total frees\t\t%lu\n",
1051 pArena->sStatistics.uCumulativeFrees);
1055 printAppend(page, count, 0, "import count\t\t%lu\n",
1056 pArena->sStatistics.uImportCount);
1060 printAppend(page, count, 0, "export count\t\t%lu\n",
1061 pArena->sStatistics.uExportCount);
1074 PVRSRV_ERROR RA_GetStats(RA_ARENA * pArena,
1075 IMG_CHAR ** ppszStr, IMG_UINT32 * pui32StrLen)
1077 IMG_CHAR *pszStr = *ppszStr;
1078 IMG_UINT32 ui32StrLen = *pui32StrLen;
1082 CHECK_SPACE(ui32StrLen);
1083 i32Count = OSSNPrintf(pszStr, 100, "\nArena '%s':\n", pArena->name);
1084 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1086 CHECK_SPACE(ui32StrLen);
1088 OSSNPrintf(pszStr, 100,
1089 " allocCB=%08X freeCB=%08X handle=%08X quantum=%d\n",
1090 pArena->pImportAlloc, pArena->pImportFree,
1091 pArena->pImportHandle, pArena->uQuantum);
1092 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1094 CHECK_SPACE(ui32StrLen);
1096 OSSNPrintf(pszStr, 100, "span count\t\t%lu\n",
1097 pArena->sStatistics.uSpanCount);
1098 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1100 CHECK_SPACE(ui32StrLen);
1102 OSSNPrintf(pszStr, 100, "live segment count\t%lu\n",
1103 pArena->sStatistics.uLiveSegmentCount);
1104 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1106 CHECK_SPACE(ui32StrLen);
1108 OSSNPrintf(pszStr, 100, "free segment count\t%lu\n",
1109 pArena->sStatistics.uFreeSegmentCount);
1110 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1112 CHECK_SPACE(ui32StrLen);
1113 i32Count = OSSNPrintf(pszStr, 100, "free resource count\t%lu (0x%x)\n",
1114 pArena->sStatistics.uFreeResourceCount,
1115 (unsigned int)pArena->sStatistics.
1116 uFreeResourceCount);
1117 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1119 CHECK_SPACE(ui32StrLen);
1121 OSSNPrintf(pszStr, 100, "total allocs\t\t%lu\n",
1122 pArena->sStatistics.uCumulativeAllocs);
1123 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1125 CHECK_SPACE(ui32StrLen);
1127 OSSNPrintf(pszStr, 100, "total frees\t\t%lu\n",
1128 pArena->sStatistics.uCumulativeFrees);
1129 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1131 CHECK_SPACE(ui32StrLen);
1133 OSSNPrintf(pszStr, 100, "import count\t\t%lu\n",
1134 pArena->sStatistics.uImportCount);
1135 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1137 CHECK_SPACE(ui32StrLen);
1139 OSSNPrintf(pszStr, 100, "export count\t\t%lu\n",
1140 pArena->sStatistics.uExportCount);
1141 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1143 CHECK_SPACE(ui32StrLen);
1144 i32Count = OSSNPrintf(pszStr, 100, " segment Chain:\n");
1145 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1147 if (pArena->pHeadSegment != IMG_NULL &&
1148 pArena->pHeadSegment->pPrevSegment != IMG_NULL) {
1149 CHECK_SPACE(ui32StrLen);
1151 OSSNPrintf(pszStr, 100,
1152 " error: head boundary tag has invalid pPrevSegment\n");
1153 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1156 if (pArena->pTailSegment != IMG_NULL &&
1157 pArena->pTailSegment->pNextSegment != IMG_NULL) {
1158 CHECK_SPACE(ui32StrLen);
1160 OSSNPrintf(pszStr, 100,
1161 " error: tail boundary tag has invalid pNextSegment\n");
1162 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1165 for (pBT = pArena->pHeadSegment; pBT != IMG_NULL;
1166 pBT = pBT->pNextSegment) {
1167 CHECK_SPACE(ui32StrLen);
1169 OSSNPrintf(pszStr, 100,
1170 "\tbase=0x%x size=0x%x type=%s ref=%08X\n",
1171 (unsigned long)pBT->base, pBT->uSize,
1172 _BTType(pBT->type), pBT->psMapping);
1173 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
1177 *pui32StrLen = ui32StrLen;