diff options
Diffstat (limited to 'pvr-source/services4/srvkm/common/ra.c')
-rwxr-xr-x | pvr-source/services4/srvkm/common/ra.c | 2427 |
1 files changed, 0 insertions, 2427 deletions
diff --git a/pvr-source/services4/srvkm/common/ra.c b/pvr-source/services4/srvkm/common/ra.c deleted file mode 100755 index da48939..0000000 --- a/pvr-source/services4/srvkm/common/ra.c +++ /dev/null @@ -1,2427 +0,0 @@ -/*************************************************************************/ /*! -@Title Resource Allocator -@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved -@Description - Implements generic resource allocation. The resource - allocator was originally intended to manage address spaces in - practice the resource allocator is generic and can manages arbitrary - sets of integers. - - Resources are allocated from arenas. Arena's can be created with an - initial span of resources. Further resources spans can be added to - arenas. A call back mechanism allows an arena to request further - resource spans on demand. - - Each arena maintains an ordered list of resource segments each - described by a boundary tag. Each boundary tag describes a segment - of resources which are either 'free', available for allocation, or - 'busy' currently allocated. Adjacent 'free' segments are always - coallesced to avoid fragmentation. - - For allocation, all 'free' segments are kept on lists of 'free' - segments in a table index by pvr_log2(segment size). ie Each table index - n holds 'free' segments in the size range 2**(n-1) -> 2**n. - - Allocation policy is based on an *almost* best fit - stratedy. Choosing any segment from the appropriate table entry - guarantees that we choose a segment which is with a power of 2 of - the size we are allocating. - - Allocated segments are inserted into a self scaling hash table which - maps the base resource of the span to the relevant boundary - tag. This allows the code to get back to the bounary tag without - exporting explicit boundary tag references through the API. - - Each arena has an associated quantum size, all allocations from the - arena are made in multiples of the basic quantum. - - On resource exhaustion in an arena, a callback if provided will be - used to request further resources. Resouces spans allocated by the - callback mechanism are delimited by special boundary tag markers of - zero span, 'span' markers. Span markers are never coallesced. Span - markers are used to detect when an imported span is completely free - and can be deallocated by the callback mechanism. -@License Dual MIT/GPLv2 - -The contents of this file are subject to the MIT license as set out below. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -Alternatively, the contents of this file may be used under the terms of -the GNU General Public License Version 2 ("GPL") in which case the provisions -of GPL are applicable instead of those above. - -If you wish to allow use of your version of this file only under the terms of -GPL, and not to allow others to use your version of this file under the terms -of the MIT license, indicate your decision by deleting the provisions above -and replace them with the notice and other provisions required by GPL as set -out in the file called "GPL-COPYING" included in this distribution. If you do -not delete the provisions above, a recipient may use your version of this file -under the terms of either the MIT license or GPL. - -This License is also included in this distribution in the file called -"MIT-COPYING". - -EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS -PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING -BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ /**************************************************************************/ - -/* Issues: - * - flags, flags are passed into the resource allocator but are not currently used. - * - determination, of import size, is currently braindead. - * - debug code should be moved out to own module and #ifdef'd - */ - -#include "services_headers.h" -#include "hash.h" -#include "ra.h" -#include "buffer_manager.h" -#include "osfunc.h" - -#if defined(__linux__) && defined(__KERNEL__) -#include <linux/kernel.h> -#include "pvr_uaccess.h" -#include "proc.h" -#include <linux/sched.h> -#endif - -#ifdef USE_BM_FREESPACE_CHECK -#include <stdio.h> -#endif - -/* The initial, and minimum size of the live address -> boundary tag - structure hash table. The value 64 is a fairly arbitrary - choice. The hash table resizes on demand so the value choosen is - not critical. */ -#define MINIMUM_HASH_SIZE (64) - -#if defined(VALIDATE_ARENA_TEST) - -/* This test validates the doubly linked ordered list of boundary tags, by -checking that adjacent members of the list have compatible eResourceSpan -and eResourceType values. */ - -typedef enum RESOURCE_DESCRIPTOR_TAG { - - RESOURCE_SPAN_LIVE = 10, - RESOURCE_SPAN_FREE, - IMPORTED_RESOURCE_SPAN_START, - IMPORTED_RESOURCE_SPAN_LIVE, - IMPORTED_RESOURCE_SPAN_FREE, - IMPORTED_RESOURCE_SPAN_END, - -} RESOURCE_DESCRIPTOR; - -typedef enum RESOURCE_TYPE_TAG { - - IMPORTED_RESOURCE_TYPE = 20, - NON_IMPORTED_RESOURCE_TYPE - -} RESOURCE_TYPE; - - -static IMG_UINT32 ui32BoundaryTagID = 0; - -IMG_UINT32 ValidateArena(RA_ARENA *pArena); -#endif - -/* boundary tags, used to describe a resource segment */ -struct _BT_ -{ - enum bt_type - { - btt_span, /* span markers */ - btt_free, /* free resource segment */ - btt_live /* allocated resource segment */ - } type; - - /* The base resource and extent of this segment */ - IMG_UINTPTR_T base; - IMG_SIZE_T uSize; - - /* doubly linked ordered list of all segments within the arena */ - struct _BT_ *pNextSegment; - struct _BT_ *pPrevSegment; - /* doubly linked un-ordered list of free segments. */ - struct _BT_ *pNextFree; - struct _BT_ *pPrevFree; - /* a user reference associated with this span, user references are - * currently only provided in the callback mechanism */ - BM_MAPPING *psMapping; - -#if defined(VALIDATE_ARENA_TEST) - RESOURCE_DESCRIPTOR eResourceSpan; - RESOURCE_TYPE eResourceType; - - /* This variable provides a reference (used in debug messages) to incompatible - boundary tags within the doubly linked ordered list. */ - IMG_UINT32 ui32BoundaryTagID; -#endif - -}; -typedef struct _BT_ BT; - - -/* resource allocation arena */ -struct _RA_ARENA_ -{ - /* arena name for diagnostics output */ - IMG_CHAR *name; - - /* allocations within this arena are quantum sized */ - IMG_SIZE_T uQuantum; - - /* import interface, if provided */ - IMG_BOOL (*pImportAlloc)(IMG_VOID *, - IMG_SIZE_T uSize, - IMG_SIZE_T *pActualSize, - BM_MAPPING **ppsMapping, - IMG_UINT32 uFlags, - IMG_PVOID pvPrivData, - IMG_UINT32 ui32PrivDataLength, - IMG_UINTPTR_T *pBase); - IMG_VOID (*pImportFree) (IMG_VOID *, - IMG_UINTPTR_T, - BM_MAPPING *psMapping); - IMG_VOID (*pBackingStoreFree) (IMG_VOID *, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE); - - /* arbitrary handle provided by arena owner to be passed into the - * import alloc and free hooks */ - IMG_VOID *pImportHandle; - - /* head of list of free boundary tags for indexed by pvr_log2 of the - boundary tag size */ -#define FREE_TABLE_LIMIT 32 - - /* power-of-two table of free lists */ - BT *aHeadFree [FREE_TABLE_LIMIT]; - - /* resource ordered segment list */ - BT *pHeadSegment; - BT *pTailSegment; - - /* segment address to boundary tag hash table */ - HASH_TABLE *pSegmentHash; - -#ifdef RA_STATS - RA_STATISTICS sStatistics; -#endif - -#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS) -#define PROC_NAME_SIZE 64 - - struct proc_dir_entry* pProcInfo; - struct proc_dir_entry* pProcSegs; - - IMG_BOOL bInitProcEntry; - -#if defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG) - struct proc_dir_entry* pProcAllocFailThreshold; - - IMG_BOOL bFailAllocationOnce; - IMG_BOOL bFailAllocationPersist; - IMG_SIZE_T uAllocFailThreshold; - IMG_UINT32 uAllocFailMask; -#endif //defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG) - -#endif -}; -/* #define ENABLE_RA_DUMP 1 */ -#if defined(ENABLE_RA_DUMP) -IMG_VOID RA_Dump (RA_ARENA *pArena); -#endif - -static INLINE IMG_BOOL RA_TestAllocationFail(RA_ARENA *pArena, IMG_SIZE_T size, IMG_UINT32 buff_type) -{ - #if defined (CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG) - if(pArena->bFailAllocationOnce == IMG_TRUE) - { - if((size > pArena->uAllocFailThreshold) && (pArena->uAllocFailMask & buff_type)) - { - if(pArena->bFailAllocationPersist == IMG_FALSE) - pArena->bFailAllocationOnce = IMG_FALSE; - return IMG_TRUE; - } - } - #endif //CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG - return IMG_FALSE; -} - -#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS) - -static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el); -static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off); - -static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el); -static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off); - -#if defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG) -static int RA_ProcSetAllocFailThreshold(struct file *file, const char __user *buffer, unsigned long count, void *data); -static void* RA_ProcSeqOff2AllocFailThreshold(struct seq_file * sfile, loff_t off); -static void RA_ProcSeqShowAllocFailThreshold(struct seq_file *sfile,void* el); -#endif //defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG) - -#endif /* defined(CONFIG_PROC_FS) && defined(DEBUG) */ - -static PVRSRV_ERROR RA_DumpHeapInfo(RA_ARENA *pArena, IMG_UINT32 ui32DebugLevel); - -#ifdef USE_BM_FREESPACE_CHECK -IMG_VOID CheckBMFreespace(IMG_VOID); -#endif - -#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS) -static IMG_CHAR *ReplaceSpaces(IMG_CHAR * const pS) -{ - IMG_CHAR *pT; - - for(pT = pS; *pT != 0; pT++) - { - if (*pT == ' ' || *pT == '\t') - { - *pT = '_'; - } - } - - return pS; -} -#endif - -/*! -****************************************************************************** - @Function _RequestAllocFail - - @Description Default callback allocator used if no callback is - specified, always fails to allocate further resources to the - arena. - - @Input _h - callback handle - @Input _uSize - requested allocation size - @Output _pActualSize - actual allocation size - @Input _pRef - user reference - @Input _uflags - allocation flags - @Input _pvPrivData - private data - @Input _ui32PrivDataLength - private data length - @Input _pBase - receives allocated base - - @Return IMG_FALSE, this function always fails to allocate. -******************************************************************************/ -static IMG_BOOL -_RequestAllocFail (IMG_VOID *_h, - IMG_SIZE_T _uSize, - IMG_SIZE_T *_pActualSize, - BM_MAPPING **_ppsMapping, - IMG_UINT32 _uFlags, - IMG_PVOID _pvPrivData, - IMG_UINT32 _ui32PrivDataLength, - IMG_UINTPTR_T *_pBase) -{ - PVR_UNREFERENCED_PARAMETER (_h); - PVR_UNREFERENCED_PARAMETER (_uSize); - PVR_UNREFERENCED_PARAMETER (_pActualSize); - PVR_UNREFERENCED_PARAMETER (_ppsMapping); - PVR_UNREFERENCED_PARAMETER (_uFlags); - PVR_UNREFERENCED_PARAMETER (_pBase); - PVR_UNREFERENCED_PARAMETER (_pvPrivData); - PVR_UNREFERENCED_PARAMETER (_ui32PrivDataLength); - - return IMG_FALSE; -} - -/*! -****************************************************************************** - @Function pvr_log2 - - @Description Computes the floor of the log base 2 of a unsigned integer - - @Input n - unsigned integer - - @Return Floor(Log2(n)) -******************************************************************************/ -static IMG_UINT32 -pvr_log2 (IMG_SIZE_T n) -{ - IMG_UINT32 l = 0; - n>>=1; - while (n>0) - { - n>>=1; - l++; - } - return l; -} - -/*! -****************************************************************************** - @Function _SegmentListInsertAfter - - @Description Insert a boundary tag into an arena segment list after a - specified boundary tag. - - @Input pArena - the arena. - @Input pInsertionPoint - the insertion point. - @Input pBT - the boundary tag to insert. - - @Return PVRSRV_ERROR -******************************************************************************/ -static PVRSRV_ERROR -_SegmentListInsertAfter (RA_ARENA *pArena, - BT *pInsertionPoint, - BT *pBT) -{ - PVR_ASSERT (pArena != IMG_NULL); - PVR_ASSERT (pInsertionPoint != IMG_NULL); - - if ((pInsertionPoint == IMG_NULL) || (pArena == IMG_NULL)) - { - PVR_DPF ((PVR_DBG_ERROR,"_SegmentListInsertAfter: invalid parameters")); - return PVRSRV_ERROR_INVALID_PARAMS; - } - - pBT->pNextSegment = pInsertionPoint->pNextSegment; - pBT->pPrevSegment = pInsertionPoint; - if (pInsertionPoint->pNextSegment == IMG_NULL) - pArena->pTailSegment = pBT; - else - pInsertionPoint->pNextSegment->pPrevSegment = pBT; - pInsertionPoint->pNextSegment = pBT; - - return PVRSRV_OK; -} - -/*! -****************************************************************************** - @Function _SegmentListInsert - - @Description Insert a boundary tag into an arena segment list at the - appropriate point. - - @Input pArena - the arena. - @Input pBT - the boundary tag to insert. - - @Return None -******************************************************************************/ -static PVRSRV_ERROR -_SegmentListInsert (RA_ARENA *pArena, BT *pBT) -{ - PVRSRV_ERROR eError = PVRSRV_OK; - - /* insert into the segment chain */ - if (pArena->pHeadSegment == IMG_NULL) - { - pArena->pHeadSegment = pArena->pTailSegment = pBT; - pBT->pNextSegment = pBT->pPrevSegment = IMG_NULL; - } - else - { - BT *pBTScan; - - if (pBT->base < pArena->pHeadSegment->base) - { - /* The base address of pBT is less than the base address of the boundary tag - at the head of the list - so insert this boundary tag at the head. */ - pBT->pNextSegment = pArena->pHeadSegment; - pArena->pHeadSegment->pPrevSegment = pBT; - pArena->pHeadSegment = pBT; - pBT->pPrevSegment = IMG_NULL; - } - else - { - - /* The base address of pBT is greater than or equal to that of the boundary tag - at the head of the list. Search for the insertion point: pBT must be inserted - before the first boundary tag with a greater base value - or at the end of the list. - */ - pBTScan = pArena->pHeadSegment; - - while ((pBTScan->pNextSegment != IMG_NULL) && (pBT->base >= pBTScan->pNextSegment->base)) - { - pBTScan = pBTScan->pNextSegment; - } - - eError = _SegmentListInsertAfter (pArena, pBTScan, pBT); - if (eError != PVRSRV_OK) - { - return eError; - } - } - } - return eError; -} - -/*! -****************************************************************************** - @Function _SegmentListRemove - - @Description Remove a boundary tag from an arena segment list. - - @Input pArena - the arena. - @Input pBT - the boundary tag to remove. - - @Return None -******************************************************************************/ -static IMG_VOID -_SegmentListRemove (RA_ARENA *pArena, BT *pBT) -{ - if (pBT->pPrevSegment == IMG_NULL) - pArena->pHeadSegment = pBT->pNextSegment; - else - pBT->pPrevSegment->pNextSegment = pBT->pNextSegment; - - if (pBT->pNextSegment == IMG_NULL) - pArena->pTailSegment = pBT->pPrevSegment; - else - pBT->pNextSegment->pPrevSegment = pBT->pPrevSegment; -} - -/*! -****************************************************************************** - @Function _SegmentSplit - - @Description Split a segment into two, maintain the arena segment list. The - boundary tag should not be in the free table. Neither the - original or the new neighbour bounary tag will be in the free - table. - - @Input pArena - the arena. - @Input pBT - the boundary tag to split. - @Input uSize - the required segment size of boundary tag after - splitting. - - @Return New neighbour boundary tag. - -******************************************************************************/ -static BT * -_SegmentSplit (RA_ARENA *pArena, BT *pBT, IMG_SIZE_T uSize) -{ - BT *pNeighbour; - - PVR_ASSERT (pArena != IMG_NULL); - - if (pArena == IMG_NULL) - { - PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: invalid parameter - pArena")); - return IMG_NULL; - } - - if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, - sizeof(BT), - (IMG_VOID **)&pNeighbour, IMG_NULL, - "Boundary Tag") != PVRSRV_OK) - { - return IMG_NULL; - } - - OSMemSet(pNeighbour, 0, sizeof(BT)); - -#if defined(VALIDATE_ARENA_TEST) - pNeighbour->ui32BoundaryTagID = ++ui32BoundaryTagID; -#endif - - pNeighbour->pPrevSegment = pBT; - pNeighbour->pNextSegment = pBT->pNextSegment; - if (pBT->pNextSegment == IMG_NULL) - pArena->pTailSegment = pNeighbour; - else - pBT->pNextSegment->pPrevSegment = pNeighbour; - pBT->pNextSegment = pNeighbour; - - pNeighbour->type = btt_free; - pNeighbour->uSize = pBT->uSize - uSize; - pNeighbour->base = pBT->base + uSize; - pNeighbour->psMapping = pBT->psMapping; - pBT->uSize = uSize; - -#if defined(VALIDATE_ARENA_TEST) - if (pNeighbour->pPrevSegment->eResourceType == IMPORTED_RESOURCE_TYPE) - { - pNeighbour->eResourceType = IMPORTED_RESOURCE_TYPE; - pNeighbour->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE; - } - else if (pNeighbour->pPrevSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE) - { - pNeighbour->eResourceType = NON_IMPORTED_RESOURCE_TYPE; - pNeighbour->eResourceSpan = RESOURCE_SPAN_FREE; - } - else - { - PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: pNeighbour->pPrevSegment->eResourceType unrecognized")); - PVR_DBG_BREAK; - } -#endif - - return pNeighbour; -} - -/*! -****************************************************************************** - @Function _FreeListInsert - - @Description Insert a boundary tag into an arena free table. - - @Input pArena - the arena. - @Input pBT - the boundary tag. - - @Return None - -******************************************************************************/ -static IMG_VOID -_FreeListInsert (RA_ARENA *pArena, BT *pBT) -{ - IMG_UINT32 uIndex; - uIndex = pvr_log2 (pBT->uSize); - pBT->type = btt_free; - pBT->pNextFree = pArena->aHeadFree [uIndex]; - pBT->pPrevFree = IMG_NULL; - if (pArena->aHeadFree[uIndex] != IMG_NULL) - pArena->aHeadFree[uIndex]->pPrevFree = pBT; - pArena->aHeadFree [uIndex] = pBT; -} - -/*! -****************************************************************************** - @Function _FreeListRemove - - @Description Remove a boundary tag from an arena free table. - - @Input pArena - the arena. - @Input pBT - the boundary tag. - - @Return None - -******************************************************************************/ -static IMG_VOID -_FreeListRemove (RA_ARENA *pArena, BT *pBT) -{ - IMG_UINT32 uIndex; - uIndex = pvr_log2 (pBT->uSize); - if (pBT->pNextFree != IMG_NULL) - pBT->pNextFree->pPrevFree = pBT->pPrevFree; - if (pBT->pPrevFree == IMG_NULL) - pArena->aHeadFree[uIndex] = pBT->pNextFree; - else - pBT->pPrevFree->pNextFree = pBT->pNextFree; -} - -/*! -****************************************************************************** - @Function _BuildSpanMarker - - @Description Construct a span marker boundary tag. - - @Input pArena - arena to contain span marker - @Input base - the base of the bounary tag. - - @Return span marker boundary tag - -******************************************************************************/ -static BT * -_BuildSpanMarker (IMG_UINTPTR_T base, IMG_SIZE_T uSize) -{ - BT *pBT; - - if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, - sizeof(BT), - (IMG_VOID **)&pBT, IMG_NULL, - "Boundary Tag") != PVRSRV_OK) - { - return IMG_NULL; - } - - OSMemSet(pBT, 0, sizeof(BT)); - -#if defined(VALIDATE_ARENA_TEST) - pBT->ui32BoundaryTagID = ++ui32BoundaryTagID; -#endif - - pBT->type = btt_span; - pBT->base = base; - pBT->uSize = uSize; - pBT->psMapping = IMG_NULL; - - return pBT; -} - -/*! -****************************************************************************** - @Function _BuildBT - - @Description Construct a boundary tag for a free segment. - - @Input base - the base of the resource segment. - @Input uSize - the extent of the resouce segment. - - @Return boundary tag - -******************************************************************************/ -static BT * -_BuildBT (IMG_UINTPTR_T base, IMG_SIZE_T uSize) -{ - BT *pBT; - - if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, - sizeof(BT), - (IMG_VOID **)&pBT, IMG_NULL, - "Boundary Tag") != PVRSRV_OK) - { - return IMG_NULL; - } - - OSMemSet(pBT, 0, sizeof(BT)); - -#if defined(VALIDATE_ARENA_TEST) - pBT->ui32BoundaryTagID = ++ui32BoundaryTagID; -#endif - - pBT->type = btt_free; - pBT->base = base; - pBT->uSize = uSize; - - return pBT; -} - -/*! -****************************************************************************** - @Function _InsertResource - - @Description Add a free resource segment to an arena. - - @Input pArena - the arena. - @Input base - the base of the resource segment. - @Input uSize - the extent of the resource segment. - - @Return New bucket pointer - IMG_NULL failure - -******************************************************************************/ -static BT * -_InsertResource (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize) -{ - BT *pBT; - PVR_ASSERT (pArena!=IMG_NULL); - if (pArena == IMG_NULL) - { - PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: invalid parameter - pArena")); - return IMG_NULL; - } - - pBT = _BuildBT (base, uSize); - if (pBT != IMG_NULL) - { - -#if defined(VALIDATE_ARENA_TEST) - pBT->eResourceSpan = RESOURCE_SPAN_FREE; - pBT->eResourceType = NON_IMPORTED_RESOURCE_TYPE; -#endif - - if (_SegmentListInsert (pArena, pBT) != PVRSRV_OK) - { - PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: call to _SegmentListInsert failed")); - return IMG_NULL; - } - _FreeListInsert (pArena, pBT); -#ifdef RA_STATS - pArena->sStatistics.uTotalResourceCount+=uSize; - pArena->sStatistics.uFreeResourceCount+=uSize; - pArena->sStatistics.uSpanCount++; -#endif - } - return pBT; -} - -/*! -****************************************************************************** - @Function _InsertResourceSpan - - @Description Add a free resource span to an arena, complete with span markers. - - @Input pArena - the arena. - @Input base - the base of the resource segment. - @Input uSize - the extent of the resource segment. - - @Return the boundary tag representing the free resource segment, - or IMG_NULL on failure. -******************************************************************************/ -static BT * -_InsertResourceSpan (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize) -{ - PVRSRV_ERROR eError; - BT *pSpanStart; - BT *pSpanEnd; - BT *pBT; - - PVR_ASSERT (pArena != IMG_NULL); - if (pArena == IMG_NULL) - { - PVR_DPF ((PVR_DBG_ERROR,"_InsertResourceSpan: invalid parameter - pArena")); - return IMG_NULL; - } - - PVR_DPF ((PVR_DBG_MESSAGE, - "RA_InsertResourceSpan: arena='%s', base=0x%x, size=0x%x", - pArena->name, base, uSize)); - - pSpanStart = _BuildSpanMarker (base, uSize); - if (pSpanStart == IMG_NULL) - { - goto fail_start; - } - -#if defined(VALIDATE_ARENA_TEST) - pSpanStart->eResourceSpan = IMPORTED_RESOURCE_SPAN_START; - pSpanStart->eResourceType = IMPORTED_RESOURCE_TYPE; -#endif - - pSpanEnd = _BuildSpanMarker (base + uSize, 0); - if (pSpanEnd == IMG_NULL) - { - goto fail_end; - } - -#if defined(VALIDATE_ARENA_TEST) - pSpanEnd->eResourceSpan = IMPORTED_RESOURCE_SPAN_END; - pSpanEnd->eResourceType = IMPORTED_RESOURCE_TYPE; -#endif - - pBT = _BuildBT (base, uSize); - if (pBT == IMG_NULL) - { - goto fail_bt; - } - -#if defined(VALIDATE_ARENA_TEST) - pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE; - pBT->eResourceType = IMPORTED_RESOURCE_TYPE; -#endif - - eError = _SegmentListInsert (pArena, pSpanStart); - if (eError != PVRSRV_OK) - { - goto fail_SegListInsert; - } - - eError = _SegmentListInsertAfter (pArena, pSpanStart, pBT); - if (eError != PVRSRV_OK) - { - goto fail_SegListInsert; - } - - _FreeListInsert (pArena, pBT); - - eError = _SegmentListInsertAfter (pArena, pBT, pSpanEnd); - if (eError != PVRSRV_OK) - { - goto fail_SegListInsert; - } - -#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_SegListInsert: - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL); - /*not nulling pointer, out of scope*/ - fail_bt: - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanEnd, IMG_NULL); - /*not nulling pointer, out of scope*/ - fail_end: - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanStart, IMG_NULL); - /*not nulling pointer, out of scope*/ - fail_start: - return IMG_NULL; -} - -/*! -****************************************************************************** - @Function _FreeBT - - @Description Free a boundary tag taking care of the segment list and the - boundary tag free table. - - @Input pArena - the arena. - @Input pBT - the boundary tag to free. - @Input bFreeBackingStore - Should backing for the memory be freed - as well. - @Return None -******************************************************************************/ -static IMG_VOID -_FreeBT (RA_ARENA *pArena, BT *pBT, IMG_BOOL bFreeBackingStore) -{ - BT *pNeighbour; - IMG_UINTPTR_T uOrigBase; - IMG_SIZE_T uOrigSize; - - PVR_ASSERT (pArena!=IMG_NULL); - PVR_ASSERT (pBT!=IMG_NULL); - - if ((pArena == IMG_NULL) || (pBT == IMG_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; - - /* 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; - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL); - /*not nulling original pointer, already overwritten*/ -#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; - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL); - /*not nulling original pointer, already overwritten*/ -#ifdef RA_STATS - pArena->sStatistics.uFreeSegmentCount--; -#endif - } - - /* try to free backing store memory. */ - if (pArena->pBackingStoreFree != IMG_NULL && bFreeBackingStore) - { - IMG_UINTPTR_T uRoundedStart, uRoundedEnd; - - /* Work out the first address we might be able to free. */ - uRoundedStart = (uOrigBase / pArena->uQuantum) * pArena->uQuantum; - /* If a span is still using that address then leave it. */ - if (uRoundedStart < pBT->base) - { - uRoundedStart += pArena->uQuantum; - } - - /* Work out the last address we might be able to free. */ - uRoundedEnd = ((uOrigBase + uOrigSize + pArena->uQuantum - 1) / pArena->uQuantum) * pArena->uQuantum; - /* If a span is still using that addres then leave it. */ - if (uRoundedEnd > (pBT->base + pBT->uSize)) - { - uRoundedEnd -= pArena->uQuantum; - } - - if (uRoundedStart < uRoundedEnd) - { - pArena->pBackingStoreFree(pArena->pImportHandle, (IMG_SIZE_T)uRoundedStart, (IMG_SIZE_T)uRoundedEnd, (IMG_HANDLE)0); - } - } - - 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->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(BT), next, IMG_NULL); - /*not nulling original pointer, already overwritten*/ - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), prev, IMG_NULL); - /*not nulling original pointer, already overwritten*/ - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL); - /*not nulling pointer, copy on stack*/ - } - else - _FreeListInsert (pArena, pBT); -} - - -/*! -****************************************************************************** - @Function _AttemptAllocAligned - - @Description Attempt an allocation from an arena. - - @Input pArena - the arena. - @Input uSize - the requested allocation size. - @Output ppsMapping - the user references associated with - the allocated segment. - @Input flags - allocation flags - @Input uAlignment - required uAlignment, or 0 - @Input uAlignmentOffset - @Output base - allocated resource base - - @Return IMG_FALSE failure - IMG_TRUE success -******************************************************************************/ -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; - - /* search for a near fit free boundary tag, start looking at the - pvr_log2 free table for our required size and work on up the - table. */ - uIndex = pvr_log2 (uSize); - - 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) - { - 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 - - /* with uAlignment we might need to discard the front of this segment */ - if (aligned_base > pBT->base) - { - BT *pNeighbour; - pNeighbour = _SegmentSplit (pArena, pBT, (IMG_SIZE_T)(aligned_base - pBT->base)); - /* partition the buffer, create a new boundary tag */ - if (pNeighbour==IMG_NULL) - { - PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Front split failed")); - /* Put pBT back in the list */ - _FreeListInsert (pArena, pBT); - 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) - { - PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Back split failed")); - /* Put pBT back in the list */ - _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; -} - - - -/*! -****************************************************************************** - @Function RA_Create - - @Description To create a resource arena. - - @Input name - the name of the arena for diagnostic purposes. - @Input base - the base of an initial resource span or 0. - @Input uSize - the size of an initial resource span or 0. - @Input uQuantum - the arena allocation quantum. - @Input alloc - a resource allocation callback or 0. - @Input free - a resource de-allocation callback or 0. - @Input backingstore_free - a callback to free resources for spans or 0. - @Input pImportHandle - handle passed to alloc and free or 0. - - @Return arena handle, or IMG_NULL. -******************************************************************************/ -RA_ARENA * -RA_Create (IMG_CHAR *name, - IMG_UINTPTR_T base, - IMG_SIZE_T uSize, - BM_MAPPING *psMapping, - IMG_SIZE_T uQuantum, - IMG_BOOL (*imp_alloc)(IMG_VOID *, IMG_SIZE_T uSize, IMG_SIZE_T *pActualSize, - BM_MAPPING **ppsMapping, IMG_UINT32 _flags, - IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength, - IMG_UINTPTR_T *pBase), - IMG_VOID (*imp_free) (IMG_VOID *, IMG_UINTPTR_T, BM_MAPPING *), - IMG_VOID (*backingstore_free) (IMG_VOID*, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE), - IMG_VOID *pImportHandle) -{ - RA_ARENA *pArena; - BT *pBT; - IMG_INT i; - - PVR_DPF ((PVR_DBG_MESSAGE, - "RA_Create: name='%s', base=0x%x, uSize=0x%x, alloc=0x%x, free=0x%x", - name, base, uSize, (IMG_UINTPTR_T)imp_alloc, (IMG_UINTPTR_T)imp_free)); - - - if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, - sizeof (*pArena), - (IMG_VOID **)&pArena, IMG_NULL, - "Resource Arena") != PVRSRV_OK) - { - goto arena_fail; - } - - pArena->name = name; - pArena->pImportAlloc = (imp_alloc!=IMG_NULL) ? imp_alloc : &_RequestAllocFail; - pArena->pImportFree = imp_free; - pArena->pBackingStoreFree = backingstore_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; - -#ifdef RA_STATS - OSMemSet(&pArena->sStatistics, 0x00, sizeof(pArena->sStatistics)); -#endif - -#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS) - if(strcmp(pArena->name,"") != 0) - { - IMG_INT ret; - IMG_CHAR szProcInfoName[PROC_NAME_SIZE]; - IMG_CHAR szProcSegsName[PROC_NAME_SIZE]; - struct proc_dir_entry* (*pfnCreateProcEntrySeq)(const IMG_CHAR *, - IMG_VOID*, - pvr_next_proc_seq_t, - pvr_show_proc_seq_t, - pvr_off2element_proc_seq_t, - pvr_startstop_proc_seq_t, - write_proc_t); - - pArena->bInitProcEntry = !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL); - - /* Don't put shared heap info into a per process /proc subdirectory */ - pfnCreateProcEntrySeq = pArena->bInitProcEntry ? CreateProcEntrySeq : CreatePerProcessProcEntrySeq; - - ret = snprintf(szProcInfoName, sizeof(szProcInfoName), "ra_info_%s", pArena->name); - if (ret > 0 && ret < sizeof(szProcInfoName)) - { - pArena->pProcInfo = pfnCreateProcEntrySeq(ReplaceSpaces(szProcInfoName), pArena, NULL, - RA_ProcSeqShowInfo, RA_ProcSeqOff2ElementInfo, NULL, NULL); - } - else - { - pArena->pProcInfo = 0; - PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_info proc entry for arena %s", pArena->name)); - } - - ret = snprintf(szProcSegsName, sizeof(szProcSegsName), "ra_segs_%s", pArena->name); - if (ret > 0 && ret < sizeof(szProcSegsName)) - { - pArena->pProcSegs = pfnCreateProcEntrySeq(ReplaceSpaces(szProcSegsName), pArena, NULL, - RA_ProcSeqShowRegs, RA_ProcSeqOff2ElementRegs, NULL, NULL); - } - else - { - pArena->pProcSegs = 0; - PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_segs proc entry for arena %s", pArena->name)); - } - -#if defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG) - pArena->uAllocFailThreshold = ~0; - pArena->uAllocFailMask = ~0; - pArena->bFailAllocationOnce = IMG_FALSE; - pArena->bFailAllocationPersist = IMG_FALSE; - - ret = snprintf(szProcSegsName, sizeof(szProcSegsName), "ra_fail_alloc_thld_%s", pArena->name); - if (ret > 0 && ret < sizeof(szProcSegsName)) - { - pArena->pProcAllocFailThreshold = pfnCreateProcEntrySeq(ReplaceSpaces(szProcSegsName), pArena, NULL, - RA_ProcSeqShowAllocFailThreshold, RA_ProcSeqOff2AllocFailThreshold, NULL, RA_ProcSetAllocFailThreshold); - } - else - { - pArena->pProcAllocFailThreshold = 0; - PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_fail_alloc_thld proc entry for arena %s", pArena->name)); - } -#endif //defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG) - } -#endif /* defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS) */ - - pArena->pSegmentHash = HASH_Create (MINIMUM_HASH_SIZE); - if (pArena->pSegmentHash==IMG_NULL) - { - goto hash_fail; - } - if (uSize>0) - { - uSize = (uSize + uQuantum - 1) / uQuantum * uQuantum; - pBT = _InsertResource (pArena, base, uSize); - if (pBT == IMG_NULL) - { - goto insert_fail; - } - pBT->psMapping = psMapping; - - } - return pArena; - -insert_fail: - HASH_Delete (pArena->pSegmentHash); -hash_fail: - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL); - /*not nulling pointer, out of scope*/ -arena_fail: - return IMG_NULL; -} - -/*! -****************************************************************************** - @Function RA_Delete - - @Description To delete a resource arena. All resources allocated from - the arena must be freed before deleting the arena. - - @Input pArena - the arena to delete. - - @Return None -******************************************************************************/ -IMG_VOID -RA_Delete (RA_ARENA *pArena) -{ - IMG_UINT32 uIndex; - - PVR_ASSERT(pArena != IMG_NULL); - - if (pArena == IMG_NULL) - { - PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: invalid parameter - pArena")); - return; - } - - PVR_DPF ((PVR_DBG_MESSAGE, - "RA_Delete: name='%s'", pArena->name)); - - for (uIndex=0; uIndex<FREE_TABLE_LIMIT; uIndex++) - pArena->aHeadFree[uIndex] = IMG_NULL; - - while (pArena->pHeadSegment != IMG_NULL) - { - BT *pBT = pArena->pHeadSegment; - - if (pBT->type != btt_free) - { - PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: allocations still exist in the arena that is being destroyed")); - PVR_DPF ((PVR_DBG_ERROR,"Likely Cause: client drivers not freeing allocations before destroying devmemcontext")); - PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: base = 0x%x size=0x%x", pBT->base, pBT->uSize)); - } - - _SegmentListRemove (pArena, pBT); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL); - /*not nulling original pointer, it has changed*/ -#ifdef RA_STATS - pArena->sStatistics.uSpanCount--; -#endif - } -#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS) - { - IMG_VOID (*pfnRemoveProcEntrySeq)(struct proc_dir_entry*); - - pfnRemoveProcEntrySeq = pArena->bInitProcEntry ? RemoveProcEntrySeq : RemovePerProcessProcEntrySeq; - - if (pArena->pProcInfo != 0) - { - pfnRemoveProcEntrySeq( pArena->pProcInfo ); - } - - if (pArena->pProcSegs != 0) - { - pfnRemoveProcEntrySeq( pArena->pProcSegs ); - } - -#if defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG) - if(pArena->pProcAllocFailThreshold != 0) - { - pfnRemoveProcEntrySeq( pArena->pProcAllocFailThreshold ); - } -#endif //defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG) - } -#endif - HASH_Delete (pArena->pSegmentHash); - OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL); - /*not nulling pointer, copy on stack*/ -} - -/*! -****************************************************************************** - @Function RA_TestDelete - - @Description To test whether it is safe to delete a resource arena. If any - allocations have not been freed, the RA must not be deleted. - - @Input pArena - the arena to test. - - @Return IMG_BOOL - IMG_TRUE if is safe to go on and call RA_Delete. -******************************************************************************/ -IMG_BOOL -RA_TestDelete (RA_ARENA *pArena) -{ - PVR_ASSERT(pArena != IMG_NULL); - - if (pArena != IMG_NULL) - { - while (pArena->pHeadSegment != IMG_NULL) - { - BT *pBT = pArena->pHeadSegment; - if (pBT->type != btt_free) - { - PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: detected resource leak!")); - PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: base = 0x%x size=0x%x", pBT->base, pBT->uSize)); - return IMG_FALSE; - } - } - } - - return IMG_TRUE; -} - -/*! -****************************************************************************** - @Function RA_Add - - @Description To add a resource span to an arena. The span must not - overlapp with any span previously added to the arena. - - @Input pArena - the arena to add a span into. - @Input base - the base of the span. - @Input uSize - the extent of the span. - - @Return IMG_TRUE - Success - IMG_FALSE - failure -******************************************************************************/ -IMG_BOOL -RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize) -{ - PVR_ASSERT (pArena != IMG_NULL); - - if (pArena == IMG_NULL) - { - PVR_DPF ((PVR_DBG_ERROR,"RA_Add: invalid parameter - pArena")); - return IMG_FALSE; - } - - PVR_DPF ((PVR_DBG_MESSAGE, - "RA_Add: name='%s', base=0x%x, size=0x%x", pArena->name, base, uSize)); - - uSize = (uSize + pArena->uQuantum - 1) / pArena->uQuantum * pArena->uQuantum; - return ((IMG_BOOL)(_InsertResource (pArena, base, uSize) != IMG_NULL)); -} - -/*! -****************************************************************************** - @Function RA_Alloc - - @Description To allocate resource from an arena. - - @Input pArena - the arena - @Input uRequestSize - the size of resource segment requested. - @Output pActualSize - the actual size of resource segment - allocated, typcially rounded up by quantum. - @Output ppsMapping - the user reference associated with allocated resource span. - @Input uFlags - flags influencing allocation policy. - @Input uAlignment - the uAlignment constraint required for the - allocated segment, use 0 if uAlignment not required. - @Input uAlignmentOffset - @Input pvPrivData - opaque private data passed through to allocator - @Input ui32PrivDataLength - length of opaque private data - - @Output base - allocated base resource - - @Return IMG_TRUE - success - IMG_FALSE - failure -******************************************************************************/ -IMG_BOOL -RA_Alloc (RA_ARENA *pArena, - IMG_SIZE_T uRequestSize, - IMG_SIZE_T *pActualSize, - BM_MAPPING **ppsMapping, - IMG_UINT32 uFlags, - IMG_UINT32 uAlignment, - IMG_UINT32 uAlignmentOffset, - IMG_PVOID pvPrivData, - IMG_UINT32 ui32PrivDataLength, - IMG_UINTPTR_T *base) -{ - IMG_BOOL bResult = IMG_FALSE; - IMG_BOOL bTestAllocFail = IMG_FALSE; - IMG_SIZE_T uSize = uRequestSize; - - PVR_ASSERT (pArena!=IMG_NULL); - - if (pArena == IMG_NULL) - { - PVR_DPF ((PVR_DBG_ERROR,"RA_Alloc: invalid parameter - pArena")); - return IMG_FALSE; - } - -#if defined(VALIDATE_ARENA_TEST) - ValidateArena(pArena); -#endif - -#ifdef USE_BM_FREESPACE_CHECK - CheckBMFreespace(); -#endif - - if (pActualSize != IMG_NULL) - { - *pActualSize = uSize; - } - - PVR_DPF ((PVR_DBG_MESSAGE, - "RA_Alloc: arena='%s', size=0x%x(0x%x), alignment=0x%x, offset=0x%x", - pArena->name, uSize, uRequestSize, uAlignment, uAlignmentOffset)); - - bTestAllocFail = RA_TestAllocationFail(pArena, uSize, ~0); - if(!bTestAllocFail) - { - /* 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, ppsMapping, uFlags, - uAlignment, uAlignmentOffset, base); - if (!bResult) - { - BM_MAPPING *psImportMapping; - IMG_UINTPTR_T import_base; - IMG_SIZE_T uImportSize = uSize; - - /* - Ensure that we allocate sufficient space to meet the uAlignment - constraint - */ - if (uAlignment > pArena->uQuantum) - { - uImportSize += (uAlignment - 1); - } - - /* ensure that we import according to the quanta of this arena */ - uImportSize = ((uImportSize + pArena->uQuantum - 1)/pArena->uQuantum)*pArena->uQuantum; - - bResult = - pArena->pImportAlloc (pArena->pImportHandle, uImportSize, &uImportSize, - &psImportMapping, uFlags, - pvPrivData, ui32PrivDataLength, &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, - psImportMapping); - PVR_DPF ((PVR_DBG_MESSAGE, - "RA_Alloc: name='%s', size=0x%x failed!", - pArena->name, uSize)); - /* RA_Dump (arena); */ - return IMG_FALSE; - } - pBT->psMapping = psImportMapping; - #ifdef RA_STATS - pArena->sStatistics.uFreeSegmentCount++; - pArena->sStatistics.uFreeResourceCount += uImportSize; - pArena->sStatistics.uImportCount++; - pArena->sStatistics.uSpanCount++; - #endif - bResult = _AttemptAllocAligned(pArena, uSize, ppsMapping, uFlags, - uAlignment, uAlignmentOffset, - base); - if (!bResult) - { - PVR_DPF ((PVR_DBG_ERROR, - "RA_Alloc: name='%s' uAlignment failed!", - pArena->name)); - } - } - } - #ifdef RA_STATS - if (bResult) - pArena->sStatistics.uCumulativeAllocs++; - #endif - } - - PVR_DPF((PVR_DBG_MESSAGE, - "RA_Alloc: arena=%s, size=0x%x(0x%x), alignment=0x%x, "\ - "offset=0x%x, result=%d", - pArena->name, - uSize, uRequestSize, uAlignment, uAlignmentOffset, - bResult)); - - /* RA_Dump (pArena); - ra_stats (pArena); - */ - - if (!bResult) { - PVR_LOG(("RA_Alloc %s %s: arena=%s, size=0x%x(0x%x), "\ - "alignment=0x%x, offset=0x%x", - (bResult ? "SUCCESS" : "FAILED"), - (bTestAllocFail ? "in TEST_MODE!" : " "), - pArena->name, - uSize, uRequestSize, uAlignment, uAlignmentOffset)); - RA_DumpHeapInfo(pArena, ~0); - } -#if defined(VALIDATE_ARENA_TEST) - ValidateArena(pArena); -#endif - - return bResult; -} - - -#if defined(VALIDATE_ARENA_TEST) - -/*! -****************************************************************************** - @Function ValidateArena - - @Description Validate an arena by checking that adjacent members of the - double linked ordered list are compatible. PVR_DBG_BREAK and - PVR_DPF messages are used when an error is detected. - NOTE: A DEBUG build is required for PVR_DBG_BREAK and PVR_DPF - to operate. - - @Input pArena - the arena - - @Return 0 -******************************************************************************/ -IMG_UINT32 ValidateArena(RA_ARENA *pArena) -{ - BT* pSegment; - RESOURCE_DESCRIPTOR eNextSpan; - - pSegment = pArena->pHeadSegment; - - if (pSegment == IMG_NULL) - { - return 0; - } - - if (pSegment->eResourceType == IMPORTED_RESOURCE_TYPE) - { - PVR_ASSERT(pSegment->eResourceSpan == IMPORTED_RESOURCE_SPAN_START); - - while (pSegment->pNextSegment) - { - eNextSpan = pSegment->pNextSegment->eResourceSpan; - - switch (pSegment->eResourceSpan) - { - case IMPORTED_RESOURCE_SPAN_LIVE: - - if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) || - (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) || - (eNextSpan == IMPORTED_RESOURCE_SPAN_END))) - { - /* error - next span must be live, free or end */ - PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", - pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); - - PVR_DBG_BREAK; - } - break; - - case IMPORTED_RESOURCE_SPAN_FREE: - - if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) || - (eNextSpan == IMPORTED_RESOURCE_SPAN_END))) - { - /* error - next span must be live or end */ - PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", - pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); - - PVR_DBG_BREAK; - } - break; - - case IMPORTED_RESOURCE_SPAN_END: - - if ((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) || - (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) || - (eNextSpan == IMPORTED_RESOURCE_SPAN_END)) - { - /* error - next span cannot be live, free or end */ - PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", - pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); - - PVR_DBG_BREAK; - } - break; - - - case IMPORTED_RESOURCE_SPAN_START: - - if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) || - (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE))) - { - /* error - next span must be live or free */ - PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", - pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); - - PVR_DBG_BREAK; - } - break; - - default: - PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", - pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); - - PVR_DBG_BREAK; - break; - } - pSegment = pSegment->pNextSegment; - } - } - else if (pSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE) - { - PVR_ASSERT((pSegment->eResourceSpan == RESOURCE_SPAN_FREE) || (pSegment->eResourceSpan == RESOURCE_SPAN_LIVE)); - - while (pSegment->pNextSegment) - { - eNextSpan = pSegment->pNextSegment->eResourceSpan; - - switch (pSegment->eResourceSpan) - { - case RESOURCE_SPAN_LIVE: - - if (!((eNextSpan == RESOURCE_SPAN_FREE) || - (eNextSpan == RESOURCE_SPAN_LIVE))) - { - /* error - next span must be free or live */ - PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", - pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); - - PVR_DBG_BREAK; - } - break; - - case RESOURCE_SPAN_FREE: - - if (!((eNextSpan == RESOURCE_SPAN_FREE) || - (eNextSpan == RESOURCE_SPAN_LIVE))) - { - /* error - next span must be free or live */ - PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", - pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); - - PVR_DBG_BREAK; - } - break; - - default: - PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)", - pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name)); - - PVR_DBG_BREAK; - break; - } - pSegment = pSegment->pNextSegment; - } - - } - else - { - PVR_DPF ((PVR_DBG_ERROR,"ValidateArena ERROR: pSegment->eResourceType unrecognized")); - - PVR_DBG_BREAK; - } - - return 0; -} - -#endif - - -/*! -****************************************************************************** - @Function RA_Free - - @Description To free a resource segment. - - @Input pArena - the arena the segment was originally allocated from. - @Input base - the base of the resource span to free. - @Input bFreeBackingStore - Should backing store memory be freed. - - @Return None -******************************************************************************/ -IMG_VOID -RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore) -{ - BT *pBT; - - PVR_ASSERT (pArena != IMG_NULL); - - if (pArena == IMG_NULL) - { - PVR_DPF ((PVR_DBG_ERROR,"RA_Free: invalid parameter - pArena")); - return; - } - -#ifdef USE_BM_FREESPACE_CHECK - CheckBMFreespace(); -#endif - - PVR_DPF ((PVR_DBG_MESSAGE, - "RA_Free: name='%s', base=0x%x", 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 - -#ifdef USE_BM_FREESPACE_CHECK -{ - IMG_BYTE* p; - IMG_BYTE* endp; - - p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset(); - endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize)); - while ((IMG_UINT32)p & 3) - { - *p++ = 0xAA; - } - while (p < (IMG_BYTE*)((IMG_UINT32)endp & 0xfffffffc)) - { - *(IMG_UINT32*)p = 0xAAAAAAAA; - p += sizeof(IMG_UINT32); - } - while (p < endp) - { - *p++ = 0xAA; - } - PVR_DPF((PVR_DBG_MESSAGE,"BM_FREESPACE_CHECK: RA_Free Cleared %08X to %08X (size=0x%x)",(IMG_BYTE*)pBT->base + SysGetDevicePhysOffset(),endp-1,pBT->uSize)); -} -#endif - _FreeBT (pArena, pBT, bFreeBackingStore); - } -} - - -/*! -****************************************************************************** - @Function RA_GetNextLiveSegment - - @Description Returns details of the next live resource segments - - @Input pArena - the arena the segment was originally allocated from. - @InOut psSegDetails - rtn details of segments - - @Return IMG_TRUE if operation succeeded -******************************************************************************/ -IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails) -{ - BT *pBT; - - if (psSegDetails->hSegment) - { - pBT = (BT *)psSegDetails->hSegment; - } - else - { - RA_ARENA *pArena = (RA_ARENA *)hArena; - - pBT = pArena->pHeadSegment; - } - /* walk the arena segments and write live one to the buffer */ - while (pBT != IMG_NULL) - { - if (pBT->type == btt_live) - { - psSegDetails->uiSize = pBT->uSize; - psSegDetails->sCpuPhyAddr.uiAddr = pBT->base; - psSegDetails->hSegment = (IMG_HANDLE)pBT->pNextSegment; - - return IMG_TRUE; - } - - pBT = pBT->pNextSegment; - } - - psSegDetails->uiSize = 0; - psSegDetails->sCpuPhyAddr.uiAddr = 0; - psSegDetails->hSegment = (IMG_HANDLE)IMG_UNDEF; - - return IMG_FALSE; -} - - -#ifdef USE_BM_FREESPACE_CHECK -RA_ARENA* pJFSavedArena = IMG_NULL; - -IMG_VOID CheckBMFreespace(IMG_VOID) -{ - BT *pBT; - IMG_BYTE* p; - IMG_BYTE* endp; - - if (pJFSavedArena != IMG_NULL) - { - for (pBT=pJFSavedArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment) - { - if (pBT->type == btt_free) - { - p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset(); - endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize) & 0xfffffffc); - - while ((IMG_UINT32)p & 3) - { - if (*p++ != 0xAA) - { - fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p); - for (;;); - break; - } - } - while (p < endp) - { - if (*(IMG_UINT32*)p != 0xAAAAAAAA) - { - fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p); - for (;;); - break; - } - p += 4; - } - } - } - } -} -#endif - - -#if (defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS)) || defined (RA_STATS) -static IMG_CHAR * -_BTType (IMG_INT eType) -{ - switch (eType) - { - case btt_span: return "span"; - case btt_free: return "free"; - case btt_live: return "live"; - } - return "junk"; -} -#endif /*defined(CONFIG_PROC_FS) && defined(DEBUG)*/ - -#if defined(ENABLE_RA_DUMP) -/*! -****************************************************************************** - @Function RA_Dump - - @Description To dump a readable description of an arena. Diagnostic only. - - @Input pArena - the arena to dump. - - @Return None -******************************************************************************/ -IMG_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=%08X free=%08X handle=%08X 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%x size=0x%x type=%s", - (IMG_UINT32) pBT->base, pBT->uSize, _BTType (pBT->type))); - } - -#ifdef HASH_TRACE - HASH_Dump (pArena->pSegmentHash); -#endif -} -#endif /* #if defined(ENABLE_RA_DUMP) */ - -static PVRSRV_ERROR RA_DumpHeapInfo(RA_ARENA *pArena, IMG_UINT32 ui32DebugLevel) -{ - BT *pBT; - - { - IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM(); - IMG_CHAR dirname_buffer[256]; - IMG_CHAR dirname[256]; - const IMG_CHAR *proc_basename = dirname_buffer; - dirname_buffer[255] = dirname[255] = '\0'; - - OSGetProcCmdline(ui32PID, dirname_buffer, sizeof(dirname_buffer)); - PVR_LOG(("\nCommand Line of the current process with ID %u is %s", ui32PID, dirname_buffer)); - - proc_basename = OSGetPathBaseName(dirname_buffer, sizeof(dirname_buffer)); - PVR_LOG(("Base Name of the current process with ID %u is %s", ui32PID, proc_basename)); - - } - - PVR_LOG(("Arena '%s':", pArena->name)); - - PVR_LOG(( " allocCB=%p freeCB=%p handle=%p quantum=%d", - pArena->pImportAlloc, - pArena->pImportFree, - pArena->pImportHandle, - pArena->uQuantum)); - - PVR_LOG(( "span count\t\t%u", pArena->sStatistics.uSpanCount)); - - PVR_LOG(( "live segment count\t%u", pArena->sStatistics.uLiveSegmentCount)); - - PVR_LOG(( "free segment count\t%u", pArena->sStatistics.uFreeSegmentCount)); - - PVR_LOG(( "free resource count\t%u (0x%x)", - pArena->sStatistics.uFreeResourceCount, - (IMG_UINT)pArena->sStatistics.uFreeResourceCount)); - - PVR_LOG(( "total allocs\t\t%u", pArena->sStatistics.uCumulativeAllocs)); - - PVR_LOG(( "total failed allocs\t%u", pArena->sStatistics.uFailedAllocCount)); - - PVR_LOG(( "total frees\t\t%u", pArena->sStatistics.uCumulativeFrees)); - - PVR_LOG(( "import count\t\t%u", pArena->sStatistics.uImportCount)); - - PVR_LOG(( "export count\t\t%u", pArena->sStatistics.uExportCount)); - - PVR_LOG(( " segment Chain:")); - - if (pArena->pHeadSegment != IMG_NULL && - pArena->pHeadSegment->pPrevSegment != IMG_NULL) - { - PVR_LOG(( " error: head boundary tag has invalid pPrevSegment")); - } - - if (pArena->pTailSegment != IMG_NULL && - pArena->pTailSegment->pNextSegment != IMG_NULL) - { - PVR_LOG(( " error: tail boundary tag has invalid pNextSegment")); - } - - for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment) - { - PVR_LOG(( "%s base=0x%08x size=%08d(0x%08x) type=%s ref=%p", - ((pBT->type == btt_span) ? "\t\t" : "\t"), - (IMG_UINT32) pBT->base, - pBT->uSize, pBT->uSize, - _BTType(pBT->type), - pBT->psMapping)); - if(pBT->psMapping) - { - BM_MAPPING *psImportMapping = pBT->psMapping; - PVR_LOG(( "\t %p: mapping type %s, mapping count=%d, size=%08d(0x%08x), flags=0x%08x, align=0x%04x", - psImportMapping, - _BMMappingType(psImportMapping->eCpuMemoryOrigin), - psImportMapping->ui32MappingCount, - psImportMapping->uSize, psImportMapping->uSize, - psImportMapping->ui32Flags, - psImportMapping->ui32DevVAddrAlignment)); - } - } - - return PVRSRV_OK; -} - -#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS) - -#if defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG) -#define _PROC_SET_ALLOC_TH_BUFFER_SZ 32 -static int RA_ProcSetAllocFailThreshold(struct file *file, const char __user *buffer, unsigned long count, void *data) -{ - PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)data; - RA_ARENA *pArena; - IMG_CHAR data_buffer[_PROC_SET_ALLOC_TH_BUFFER_SZ]; - IMG_INT32 value = ~0; - IMG_UINT32 mask = ~0; - IMG_INT32 format_ret; - - if ((handlers == NULL) || (handlers->data == NULL) || (count > sizeof(data_buffer))) - { - return -EINVAL; - } - - pArena = (RA_ARENA *)handlers->data; - - count = MIN(count, sizeof(data_buffer)); - - if (pvr_copy_from_user(data_buffer, buffer, count)) - return -EINVAL; - - if (data_buffer[count - 1] != '\n') - return -EINVAL; - - data_buffer[(sizeof(data_buffer) - 1)] = '\0'; - if((sizeof(data_buffer) -1) <= count) - data_buffer[count] = '\0'; - - PVR_LOG(("Buffer from the user is %s\n", data_buffer)); - format_ret = sscanf(data_buffer, "%i:0x%x", &value, &mask); - PVR_LOG(("Value set is %i, type is %x, format %i\n", value, mask, format_ret)); - if(format_ret <= 0) - return -EINVAL; - -/* - Heap Allocation Buffer Threshold Setting - for testing purposes only - Causes allocation of a GFX buffer of type MASK for the respective heap to - fail. - Format is <threshold value number>:<buffer type mask hex value> - for example: 1000:0x01. - Value of -1 disables the allocation fail test - Value bigger than and eq. to 0 enables the allocation fail test for - the first buffer only. - Value smaller than -1 enables the buffer allocation failure for this - heap until the test disables it. -*/ - if(value < 0) - { - if(value == -1) - { - pArena->bFailAllocationPersist = pArena->bFailAllocationOnce = IMG_FALSE; - } - else if(value == -2) - { - RA_DumpHeapInfo(pArena, ~0); - } - else - { - pArena->bFailAllocationPersist = pArena->bFailAllocationOnce = IMG_TRUE; - pArena->uAllocFailThreshold = -value; - } - } - else - { - pArena->bFailAllocationPersist = 0; - pArena->bFailAllocationOnce = 1; - pArena->uAllocFailThreshold = value; - } - - if(format_ret > 1) - { - if((pArena->bFailAllocationOnce == IMG_TRUE) && (mask == 0)) - pArena->uAllocFailMask = ~0; - else - pArena->uAllocFailMask = mask; - } - PVR_LOG(("*************** User Fail Heap Allocation Settings for %s *******************************\n", - pArena->name)); - PVR_LOG(("Fail Heap Allocation is %s in %s mode\n", (pArena->bFailAllocationOnce ? "Enabled": "Disabled"), - (pArena->bFailAllocationPersist ? "Persistent": "One-Shot"))); - PVR_LOG(("Fail Heap Allocation Buffer Size Threshold is %u with a Mask of 0x%x\n", - pArena->uAllocFailThreshold, pArena->uAllocFailMask)); - PVR_LOG(("*******************************************************************************************\n")); - return (count); -} - -static void* RA_ProcSeqOff2AllocFailThreshold(struct seq_file * sfile, loff_t off) -{ - - if(off <= 1) - return (void*)(IMG_INT)(off+1); - - return 0; -} - -static void RA_ProcSeqShowAllocFailThreshold(struct seq_file *sfile,void* el) -{ - PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private; - RA_ARENA *pArena = (RA_ARENA *)handlers->data; - IMG_INT off = (IMG_INT)el; - - switch (off) - { - case 1: - seq_printf(sfile, "Heap Allocation Buffer Threshold Setting - for testing purposes only\n"); - seq_printf(sfile, "Format is <threshold value number>:<buffer type mask hex value> for example: 1000:0x01\n"); - seq_printf(sfile, "Value of -1 disables the allocation fail test\n"); - seq_printf(sfile, "Value of -2 dumps the heap entries to the kernel log\n"); - seq_printf(sfile, "Value => 0 enables the allocation fail test for the first buffer with the met threshold only\n"); - seq_printf(sfile, "Value < -2 enables the buffer allocation failure for this heap until the test disables it\n"); - break; - case 2: - seq_printf(sfile, "*********** Current Settings: ********************\n"); - seq_printf(sfile,"Fail Heap Allocation is %s in %s mode\n", (pArena->bFailAllocationOnce ? "Enabled": "Disabled"), - (pArena->bFailAllocationPersist ? "Persistent": "One-Shot")); - seq_printf(sfile, "Fail Heap Allocation Buffer Size Threshold is %u with a Mask of 0x%x\n", - pArena->uAllocFailThreshold, pArena->uAllocFailMask); - break; - } -} -#endif //defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG) - -static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el) -{ - PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private; - RA_ARENA *pArena = (RA_ARENA *)handlers->data; - IMG_INT off = (IMG_INT)el; - - switch (off) - { - case 1: - seq_printf(sfile, "quantum\t\t\t%u\n", pArena->uQuantum); - break; - case 2: - seq_printf(sfile, "import_handle\t\t%08X\n", (IMG_UINT)pArena->pImportHandle); - break; -#ifdef RA_STATS - case 3: - seq_printf(sfile,"span count\t\t%u\n", pArena->sStatistics.uSpanCount); - break; - case 4: - seq_printf(sfile, "live segment count\t%u\n", pArena->sStatistics.uLiveSegmentCount); - break; - case 5: - seq_printf(sfile, "free segment count\t%u\n", pArena->sStatistics.uFreeSegmentCount); - break; - case 6: - seq_printf(sfile, "free resource count\t%u (0x%x)\n", - pArena->sStatistics.uFreeResourceCount, - (IMG_UINT)pArena->sStatistics.uFreeResourceCount); - break; - case 7: - seq_printf(sfile, "total allocs\t\t%u\n", pArena->sStatistics.uCumulativeAllocs); - break; - case 8: - seq_printf(sfile, "total frees\t\t%u\n", pArena->sStatistics.uCumulativeFrees); - break; - case 9: - seq_printf(sfile, "import count\t\t%u\n", pArena->sStatistics.uImportCount); - break; - case 10: - seq_printf(sfile, "export count\t\t%u\n", pArena->sStatistics.uExportCount); - break; -#endif - } - -} - -static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off) -{ -#ifdef RA_STATS - if(off <= 9) -#else - if(off <= 1) -#endif - return (void*)(IMG_INT)(off+1); - return 0; -} - -static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el) -{ - PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private; - RA_ARENA *pArena = (RA_ARENA *)handlers->data; - BT *pBT = (BT*)el; - - if (el == PVR_PROC_SEQ_START_TOKEN) - { - seq_printf(sfile, "Arena \"%s\"\nBase Size Type Ref\n", pArena->name); - return; - } - - if (pBT) - { - seq_printf(sfile, "%08x %8x %4s %08x\n", - (IMG_UINT)pBT->base, (IMG_UINT)pBT->uSize, _BTType (pBT->type), - (IMG_UINT)pBT->psMapping); - } -} - -static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off) -{ - PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private; - RA_ARENA *pArena = (RA_ARENA *)handlers->data; - BT *pBT = 0; - - if(off == 0) - return PVR_PROC_SEQ_START_TOKEN; - - for (pBT=pArena->pHeadSegment; --off && pBT; pBT=pBT->pNextSegment); - - return (void*)pBT; -} - -#endif /* defined(CONFIG_PROC_FS) && defined(DEBUG) */ - - -#ifdef RA_STATS -/*! -****************************************************************************** - @Function RA_GetStats - - @Description Gets the arena stats and places in client buffer - - @Input pArena - the arena to print statistics for. - @Input ppszStr - caller string to fill - @Input pui32StrLen - length of caller string - - @Return PVRSRV_ERROR -******************************************************************************/ -PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena, - IMG_CHAR **ppszStr, - IMG_UINT32 *pui32StrLen) -{ - IMG_CHAR *pszStr = *ppszStr; - IMG_UINT32 ui32StrLen = *pui32StrLen; - IMG_INT32 i32Count; - BT *pBT; - - CHECK_SPACE(ui32StrLen); - i32Count = OSSNPrintf(pszStr, 100, "\nArena '%s':\n", pArena->name); - UPDATE_SPACE(pszStr, i32Count, ui32StrLen); - - - CHECK_SPACE(ui32StrLen); - i32Count = OSSNPrintf(pszStr, 100, " allocCB=%p freeCB=%p handle=%p quantum=%d\n", - pArena->pImportAlloc, - pArena->pImportFree, - pArena->pImportHandle, - pArena->uQuantum); - UPDATE_SPACE(pszStr, i32Count, ui32StrLen); - - CHECK_SPACE(ui32StrLen); - i32Count = OSSNPrintf(pszStr, 100, "span count\t\t%u\n", pArena->sStatistics.uSpanCount); - UPDATE_SPACE(pszStr, i32Count, ui32StrLen); - - CHECK_SPACE(ui32StrLen); - i32Count = OSSNPrintf(pszStr, 100, "live segment count\t%u\n", pArena->sStatistics.uLiveSegmentCount); - UPDATE_SPACE(pszStr, i32Count, ui32StrLen); - - CHECK_SPACE(ui32StrLen); - i32Count = OSSNPrintf(pszStr, 100, "free segment count\t%u\n", pArena->sStatistics.uFreeSegmentCount); - UPDATE_SPACE(pszStr, i32Count, ui32StrLen); - - CHECK_SPACE(ui32StrLen); - i32Count = OSSNPrintf(pszStr, 100, "free resource count\t%u (0x%x)\n", - pArena->sStatistics.uFreeResourceCount, - (IMG_UINT)pArena->sStatistics.uFreeResourceCount); - UPDATE_SPACE(pszStr, i32Count, ui32StrLen); - - CHECK_SPACE(ui32StrLen); - i32Count = OSSNPrintf(pszStr, 100, "total allocs\t\t%u\n", pArena->sStatistics.uCumulativeAllocs); - UPDATE_SPACE(pszStr, i32Count, ui32StrLen); - - CHECK_SPACE(ui32StrLen); - i32Count = OSSNPrintf(pszStr, 100, "total frees\t\t%u\n", pArena->sStatistics.uCumulativeFrees); - UPDATE_SPACE(pszStr, i32Count, ui32StrLen); - - CHECK_SPACE(ui32StrLen); - i32Count = OSSNPrintf(pszStr, 100, "import count\t\t%u\n", pArena->sStatistics.uImportCount); - UPDATE_SPACE(pszStr, i32Count, ui32StrLen); - - CHECK_SPACE(ui32StrLen); - i32Count = OSSNPrintf(pszStr, 100, "export count\t\t%u\n", pArena->sStatistics.uExportCount); - UPDATE_SPACE(pszStr, i32Count, ui32StrLen); - - CHECK_SPACE(ui32StrLen); - i32Count = OSSNPrintf(pszStr, 100, " segment Chain:\n"); - UPDATE_SPACE(pszStr, i32Count, ui32StrLen); - - if (pArena->pHeadSegment != IMG_NULL && - pArena->pHeadSegment->pPrevSegment != IMG_NULL) - { - CHECK_SPACE(ui32StrLen); - i32Count = OSSNPrintf(pszStr, 100, " error: head boundary tag has invalid pPrevSegment\n"); - UPDATE_SPACE(pszStr, i32Count, ui32StrLen); - } - - if (pArena->pTailSegment != IMG_NULL && - pArena->pTailSegment->pNextSegment != IMG_NULL) - { - CHECK_SPACE(ui32StrLen); - i32Count = OSSNPrintf(pszStr, 100, " error: tail boundary tag has invalid pNextSegment\n"); - UPDATE_SPACE(pszStr, i32Count, ui32StrLen); - } - - for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment) - { - CHECK_SPACE(ui32StrLen); - i32Count = OSSNPrintf(pszStr, 100, "\tbase=0x%x size=0x%x type=%s ref=%p\n", - (IMG_UINT32) pBT->base, - pBT->uSize, - _BTType(pBT->type), - pBT->psMapping); - UPDATE_SPACE(pszStr, i32Count, ui32StrLen); - } - - *ppszStr = pszStr; - *pui32StrLen = ui32StrLen; - - return PVRSRV_OK; -} - -PVRSRV_ERROR RA_GetStatsFreeMem(RA_ARENA *pArena, - IMG_CHAR **ppszStr, - IMG_UINT32 *pui32StrLen) -{ - IMG_CHAR *pszStr = *ppszStr; - IMG_UINT32 ui32StrLen = *pui32StrLen; - IMG_INT32 i32Count; - CHECK_SPACE(ui32StrLen); - i32Count = OSSNPrintf(pszStr, 100, "Bytes free: Arena %-30s: %u (0x%x)\n", pArena->name, - pArena->sStatistics.uFreeResourceCount, - pArena->sStatistics.uFreeResourceCount); - UPDATE_SPACE(pszStr, i32Count, ui32StrLen); - *ppszStr = pszStr; - *pui32StrLen = ui32StrLen; - - return PVRSRV_OK; -} -#endif - -/****************************************************************************** - End of file (ra.c) -******************************************************************************/ - - - - |