summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'omap5/sgx_src/eurasia_km/services4/srvkm/common/ra.c')
-rw-r--r--omap5/sgx_src/eurasia_km/services4/srvkm/common/ra.c2427
1 files changed, 0 insertions, 2427 deletions
diff --git a/omap5/sgx_src/eurasia_km/services4/srvkm/common/ra.c b/omap5/sgx_src/eurasia_km/services4/srvkm/common/ra.c
deleted file mode 100644
index da48939..0000000
--- a/omap5/sgx_src/eurasia_km/services4/srvkm/common/ra.c
+++ /dev/null
@@ -1,2427 +0,0 @@
1/*************************************************************************/ /*!
2@Title Resource Allocator
3@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
4@Description
5 Implements generic resource allocation. The resource
6 allocator was originally intended to manage address spaces in
7 practice the resource allocator is generic and can manages arbitrary
8 sets of integers.
9
10 Resources are allocated from arenas. Arena's can be created with an
11 initial span of resources. Further resources spans can be added to
12 arenas. A call back mechanism allows an arena to request further
13 resource spans on demand.
14
15 Each arena maintains an ordered list of resource segments each
16 described by a boundary tag. Each boundary tag describes a segment
17 of resources which are either 'free', available for allocation, or
18 'busy' currently allocated. Adjacent 'free' segments are always
19 coallesced to avoid fragmentation.
20
21 For allocation, all 'free' segments are kept on lists of 'free'
22 segments in a table index by pvr_log2(segment size). ie Each table index
23 n holds 'free' segments in the size range 2**(n-1) -> 2**n.
24
25 Allocation policy is based on an *almost* best fit
26 stratedy. Choosing any segment from the appropriate table entry
27 guarantees that we choose a segment which is with a power of 2 of
28 the size we are allocating.
29
30 Allocated segments are inserted into a self scaling hash table which
31 maps the base resource of the span to the relevant boundary
32 tag. This allows the code to get back to the bounary tag without
33 exporting explicit boundary tag references through the API.
34
35 Each arena has an associated quantum size, all allocations from the
36 arena are made in multiples of the basic quantum.
37
38 On resource exhaustion in an arena, a callback if provided will be
39 used to request further resources. Resouces spans allocated by the
40 callback mechanism are delimited by special boundary tag markers of
41 zero span, 'span' markers. Span markers are never coallesced. Span
42 markers are used to detect when an imported span is completely free
43 and can be deallocated by the callback mechanism.
44@License Dual MIT/GPLv2
45
46The contents of this file are subject to the MIT license as set out below.
47
48Permission is hereby granted, free of charge, to any person obtaining a copy
49of this software and associated documentation files (the "Software"), to deal
50in the Software without restriction, including without limitation the rights
51to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
52copies of the Software, and to permit persons to whom the Software is
53furnished to do so, subject to the following conditions:
54
55The above copyright notice and this permission notice shall be included in
56all copies or substantial portions of the Software.
57
58Alternatively, the contents of this file may be used under the terms of
59the GNU General Public License Version 2 ("GPL") in which case the provisions
60of GPL are applicable instead of those above.
61
62If you wish to allow use of your version of this file only under the terms of
63GPL, and not to allow others to use your version of this file under the terms
64of the MIT license, indicate your decision by deleting the provisions above
65and replace them with the notice and other provisions required by GPL as set
66out in the file called "GPL-COPYING" included in this distribution. If you do
67not delete the provisions above, a recipient may use your version of this file
68under the terms of either the MIT license or GPL.
69
70This License is also included in this distribution in the file called
71"MIT-COPYING".
72
73EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
74PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
75BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
76PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
77COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
78IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
79CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
80*/ /**************************************************************************/
81
82/* Issues:
83 * - flags, flags are passed into the resource allocator but are not currently used.
84 * - determination, of import size, is currently braindead.
85 * - debug code should be moved out to own module and #ifdef'd
86 */
87
88#include "services_headers.h"
89#include "hash.h"
90#include "ra.h"
91#include "buffer_manager.h"
92#include "osfunc.h"
93
94#if defined(__linux__) && defined(__KERNEL__)
95#include <linux/kernel.h>
96#include "pvr_uaccess.h"
97#include "proc.h"
98#include <linux/sched.h>
99#endif
100
101#ifdef USE_BM_FREESPACE_CHECK
102#include <stdio.h>
103#endif
104
105/* The initial, and minimum size of the live address -> boundary tag
106 structure hash table. The value 64 is a fairly arbitrary
107 choice. The hash table resizes on demand so the value choosen is
108 not critical. */
109#define MINIMUM_HASH_SIZE (64)
110
111#if defined(VALIDATE_ARENA_TEST)
112
113/* This test validates the doubly linked ordered list of boundary tags, by
114checking that adjacent members of the list have compatible eResourceSpan
115and eResourceType values. */
116
117typedef enum RESOURCE_DESCRIPTOR_TAG {
118
119 RESOURCE_SPAN_LIVE = 10,
120 RESOURCE_SPAN_FREE,
121 IMPORTED_RESOURCE_SPAN_START,
122 IMPORTED_RESOURCE_SPAN_LIVE,
123 IMPORTED_RESOURCE_SPAN_FREE,
124 IMPORTED_RESOURCE_SPAN_END,
125
126} RESOURCE_DESCRIPTOR;
127
128typedef enum RESOURCE_TYPE_TAG {
129
130 IMPORTED_RESOURCE_TYPE = 20,
131 NON_IMPORTED_RESOURCE_TYPE
132
133} RESOURCE_TYPE;
134
135
136static IMG_UINT32 ui32BoundaryTagID = 0;
137
138IMG_UINT32 ValidateArena(RA_ARENA *pArena);
139#endif
140
141/* boundary tags, used to describe a resource segment */
142struct _BT_
143{
144 enum bt_type
145 {
146 btt_span, /* span markers */
147 btt_free, /* free resource segment */
148 btt_live /* allocated resource segment */
149 } type;
150
151 /* The base resource and extent of this segment */
152 IMG_UINTPTR_T base;
153 IMG_SIZE_T uSize;
154
155 /* doubly linked ordered list of all segments within the arena */
156 struct _BT_ *pNextSegment;
157 struct _BT_ *pPrevSegment;
158 /* doubly linked un-ordered list of free segments. */
159 struct _BT_ *pNextFree;
160 struct _BT_ *pPrevFree;
161 /* a user reference associated with this span, user references are
162 * currently only provided in the callback mechanism */
163 BM_MAPPING *psMapping;
164
165#if defined(VALIDATE_ARENA_TEST)
166 RESOURCE_DESCRIPTOR eResourceSpan;
167 RESOURCE_TYPE eResourceType;
168
169 /* This variable provides a reference (used in debug messages) to incompatible
170 boundary tags within the doubly linked ordered list. */
171 IMG_UINT32 ui32BoundaryTagID;
172#endif
173
174};
175typedef struct _BT_ BT;
176
177
178/* resource allocation arena */
179struct _RA_ARENA_
180{
181 /* arena name for diagnostics output */
182 IMG_CHAR *name;
183
184 /* allocations within this arena are quantum sized */
185 IMG_SIZE_T uQuantum;
186
187 /* import interface, if provided */
188 IMG_BOOL (*pImportAlloc)(IMG_VOID *,
189 IMG_SIZE_T uSize,
190 IMG_SIZE_T *pActualSize,
191 BM_MAPPING **ppsMapping,
192 IMG_UINT32 uFlags,
193 IMG_PVOID pvPrivData,
194 IMG_UINT32 ui32PrivDataLength,
195 IMG_UINTPTR_T *pBase);
196 IMG_VOID (*pImportFree) (IMG_VOID *,
197 IMG_UINTPTR_T,
198 BM_MAPPING *psMapping);
199 IMG_VOID (*pBackingStoreFree) (IMG_VOID *, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE);
200
201 /* arbitrary handle provided by arena owner to be passed into the
202 * import alloc and free hooks */
203 IMG_VOID *pImportHandle;
204
205 /* head of list of free boundary tags for indexed by pvr_log2 of the
206 boundary tag size */
207#define FREE_TABLE_LIMIT 32
208
209 /* power-of-two table of free lists */
210 BT *aHeadFree [FREE_TABLE_LIMIT];
211
212 /* resource ordered segment list */
213 BT *pHeadSegment;
214 BT *pTailSegment;
215
216 /* segment address to boundary tag hash table */
217 HASH_TABLE *pSegmentHash;
218
219#ifdef RA_STATS
220 RA_STATISTICS sStatistics;
221#endif
222
223#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS)
224#define PROC_NAME_SIZE 64
225
226 struct proc_dir_entry* pProcInfo;
227 struct proc_dir_entry* pProcSegs;
228
229 IMG_BOOL bInitProcEntry;
230
231#if defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG)
232 struct proc_dir_entry* pProcAllocFailThreshold;
233
234 IMG_BOOL bFailAllocationOnce;
235 IMG_BOOL bFailAllocationPersist;
236 IMG_SIZE_T uAllocFailThreshold;
237 IMG_UINT32 uAllocFailMask;
238#endif //defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG)
239
240#endif
241};
242/* #define ENABLE_RA_DUMP 1 */
243#if defined(ENABLE_RA_DUMP)
244IMG_VOID RA_Dump (RA_ARENA *pArena);
245#endif
246
247static INLINE IMG_BOOL RA_TestAllocationFail(RA_ARENA *pArena, IMG_SIZE_T size, IMG_UINT32 buff_type)
248{
249 #if defined (CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG)
250 if(pArena->bFailAllocationOnce == IMG_TRUE)
251 {
252 if((size > pArena->uAllocFailThreshold) && (pArena->uAllocFailMask & buff_type))
253 {
254 if(pArena->bFailAllocationPersist == IMG_FALSE)
255 pArena->bFailAllocationOnce = IMG_FALSE;
256 return IMG_TRUE;
257 }
258 }
259 #endif //CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG
260 return IMG_FALSE;
261}
262
263#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS)
264
265static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el);
266static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off);
267
268static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el);
269static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off);
270
271#if defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG)
272static int RA_ProcSetAllocFailThreshold(struct file *file, const char __user *buffer, unsigned long count, void *data);
273static void* RA_ProcSeqOff2AllocFailThreshold(struct seq_file * sfile, loff_t off);
274static void RA_ProcSeqShowAllocFailThreshold(struct seq_file *sfile,void* el);
275#endif //defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG)
276
277#endif /* defined(CONFIG_PROC_FS) && defined(DEBUG) */
278
279static PVRSRV_ERROR RA_DumpHeapInfo(RA_ARENA *pArena, IMG_UINT32 ui32DebugLevel);
280
281#ifdef USE_BM_FREESPACE_CHECK
282IMG_VOID CheckBMFreespace(IMG_VOID);
283#endif
284
285#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS)
286static IMG_CHAR *ReplaceSpaces(IMG_CHAR * const pS)
287{
288 IMG_CHAR *pT;
289
290 for(pT = pS; *pT != 0; pT++)
291 {
292 if (*pT == ' ' || *pT == '\t')
293 {
294 *pT = '_';
295 }
296 }
297
298 return pS;
299}
300#endif
301
302/*!
303******************************************************************************
304 @Function _RequestAllocFail
305
306 @Description Default callback allocator used if no callback is
307 specified, always fails to allocate further resources to the
308 arena.
309
310 @Input _h - callback handle
311 @Input _uSize - requested allocation size
312 @Output _pActualSize - actual allocation size
313 @Input _pRef - user reference
314 @Input _uflags - allocation flags
315 @Input _pvPrivData - private data
316 @Input _ui32PrivDataLength - private data length
317 @Input _pBase - receives allocated base
318
319 @Return IMG_FALSE, this function always fails to allocate.
320******************************************************************************/
321static IMG_BOOL
322_RequestAllocFail (IMG_VOID *_h,
323 IMG_SIZE_T _uSize,
324 IMG_SIZE_T *_pActualSize,
325 BM_MAPPING **_ppsMapping,
326 IMG_UINT32 _uFlags,
327 IMG_PVOID _pvPrivData,
328 IMG_UINT32 _ui32PrivDataLength,
329 IMG_UINTPTR_T *_pBase)
330{
331 PVR_UNREFERENCED_PARAMETER (_h);
332 PVR_UNREFERENCED_PARAMETER (_uSize);
333 PVR_UNREFERENCED_PARAMETER (_pActualSize);
334 PVR_UNREFERENCED_PARAMETER (_ppsMapping);
335 PVR_UNREFERENCED_PARAMETER (_uFlags);
336 PVR_UNREFERENCED_PARAMETER (_pBase);
337 PVR_UNREFERENCED_PARAMETER (_pvPrivData);
338 PVR_UNREFERENCED_PARAMETER (_ui32PrivDataLength);
339
340 return IMG_FALSE;
341}
342
343/*!
344******************************************************************************
345 @Function pvr_log2
346
347 @Description Computes the floor of the log base 2 of a unsigned integer
348
349 @Input n - unsigned integer
350
351 @Return Floor(Log2(n))
352******************************************************************************/
353static IMG_UINT32
354pvr_log2 (IMG_SIZE_T n)
355{
356 IMG_UINT32 l = 0;
357 n>>=1;
358 while (n>0)
359 {
360 n>>=1;
361 l++;
362 }
363 return l;
364}
365
366/*!
367******************************************************************************
368 @Function _SegmentListInsertAfter
369
370 @Description Insert a boundary tag into an arena segment list after a
371 specified boundary tag.
372
373 @Input pArena - the arena.
374 @Input pInsertionPoint - the insertion point.
375 @Input pBT - the boundary tag to insert.
376
377 @Return PVRSRV_ERROR
378******************************************************************************/
379static PVRSRV_ERROR
380_SegmentListInsertAfter (RA_ARENA *pArena,
381 BT *pInsertionPoint,
382 BT *pBT)
383{
384 PVR_ASSERT (pArena != IMG_NULL);
385 PVR_ASSERT (pInsertionPoint != IMG_NULL);
386
387 if ((pInsertionPoint == IMG_NULL) || (pArena == IMG_NULL))
388 {
389 PVR_DPF ((PVR_DBG_ERROR,"_SegmentListInsertAfter: invalid parameters"));
390 return PVRSRV_ERROR_INVALID_PARAMS;
391 }
392
393 pBT->pNextSegment = pInsertionPoint->pNextSegment;
394 pBT->pPrevSegment = pInsertionPoint;
395 if (pInsertionPoint->pNextSegment == IMG_NULL)
396 pArena->pTailSegment = pBT;
397 else
398 pInsertionPoint->pNextSegment->pPrevSegment = pBT;
399 pInsertionPoint->pNextSegment = pBT;
400
401 return PVRSRV_OK;
402}
403
404/*!
405******************************************************************************
406 @Function _SegmentListInsert
407
408 @Description Insert a boundary tag into an arena segment list at the
409 appropriate point.
410
411 @Input pArena - the arena.
412 @Input pBT - the boundary tag to insert.
413
414 @Return None
415******************************************************************************/
416static PVRSRV_ERROR
417_SegmentListInsert (RA_ARENA *pArena, BT *pBT)
418{
419 PVRSRV_ERROR eError = PVRSRV_OK;
420
421 /* insert into the segment chain */
422 if (pArena->pHeadSegment == IMG_NULL)
423 {
424 pArena->pHeadSegment = pArena->pTailSegment = pBT;
425 pBT->pNextSegment = pBT->pPrevSegment = IMG_NULL;
426 }
427 else
428 {
429 BT *pBTScan;
430
431 if (pBT->base < pArena->pHeadSegment->base)
432 {
433 /* The base address of pBT is less than the base address of the boundary tag
434 at the head of the list - so insert this boundary tag at the head. */
435 pBT->pNextSegment = pArena->pHeadSegment;
436 pArena->pHeadSegment->pPrevSegment = pBT;
437 pArena->pHeadSegment = pBT;
438 pBT->pPrevSegment = IMG_NULL;
439 }
440 else
441 {
442
443 /* The base address of pBT is greater than or equal to that of the boundary tag
444 at the head of the list. Search for the insertion point: pBT must be inserted
445 before the first boundary tag with a greater base value - or at the end of the list.
446 */
447 pBTScan = pArena->pHeadSegment;
448
449 while ((pBTScan->pNextSegment != IMG_NULL) && (pBT->base >= pBTScan->pNextSegment->base))
450 {
451 pBTScan = pBTScan->pNextSegment;
452 }
453
454 eError = _SegmentListInsertAfter (pArena, pBTScan, pBT);
455 if (eError != PVRSRV_OK)
456 {
457 return eError;
458 }
459 }
460 }
461 return eError;
462}
463
464/*!
465******************************************************************************
466 @Function _SegmentListRemove
467
468 @Description Remove a boundary tag from an arena segment list.
469
470 @Input pArena - the arena.
471 @Input pBT - the boundary tag to remove.
472
473 @Return None
474******************************************************************************/
475static IMG_VOID
476_SegmentListRemove (RA_ARENA *pArena, BT *pBT)
477{
478 if (pBT->pPrevSegment == IMG_NULL)
479 pArena->pHeadSegment = pBT->pNextSegment;
480 else
481 pBT->pPrevSegment->pNextSegment = pBT->pNextSegment;
482
483 if (pBT->pNextSegment == IMG_NULL)
484 pArena->pTailSegment = pBT->pPrevSegment;
485 else
486 pBT->pNextSegment->pPrevSegment = pBT->pPrevSegment;
487}
488
489/*!
490******************************************************************************
491 @Function _SegmentSplit
492
493 @Description Split a segment into two, maintain the arena segment list. The
494 boundary tag should not be in the free table. Neither the
495 original or the new neighbour bounary tag will be in the free
496 table.
497
498 @Input pArena - the arena.
499 @Input pBT - the boundary tag to split.
500 @Input uSize - the required segment size of boundary tag after
501 splitting.
502
503 @Return New neighbour boundary tag.
504
505******************************************************************************/
506static BT *
507_SegmentSplit (RA_ARENA *pArena, BT *pBT, IMG_SIZE_T uSize)
508{
509 BT *pNeighbour;
510
511 PVR_ASSERT (pArena != IMG_NULL);
512
513 if (pArena == IMG_NULL)
514 {
515 PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: invalid parameter - pArena"));
516 return IMG_NULL;
517 }
518
519 if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
520 sizeof(BT),
521 (IMG_VOID **)&pNeighbour, IMG_NULL,
522 "Boundary Tag") != PVRSRV_OK)
523 {
524 return IMG_NULL;
525 }
526
527 OSMemSet(pNeighbour, 0, sizeof(BT));
528
529#if defined(VALIDATE_ARENA_TEST)
530 pNeighbour->ui32BoundaryTagID = ++ui32BoundaryTagID;
531#endif
532
533 pNeighbour->pPrevSegment = pBT;
534 pNeighbour->pNextSegment = pBT->pNextSegment;
535 if (pBT->pNextSegment == IMG_NULL)
536 pArena->pTailSegment = pNeighbour;
537 else
538 pBT->pNextSegment->pPrevSegment = pNeighbour;
539 pBT->pNextSegment = pNeighbour;
540
541 pNeighbour->type = btt_free;
542 pNeighbour->uSize = pBT->uSize - uSize;
543 pNeighbour->base = pBT->base + uSize;
544 pNeighbour->psMapping = pBT->psMapping;
545 pBT->uSize = uSize;
546
547#if defined(VALIDATE_ARENA_TEST)
548 if (pNeighbour->pPrevSegment->eResourceType == IMPORTED_RESOURCE_TYPE)
549 {
550 pNeighbour->eResourceType = IMPORTED_RESOURCE_TYPE;
551 pNeighbour->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
552 }
553 else if (pNeighbour->pPrevSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
554 {
555 pNeighbour->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
556 pNeighbour->eResourceSpan = RESOURCE_SPAN_FREE;
557 }
558 else
559 {
560 PVR_DPF ((PVR_DBG_ERROR,"_SegmentSplit: pNeighbour->pPrevSegment->eResourceType unrecognized"));
561 PVR_DBG_BREAK;
562 }
563#endif
564
565 return pNeighbour;
566}
567
568/*!
569******************************************************************************
570 @Function _FreeListInsert
571
572 @Description Insert a boundary tag into an arena free table.
573
574 @Input pArena - the arena.
575 @Input pBT - the boundary tag.
576
577 @Return None
578
579******************************************************************************/
580static IMG_VOID
581_FreeListInsert (RA_ARENA *pArena, BT *pBT)
582{
583 IMG_UINT32 uIndex;
584 uIndex = pvr_log2 (pBT->uSize);
585 pBT->type = btt_free;
586 pBT->pNextFree = pArena->aHeadFree [uIndex];
587 pBT->pPrevFree = IMG_NULL;
588 if (pArena->aHeadFree[uIndex] != IMG_NULL)
589 pArena->aHeadFree[uIndex]->pPrevFree = pBT;
590 pArena->aHeadFree [uIndex] = pBT;
591}
592
593/*!
594******************************************************************************
595 @Function _FreeListRemove
596
597 @Description Remove a boundary tag from an arena free table.
598
599 @Input pArena - the arena.
600 @Input pBT - the boundary tag.
601
602 @Return None
603
604******************************************************************************/
605static IMG_VOID
606_FreeListRemove (RA_ARENA *pArena, BT *pBT)
607{
608 IMG_UINT32 uIndex;
609 uIndex = pvr_log2 (pBT->uSize);
610 if (pBT->pNextFree != IMG_NULL)
611 pBT->pNextFree->pPrevFree = pBT->pPrevFree;
612 if (pBT->pPrevFree == IMG_NULL)
613 pArena->aHeadFree[uIndex] = pBT->pNextFree;
614 else
615 pBT->pPrevFree->pNextFree = pBT->pNextFree;
616}
617
618/*!
619******************************************************************************
620 @Function _BuildSpanMarker
621
622 @Description Construct a span marker boundary tag.
623
624 @Input pArena - arena to contain span marker
625 @Input base - the base of the bounary tag.
626
627 @Return span marker boundary tag
628
629******************************************************************************/
630static BT *
631_BuildSpanMarker (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
632{
633 BT *pBT;
634
635 if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
636 sizeof(BT),
637 (IMG_VOID **)&pBT, IMG_NULL,
638 "Boundary Tag") != PVRSRV_OK)
639 {
640 return IMG_NULL;
641 }
642
643 OSMemSet(pBT, 0, sizeof(BT));
644
645#if defined(VALIDATE_ARENA_TEST)
646 pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
647#endif
648
649 pBT->type = btt_span;
650 pBT->base = base;
651 pBT->uSize = uSize;
652 pBT->psMapping = IMG_NULL;
653
654 return pBT;
655}
656
657/*!
658******************************************************************************
659 @Function _BuildBT
660
661 @Description Construct a boundary tag for a free segment.
662
663 @Input base - the base of the resource segment.
664 @Input uSize - the extent of the resouce segment.
665
666 @Return boundary tag
667
668******************************************************************************/
669static BT *
670_BuildBT (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
671{
672 BT *pBT;
673
674 if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
675 sizeof(BT),
676 (IMG_VOID **)&pBT, IMG_NULL,
677 "Boundary Tag") != PVRSRV_OK)
678 {
679 return IMG_NULL;
680 }
681
682 OSMemSet(pBT, 0, sizeof(BT));
683
684#if defined(VALIDATE_ARENA_TEST)
685 pBT->ui32BoundaryTagID = ++ui32BoundaryTagID;
686#endif
687
688 pBT->type = btt_free;
689 pBT->base = base;
690 pBT->uSize = uSize;
691
692 return pBT;
693}
694
695/*!
696******************************************************************************
697 @Function _InsertResource
698
699 @Description Add a free resource segment to an arena.
700
701 @Input pArena - the arena.
702 @Input base - the base of the resource segment.
703 @Input uSize - the extent of the resource segment.
704
705 @Return New bucket pointer
706 IMG_NULL failure
707
708******************************************************************************/
709static BT *
710_InsertResource (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
711{
712 BT *pBT;
713 PVR_ASSERT (pArena!=IMG_NULL);
714 if (pArena == IMG_NULL)
715 {
716 PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: invalid parameter - pArena"));
717 return IMG_NULL;
718 }
719
720 pBT = _BuildBT (base, uSize);
721 if (pBT != IMG_NULL)
722 {
723
724#if defined(VALIDATE_ARENA_TEST)
725 pBT->eResourceSpan = RESOURCE_SPAN_FREE;
726 pBT->eResourceType = NON_IMPORTED_RESOURCE_TYPE;
727#endif
728
729 if (_SegmentListInsert (pArena, pBT) != PVRSRV_OK)
730 {
731 PVR_DPF ((PVR_DBG_ERROR,"_InsertResource: call to _SegmentListInsert failed"));
732 return IMG_NULL;
733 }
734 _FreeListInsert (pArena, pBT);
735#ifdef RA_STATS
736 pArena->sStatistics.uTotalResourceCount+=uSize;
737 pArena->sStatistics.uFreeResourceCount+=uSize;
738 pArena->sStatistics.uSpanCount++;
739#endif
740 }
741 return pBT;
742}
743
744/*!
745******************************************************************************
746 @Function _InsertResourceSpan
747
748 @Description Add a free resource span to an arena, complete with span markers.
749
750 @Input pArena - the arena.
751 @Input base - the base of the resource segment.
752 @Input uSize - the extent of the resource segment.
753
754 @Return the boundary tag representing the free resource segment,
755 or IMG_NULL on failure.
756******************************************************************************/
757static BT *
758_InsertResourceSpan (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
759{
760 PVRSRV_ERROR eError;
761 BT *pSpanStart;
762 BT *pSpanEnd;
763 BT *pBT;
764
765 PVR_ASSERT (pArena != IMG_NULL);
766 if (pArena == IMG_NULL)
767 {
768 PVR_DPF ((PVR_DBG_ERROR,"_InsertResourceSpan: invalid parameter - pArena"));
769 return IMG_NULL;
770 }
771
772 PVR_DPF ((PVR_DBG_MESSAGE,
773 "RA_InsertResourceSpan: arena='%s', base=0x%x, size=0x%x",
774 pArena->name, base, uSize));
775
776 pSpanStart = _BuildSpanMarker (base, uSize);
777 if (pSpanStart == IMG_NULL)
778 {
779 goto fail_start;
780 }
781
782#if defined(VALIDATE_ARENA_TEST)
783 pSpanStart->eResourceSpan = IMPORTED_RESOURCE_SPAN_START;
784 pSpanStart->eResourceType = IMPORTED_RESOURCE_TYPE;
785#endif
786
787 pSpanEnd = _BuildSpanMarker (base + uSize, 0);
788 if (pSpanEnd == IMG_NULL)
789 {
790 goto fail_end;
791 }
792
793#if defined(VALIDATE_ARENA_TEST)
794 pSpanEnd->eResourceSpan = IMPORTED_RESOURCE_SPAN_END;
795 pSpanEnd->eResourceType = IMPORTED_RESOURCE_TYPE;
796#endif
797
798 pBT = _BuildBT (base, uSize);
799 if (pBT == IMG_NULL)
800 {
801 goto fail_bt;
802 }
803
804#if defined(VALIDATE_ARENA_TEST)
805 pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_FREE;
806 pBT->eResourceType = IMPORTED_RESOURCE_TYPE;
807#endif
808
809 eError = _SegmentListInsert (pArena, pSpanStart);
810 if (eError != PVRSRV_OK)
811 {
812 goto fail_SegListInsert;
813 }
814
815 eError = _SegmentListInsertAfter (pArena, pSpanStart, pBT);
816 if (eError != PVRSRV_OK)
817 {
818 goto fail_SegListInsert;
819 }
820
821 _FreeListInsert (pArena, pBT);
822
823 eError = _SegmentListInsertAfter (pArena, pBT, pSpanEnd);
824 if (eError != PVRSRV_OK)
825 {
826 goto fail_SegListInsert;
827 }
828
829#ifdef RA_STATS
830 pArena->sStatistics.uTotalResourceCount+=uSize;
831/* pArena->sStatistics.uFreeResourceCount+=uSize;
832 This has got to be wrong as uFreeResourceCount ends
833 up larger than uTotalResourceCount by uTotalResourceCount
834 - allocated memory
835*/
836#endif
837 return pBT;
838
839 fail_SegListInsert:
840 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
841 /*not nulling pointer, out of scope*/
842 fail_bt:
843 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanEnd, IMG_NULL);
844 /*not nulling pointer, out of scope*/
845 fail_end:
846 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanStart, IMG_NULL);
847 /*not nulling pointer, out of scope*/
848 fail_start:
849 return IMG_NULL;
850}
851
852/*!
853******************************************************************************
854 @Function _FreeBT
855
856 @Description Free a boundary tag taking care of the segment list and the
857 boundary tag free table.
858
859 @Input pArena - the arena.
860 @Input pBT - the boundary tag to free.
861 @Input bFreeBackingStore - Should backing for the memory be freed
862 as well.
863 @Return None
864******************************************************************************/
865static IMG_VOID
866_FreeBT (RA_ARENA *pArena, BT *pBT, IMG_BOOL bFreeBackingStore)
867{
868 BT *pNeighbour;
869 IMG_UINTPTR_T uOrigBase;
870 IMG_SIZE_T uOrigSize;
871
872 PVR_ASSERT (pArena!=IMG_NULL);
873 PVR_ASSERT (pBT!=IMG_NULL);
874
875 if ((pArena == IMG_NULL) || (pBT == IMG_NULL))
876 {
877 PVR_DPF ((PVR_DBG_ERROR,"_FreeBT: invalid parameter"));
878 return;
879 }
880
881#ifdef RA_STATS
882 pArena->sStatistics.uLiveSegmentCount--;
883 pArena->sStatistics.uFreeSegmentCount++;
884 pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
885#endif
886
887 uOrigBase = pBT->base;
888 uOrigSize = pBT->uSize;
889
890 /* try and coalesce with left neighbour */
891 pNeighbour = pBT->pPrevSegment;
892 if (pNeighbour!=IMG_NULL
893 && pNeighbour->type == btt_free
894 && pNeighbour->base + pNeighbour->uSize == pBT->base)
895 {
896 _FreeListRemove (pArena, pNeighbour);
897 _SegmentListRemove (pArena, pNeighbour);
898 pBT->base = pNeighbour->base;
899 pBT->uSize += pNeighbour->uSize;
900 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
901 /*not nulling original pointer, already overwritten*/
902#ifdef RA_STATS
903 pArena->sStatistics.uFreeSegmentCount--;
904#endif
905 }
906
907 /* try to coalesce with right neighbour */
908 pNeighbour = pBT->pNextSegment;
909 if (pNeighbour!=IMG_NULL
910 && pNeighbour->type == btt_free
911 && pBT->base + pBT->uSize == pNeighbour->base)
912 {
913 _FreeListRemove (pArena, pNeighbour);
914 _SegmentListRemove (pArena, pNeighbour);
915 pBT->uSize += pNeighbour->uSize;
916 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
917 /*not nulling original pointer, already overwritten*/
918#ifdef RA_STATS
919 pArena->sStatistics.uFreeSegmentCount--;
920#endif
921 }
922
923 /* try to free backing store memory. */
924 if (pArena->pBackingStoreFree != IMG_NULL && bFreeBackingStore)
925 {
926 IMG_UINTPTR_T uRoundedStart, uRoundedEnd;
927
928 /* Work out the first address we might be able to free. */
929 uRoundedStart = (uOrigBase / pArena->uQuantum) * pArena->uQuantum;
930 /* If a span is still using that address then leave it. */
931 if (uRoundedStart < pBT->base)
932 {
933 uRoundedStart += pArena->uQuantum;
934 }
935
936 /* Work out the last address we might be able to free. */
937 uRoundedEnd = ((uOrigBase + uOrigSize + pArena->uQuantum - 1) / pArena->uQuantum) * pArena->uQuantum;
938 /* If a span is still using that addres then leave it. */
939 if (uRoundedEnd > (pBT->base + pBT->uSize))
940 {
941 uRoundedEnd -= pArena->uQuantum;
942 }
943
944 if (uRoundedStart < uRoundedEnd)
945 {
946 pArena->pBackingStoreFree(pArena->pImportHandle, (IMG_SIZE_T)uRoundedStart, (IMG_SIZE_T)uRoundedEnd, (IMG_HANDLE)0);
947 }
948 }
949
950 if (pBT->pNextSegment!=IMG_NULL && pBT->pNextSegment->type == btt_span
951 && pBT->pPrevSegment!=IMG_NULL && pBT->pPrevSegment->type == btt_span)
952 {
953 BT *next = pBT->pNextSegment;
954 BT *prev = pBT->pPrevSegment;
955 _SegmentListRemove (pArena, next);
956 _SegmentListRemove (pArena, prev);
957 _SegmentListRemove (pArena, pBT);
958 pArena->pImportFree (pArena->pImportHandle, pBT->base, pBT->psMapping);
959#ifdef RA_STATS
960 pArena->sStatistics.uSpanCount--;
961 pArena->sStatistics.uExportCount++;
962 pArena->sStatistics.uFreeSegmentCount--;
963 pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
964 pArena->sStatistics.uTotalResourceCount-=pBT->uSize;
965#endif
966 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), next, IMG_NULL);
967 /*not nulling original pointer, already overwritten*/
968 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), prev, IMG_NULL);
969 /*not nulling original pointer, already overwritten*/
970 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
971 /*not nulling pointer, copy on stack*/
972 }
973 else
974 _FreeListInsert (pArena, pBT);
975}
976
977
978/*!
979******************************************************************************
980 @Function _AttemptAllocAligned
981
982 @Description Attempt an allocation from an arena.
983
984 @Input pArena - the arena.
985 @Input uSize - the requested allocation size.
986 @Output ppsMapping - the user references associated with
987 the allocated segment.
988 @Input flags - allocation flags
989 @Input uAlignment - required uAlignment, or 0
990 @Input uAlignmentOffset
991 @Output base - allocated resource base
992
993 @Return IMG_FALSE failure
994 IMG_TRUE success
995******************************************************************************/
996static IMG_BOOL
997_AttemptAllocAligned (RA_ARENA *pArena,
998 IMG_SIZE_T uSize,
999 BM_MAPPING **ppsMapping,
1000 IMG_UINT32 uFlags,
1001 IMG_UINT32 uAlignment,
1002 IMG_UINT32 uAlignmentOffset,
1003 IMG_UINTPTR_T *base)
1004{
1005 IMG_UINT32 uIndex;
1006 PVR_ASSERT (pArena!=IMG_NULL);
1007 if (pArena == IMG_NULL)
1008 {
1009 PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: invalid parameter - pArena"));
1010 return IMG_FALSE;
1011 }
1012
1013 if (uAlignment>1)
1014 uAlignmentOffset %= uAlignment;
1015
1016 /* search for a near fit free boundary tag, start looking at the
1017 pvr_log2 free table for our required size and work on up the
1018 table. */
1019 uIndex = pvr_log2 (uSize);
1020
1021 while (uIndex < FREE_TABLE_LIMIT && pArena->aHeadFree[uIndex]==IMG_NULL)
1022 uIndex++;
1023
1024 while (uIndex < FREE_TABLE_LIMIT)
1025 {
1026 if (pArena->aHeadFree[uIndex]!=IMG_NULL)
1027 {
1028 /* we have a cached free boundary tag */
1029 BT *pBT;
1030
1031 pBT = pArena->aHeadFree [uIndex];
1032 while (pBT!=IMG_NULL)
1033 {
1034 IMG_UINTPTR_T aligned_base;
1035
1036 if (uAlignment>1)
1037 aligned_base = (pBT->base + uAlignmentOffset + uAlignment - 1) / uAlignment * uAlignment - uAlignmentOffset;
1038 else
1039 aligned_base = pBT->base;
1040 PVR_DPF ((PVR_DBG_MESSAGE,
1041 "RA_AttemptAllocAligned: pBT-base=0x%x "
1042 "pBT-size=0x%x alignedbase=0x%x size=0x%x",
1043 pBT->base, pBT->uSize, aligned_base, uSize));
1044
1045 if (pBT->base + pBT->uSize >= aligned_base + uSize)
1046 {
1047 if(!pBT->psMapping || pBT->psMapping->ui32Flags == uFlags)
1048 {
1049 _FreeListRemove (pArena, pBT);
1050
1051 PVR_ASSERT (pBT->type == btt_free);
1052
1053#ifdef RA_STATS
1054 pArena->sStatistics.uLiveSegmentCount++;
1055 pArena->sStatistics.uFreeSegmentCount--;
1056 pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
1057#endif
1058
1059 /* with uAlignment we might need to discard the front of this segment */
1060 if (aligned_base > pBT->base)
1061 {
1062 BT *pNeighbour;
1063 pNeighbour = _SegmentSplit (pArena, pBT, (IMG_SIZE_T)(aligned_base - pBT->base));
1064 /* partition the buffer, create a new boundary tag */
1065 if (pNeighbour==IMG_NULL)
1066 {
1067 PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Front split failed"));
1068 /* Put pBT back in the list */
1069 _FreeListInsert (pArena, pBT);
1070 return IMG_FALSE;
1071 }
1072
1073 _FreeListInsert (pArena, pBT);
1074 #ifdef RA_STATS
1075 pArena->sStatistics.uFreeSegmentCount++;
1076 pArena->sStatistics.uFreeResourceCount+=pBT->uSize;
1077 #endif
1078 pBT = pNeighbour;
1079 }
1080
1081 /* the segment might be too big, if so, discard the back of the segment */
1082 if (pBT->uSize > uSize)
1083 {
1084 BT *pNeighbour;
1085 pNeighbour = _SegmentSplit (pArena, pBT, uSize);
1086 /* partition the buffer, create a new boundary tag */
1087 if (pNeighbour==IMG_NULL)
1088 {
1089 PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Back split failed"));
1090 /* Put pBT back in the list */
1091 _FreeListInsert (pArena, pBT);
1092 return IMG_FALSE;
1093 }
1094
1095 _FreeListInsert (pArena, pNeighbour);
1096 #ifdef RA_STATS
1097 pArena->sStatistics.uFreeSegmentCount++;
1098 pArena->sStatistics.uFreeResourceCount+=pNeighbour->uSize;
1099 #endif
1100 }
1101
1102 pBT->type = btt_live;
1103
1104#if defined(VALIDATE_ARENA_TEST)
1105 if (pBT->eResourceType == IMPORTED_RESOURCE_TYPE)
1106 {
1107 pBT->eResourceSpan = IMPORTED_RESOURCE_SPAN_LIVE;
1108 }
1109 else if (pBT->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
1110 {
1111 pBT->eResourceSpan = RESOURCE_SPAN_LIVE;
1112 }
1113 else
1114 {
1115 PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned ERROR: pBT->eResourceType unrecognized"));
1116 PVR_DBG_BREAK;
1117 }
1118#endif
1119 if (!HASH_Insert (pArena->pSegmentHash, pBT->base, (IMG_UINTPTR_T) pBT))
1120 {
1121 _FreeBT (pArena, pBT, IMG_FALSE);
1122 return IMG_FALSE;
1123 }
1124
1125 if (ppsMapping!=IMG_NULL)
1126 *ppsMapping = pBT->psMapping;
1127
1128 *base = pBT->base;
1129
1130 return IMG_TRUE;
1131 }
1132 else
1133 {
1134 PVR_DPF ((PVR_DBG_MESSAGE,
1135 "AttemptAllocAligned: mismatch in flags. Import has %x, request was %x", pBT->psMapping->ui32Flags, uFlags));
1136
1137 }
1138 }
1139 pBT = pBT->pNextFree;
1140 }
1141
1142 }
1143 uIndex++;
1144 }
1145
1146 return IMG_FALSE;
1147}
1148
1149
1150
1151/*!
1152******************************************************************************
1153 @Function RA_Create
1154
1155 @Description To create a resource arena.
1156
1157 @Input name - the name of the arena for diagnostic purposes.
1158 @Input base - the base of an initial resource span or 0.
1159 @Input uSize - the size of an initial resource span or 0.
1160 @Input uQuantum - the arena allocation quantum.
1161 @Input alloc - a resource allocation callback or 0.
1162 @Input free - a resource de-allocation callback or 0.
1163 @Input backingstore_free - a callback to free resources for spans or 0.
1164 @Input pImportHandle - handle passed to alloc and free or 0.
1165
1166 @Return arena handle, or IMG_NULL.
1167******************************************************************************/
1168RA_ARENA *
1169RA_Create (IMG_CHAR *name,
1170 IMG_UINTPTR_T base,
1171 IMG_SIZE_T uSize,
1172 BM_MAPPING *psMapping,
1173 IMG_SIZE_T uQuantum,
1174 IMG_BOOL (*imp_alloc)(IMG_VOID *, IMG_SIZE_T uSize, IMG_SIZE_T *pActualSize,
1175 BM_MAPPING **ppsMapping, IMG_UINT32 _flags,
1176 IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength,
1177 IMG_UINTPTR_T *pBase),
1178 IMG_VOID (*imp_free) (IMG_VOID *, IMG_UINTPTR_T, BM_MAPPING *),
1179 IMG_VOID (*backingstore_free) (IMG_VOID*, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE),
1180 IMG_VOID *pImportHandle)
1181{
1182 RA_ARENA *pArena;
1183 BT *pBT;
1184 IMG_INT i;
1185
1186 PVR_DPF ((PVR_DBG_MESSAGE,
1187 "RA_Create: name='%s', base=0x%x, uSize=0x%x, alloc=0x%x, free=0x%x",
1188 name, base, uSize, (IMG_UINTPTR_T)imp_alloc, (IMG_UINTPTR_T)imp_free));
1189
1190
1191 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
1192 sizeof (*pArena),
1193 (IMG_VOID **)&pArena, IMG_NULL,
1194 "Resource Arena") != PVRSRV_OK)
1195 {
1196 goto arena_fail;
1197 }
1198
1199 pArena->name = name;
1200 pArena->pImportAlloc = (imp_alloc!=IMG_NULL) ? imp_alloc : &_RequestAllocFail;
1201 pArena->pImportFree = imp_free;
1202 pArena->pBackingStoreFree = backingstore_free;
1203 pArena->pImportHandle = pImportHandle;
1204 for (i=0; i<FREE_TABLE_LIMIT; i++)
1205 pArena->aHeadFree[i] = IMG_NULL;
1206 pArena->pHeadSegment = IMG_NULL;
1207 pArena->pTailSegment = IMG_NULL;
1208 pArena->uQuantum = uQuantum;
1209
1210#ifdef RA_STATS
1211 OSMemSet(&pArena->sStatistics, 0x00, sizeof(pArena->sStatistics));
1212#endif
1213
1214#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS)
1215 if(strcmp(pArena->name,"") != 0)
1216 {
1217 IMG_INT ret;
1218 IMG_CHAR szProcInfoName[PROC_NAME_SIZE];
1219 IMG_CHAR szProcSegsName[PROC_NAME_SIZE];
1220 struct proc_dir_entry* (*pfnCreateProcEntrySeq)(const IMG_CHAR *,
1221 IMG_VOID*,
1222 pvr_next_proc_seq_t,
1223 pvr_show_proc_seq_t,
1224 pvr_off2element_proc_seq_t,
1225 pvr_startstop_proc_seq_t,
1226 write_proc_t);
1227
1228 pArena->bInitProcEntry = !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL);
1229
1230 /* Don't put shared heap info into a per process /proc subdirectory */
1231 pfnCreateProcEntrySeq = pArena->bInitProcEntry ? CreateProcEntrySeq : CreatePerProcessProcEntrySeq;
1232
1233 ret = snprintf(szProcInfoName, sizeof(szProcInfoName), "ra_info_%s", pArena->name);
1234 if (ret > 0 && ret < sizeof(szProcInfoName))
1235 {
1236 pArena->pProcInfo = pfnCreateProcEntrySeq(ReplaceSpaces(szProcInfoName), pArena, NULL,
1237 RA_ProcSeqShowInfo, RA_ProcSeqOff2ElementInfo, NULL, NULL);
1238 }
1239 else
1240 {
1241 pArena->pProcInfo = 0;
1242 PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_info proc entry for arena %s", pArena->name));
1243 }
1244
1245 ret = snprintf(szProcSegsName, sizeof(szProcSegsName), "ra_segs_%s", pArena->name);
1246 if (ret > 0 && ret < sizeof(szProcSegsName))
1247 {
1248 pArena->pProcSegs = pfnCreateProcEntrySeq(ReplaceSpaces(szProcSegsName), pArena, NULL,
1249 RA_ProcSeqShowRegs, RA_ProcSeqOff2ElementRegs, NULL, NULL);
1250 }
1251 else
1252 {
1253 pArena->pProcSegs = 0;
1254 PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_segs proc entry for arena %s", pArena->name));
1255 }
1256
1257#if defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG)
1258 pArena->uAllocFailThreshold = ~0;
1259 pArena->uAllocFailMask = ~0;
1260 pArena->bFailAllocationOnce = IMG_FALSE;
1261 pArena->bFailAllocationPersist = IMG_FALSE;
1262
1263 ret = snprintf(szProcSegsName, sizeof(szProcSegsName), "ra_fail_alloc_thld_%s", pArena->name);
1264 if (ret > 0 && ret < sizeof(szProcSegsName))
1265 {
1266 pArena->pProcAllocFailThreshold = pfnCreateProcEntrySeq(ReplaceSpaces(szProcSegsName), pArena, NULL,
1267 RA_ProcSeqShowAllocFailThreshold, RA_ProcSeqOff2AllocFailThreshold, NULL, RA_ProcSetAllocFailThreshold);
1268 }
1269 else
1270 {
1271 pArena->pProcAllocFailThreshold = 0;
1272 PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_fail_alloc_thld proc entry for arena %s", pArena->name));
1273 }
1274#endif //defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG)
1275 }
1276#endif /* defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS) */
1277
1278 pArena->pSegmentHash = HASH_Create (MINIMUM_HASH_SIZE);
1279 if (pArena->pSegmentHash==IMG_NULL)
1280 {
1281 goto hash_fail;
1282 }
1283 if (uSize>0)
1284 {
1285 uSize = (uSize + uQuantum - 1) / uQuantum * uQuantum;
1286 pBT = _InsertResource (pArena, base, uSize);
1287 if (pBT == IMG_NULL)
1288 {
1289 goto insert_fail;
1290 }
1291 pBT->psMapping = psMapping;
1292
1293 }
1294 return pArena;
1295
1296insert_fail:
1297 HASH_Delete (pArena->pSegmentHash);
1298hash_fail:
1299 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
1300 /*not nulling pointer, out of scope*/
1301arena_fail:
1302 return IMG_NULL;
1303}
1304
1305/*!
1306******************************************************************************
1307 @Function RA_Delete
1308
1309 @Description To delete a resource arena. All resources allocated from
1310 the arena must be freed before deleting the arena.
1311
1312 @Input pArena - the arena to delete.
1313
1314 @Return None
1315******************************************************************************/
1316IMG_VOID
1317RA_Delete (RA_ARENA *pArena)
1318{
1319 IMG_UINT32 uIndex;
1320
1321 PVR_ASSERT(pArena != IMG_NULL);
1322
1323 if (pArena == IMG_NULL)
1324 {
1325 PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: invalid parameter - pArena"));
1326 return;
1327 }
1328
1329 PVR_DPF ((PVR_DBG_MESSAGE,
1330 "RA_Delete: name='%s'", pArena->name));
1331
1332 for (uIndex=0; uIndex<FREE_TABLE_LIMIT; uIndex++)
1333 pArena->aHeadFree[uIndex] = IMG_NULL;
1334
1335 while (pArena->pHeadSegment != IMG_NULL)
1336 {
1337 BT *pBT = pArena->pHeadSegment;
1338
1339 if (pBT->type != btt_free)
1340 {
1341 PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: allocations still exist in the arena that is being destroyed"));
1342 PVR_DPF ((PVR_DBG_ERROR,"Likely Cause: client drivers not freeing allocations before destroying devmemcontext"));
1343 PVR_DPF ((PVR_DBG_ERROR,"RA_Delete: base = 0x%x size=0x%x", pBT->base, pBT->uSize));
1344 }
1345
1346 _SegmentListRemove (pArena, pBT);
1347 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
1348 /*not nulling original pointer, it has changed*/
1349#ifdef RA_STATS
1350 pArena->sStatistics.uSpanCount--;
1351#endif
1352 }
1353#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS)
1354 {
1355 IMG_VOID (*pfnRemoveProcEntrySeq)(struct proc_dir_entry*);
1356
1357 pfnRemoveProcEntrySeq = pArena->bInitProcEntry ? RemoveProcEntrySeq : RemovePerProcessProcEntrySeq;
1358
1359 if (pArena->pProcInfo != 0)
1360 {
1361 pfnRemoveProcEntrySeq( pArena->pProcInfo );
1362 }
1363
1364 if (pArena->pProcSegs != 0)
1365 {
1366 pfnRemoveProcEntrySeq( pArena->pProcSegs );
1367 }
1368
1369#if defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG)
1370 if(pArena->pProcAllocFailThreshold != 0)
1371 {
1372 pfnRemoveProcEntrySeq( pArena->pProcAllocFailThreshold );
1373 }
1374#endif //defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG)
1375 }
1376#endif
1377 HASH_Delete (pArena->pSegmentHash);
1378 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
1379 /*not nulling pointer, copy on stack*/
1380}
1381
1382/*!
1383******************************************************************************
1384 @Function RA_TestDelete
1385
1386 @Description To test whether it is safe to delete a resource arena. If any
1387 allocations have not been freed, the RA must not be deleted.
1388
1389 @Input pArena - the arena to test.
1390
1391 @Return IMG_BOOL - IMG_TRUE if is safe to go on and call RA_Delete.
1392******************************************************************************/
1393IMG_BOOL
1394RA_TestDelete (RA_ARENA *pArena)
1395{
1396 PVR_ASSERT(pArena != IMG_NULL);
1397
1398 if (pArena != IMG_NULL)
1399 {
1400 while (pArena->pHeadSegment != IMG_NULL)
1401 {
1402 BT *pBT = pArena->pHeadSegment;
1403 if (pBT->type != btt_free)
1404 {
1405 PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: detected resource leak!"));
1406 PVR_DPF ((PVR_DBG_ERROR,"RA_TestDelete: base = 0x%x size=0x%x", pBT->base, pBT->uSize));
1407 return IMG_FALSE;
1408 }
1409 }
1410 }
1411
1412 return IMG_TRUE;
1413}
1414
1415/*!
1416******************************************************************************
1417 @Function RA_Add
1418
1419 @Description To add a resource span to an arena. The span must not
1420 overlapp with any span previously added to the arena.
1421
1422 @Input pArena - the arena to add a span into.
1423 @Input base - the base of the span.
1424 @Input uSize - the extent of the span.
1425
1426 @Return IMG_TRUE - Success
1427 IMG_FALSE - failure
1428******************************************************************************/
1429IMG_BOOL
1430RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
1431{
1432 PVR_ASSERT (pArena != IMG_NULL);
1433
1434 if (pArena == IMG_NULL)
1435 {
1436 PVR_DPF ((PVR_DBG_ERROR,"RA_Add: invalid parameter - pArena"));
1437 return IMG_FALSE;
1438 }
1439
1440 PVR_DPF ((PVR_DBG_MESSAGE,
1441 "RA_Add: name='%s', base=0x%x, size=0x%x", pArena->name, base, uSize));
1442
1443 uSize = (uSize + pArena->uQuantum - 1) / pArena->uQuantum * pArena->uQuantum;
1444 return ((IMG_BOOL)(_InsertResource (pArena, base, uSize) != IMG_NULL));
1445}
1446
1447/*!
1448******************************************************************************
1449 @Function RA_Alloc
1450
1451 @Description To allocate resource from an arena.
1452
1453 @Input pArena - the arena
1454 @Input uRequestSize - the size of resource segment requested.
1455 @Output pActualSize - the actual size of resource segment
1456 allocated, typcially rounded up by quantum.
1457 @Output ppsMapping - the user reference associated with allocated resource span.
1458 @Input uFlags - flags influencing allocation policy.
1459 @Input uAlignment - the uAlignment constraint required for the
1460 allocated segment, use 0 if uAlignment not required.
1461 @Input uAlignmentOffset
1462 @Input pvPrivData - opaque private data passed through to allocator
1463 @Input ui32PrivDataLength - length of opaque private data
1464
1465 @Output base - allocated base resource
1466
1467 @Return IMG_TRUE - success
1468 IMG_FALSE - failure
1469******************************************************************************/
1470IMG_BOOL
1471RA_Alloc (RA_ARENA *pArena,
1472 IMG_SIZE_T uRequestSize,
1473 IMG_SIZE_T *pActualSize,
1474 BM_MAPPING **ppsMapping,
1475 IMG_UINT32 uFlags,
1476 IMG_UINT32 uAlignment,
1477 IMG_UINT32 uAlignmentOffset,
1478 IMG_PVOID pvPrivData,
1479 IMG_UINT32 ui32PrivDataLength,
1480 IMG_UINTPTR_T *base)
1481{
1482 IMG_BOOL bResult = IMG_FALSE;
1483 IMG_BOOL bTestAllocFail = IMG_FALSE;
1484 IMG_SIZE_T uSize = uRequestSize;
1485
1486 PVR_ASSERT (pArena!=IMG_NULL);
1487
1488 if (pArena == IMG_NULL)
1489 {
1490 PVR_DPF ((PVR_DBG_ERROR,"RA_Alloc: invalid parameter - pArena"));
1491 return IMG_FALSE;
1492 }
1493
1494#if defined(VALIDATE_ARENA_TEST)
1495 ValidateArena(pArena);
1496#endif
1497
1498#ifdef USE_BM_FREESPACE_CHECK
1499 CheckBMFreespace();
1500#endif
1501
1502 if (pActualSize != IMG_NULL)
1503 {
1504 *pActualSize = uSize;
1505 }
1506
1507 PVR_DPF ((PVR_DBG_MESSAGE,
1508 "RA_Alloc: arena='%s', size=0x%x(0x%x), alignment=0x%x, offset=0x%x",
1509 pArena->name, uSize, uRequestSize, uAlignment, uAlignmentOffset));
1510
1511 bTestAllocFail = RA_TestAllocationFail(pArena, uSize, ~0);
1512 if(!bTestAllocFail)
1513 {
1514 /* if allocation failed then we might have an import source which
1515 can provide more resource, else we will have to fail the
1516 allocation to the caller. */
1517 bResult = _AttemptAllocAligned (pArena, uSize, ppsMapping, uFlags,
1518 uAlignment, uAlignmentOffset, base);
1519 if (!bResult)
1520 {
1521 BM_MAPPING *psImportMapping;
1522 IMG_UINTPTR_T import_base;
1523 IMG_SIZE_T uImportSize = uSize;
1524
1525 /*
1526 Ensure that we allocate sufficient space to meet the uAlignment
1527 constraint
1528 */
1529 if (uAlignment > pArena->uQuantum)
1530 {
1531 uImportSize += (uAlignment - 1);
1532 }
1533
1534 /* ensure that we import according to the quanta of this arena */
1535 uImportSize = ((uImportSize + pArena->uQuantum - 1)/pArena->uQuantum)*pArena->uQuantum;
1536
1537 bResult =
1538 pArena->pImportAlloc (pArena->pImportHandle, uImportSize, &uImportSize,
1539 &psImportMapping, uFlags,
1540 pvPrivData, ui32PrivDataLength, &import_base);
1541 if (bResult)
1542 {
1543 BT *pBT;
1544 pBT = _InsertResourceSpan (pArena, import_base, uImportSize);
1545 /* successfully import more resource, create a span to
1546 represent it and retry the allocation attempt */
1547 if (pBT == IMG_NULL)
1548 {
1549 /* insufficient resources to insert the newly acquired span,
1550 so free it back again */
1551 pArena->pImportFree(pArena->pImportHandle, import_base,
1552 psImportMapping);
1553 PVR_DPF ((PVR_DBG_MESSAGE,
1554 "RA_Alloc: name='%s', size=0x%x failed!",
1555 pArena->name, uSize));
1556 /* RA_Dump (arena); */
1557 return IMG_FALSE;
1558 }
1559 pBT->psMapping = psImportMapping;
1560 #ifdef RA_STATS
1561 pArena->sStatistics.uFreeSegmentCount++;
1562 pArena->sStatistics.uFreeResourceCount += uImportSize;
1563 pArena->sStatistics.uImportCount++;
1564 pArena->sStatistics.uSpanCount++;
1565 #endif
1566 bResult = _AttemptAllocAligned(pArena, uSize, ppsMapping, uFlags,
1567 uAlignment, uAlignmentOffset,
1568 base);
1569 if (!bResult)
1570 {
1571 PVR_DPF ((PVR_DBG_ERROR,
1572 "RA_Alloc: name='%s' uAlignment failed!",
1573 pArena->name));
1574 }
1575 }
1576 }
1577 #ifdef RA_STATS
1578 if (bResult)
1579 pArena->sStatistics.uCumulativeAllocs++;
1580 #endif
1581 }
1582
1583 PVR_DPF((PVR_DBG_MESSAGE,
1584 "RA_Alloc: arena=%s, size=0x%x(0x%x), alignment=0x%x, "\
1585 "offset=0x%x, result=%d",
1586 pArena->name,
1587 uSize, uRequestSize, uAlignment, uAlignmentOffset,
1588 bResult));
1589
1590 /* RA_Dump (pArena);
1591 ra_stats (pArena);
1592 */
1593
1594 if (!bResult) {
1595 PVR_LOG(("RA_Alloc %s %s: arena=%s, size=0x%x(0x%x), "\
1596 "alignment=0x%x, offset=0x%x",
1597 (bResult ? "SUCCESS" : "FAILED"),
1598 (bTestAllocFail ? "in TEST_MODE!" : " "),
1599 pArena->name,
1600 uSize, uRequestSize, uAlignment, uAlignmentOffset));
1601 RA_DumpHeapInfo(pArena, ~0);
1602 }
1603#if defined(VALIDATE_ARENA_TEST)
1604 ValidateArena(pArena);
1605#endif
1606
1607 return bResult;
1608}
1609
1610
1611#if defined(VALIDATE_ARENA_TEST)
1612
1613/*!
1614******************************************************************************
1615 @Function ValidateArena
1616
1617 @Description Validate an arena by checking that adjacent members of the
1618 double linked ordered list are compatible. PVR_DBG_BREAK and
1619 PVR_DPF messages are used when an error is detected.
1620 NOTE: A DEBUG build is required for PVR_DBG_BREAK and PVR_DPF
1621 to operate.
1622
1623 @Input pArena - the arena
1624
1625 @Return 0
1626******************************************************************************/
1627IMG_UINT32 ValidateArena(RA_ARENA *pArena)
1628{
1629 BT* pSegment;
1630 RESOURCE_DESCRIPTOR eNextSpan;
1631
1632 pSegment = pArena->pHeadSegment;
1633
1634 if (pSegment == IMG_NULL)
1635 {
1636 return 0;
1637 }
1638
1639 if (pSegment->eResourceType == IMPORTED_RESOURCE_TYPE)
1640 {
1641 PVR_ASSERT(pSegment->eResourceSpan == IMPORTED_RESOURCE_SPAN_START);
1642
1643 while (pSegment->pNextSegment)
1644 {
1645 eNextSpan = pSegment->pNextSegment->eResourceSpan;
1646
1647 switch (pSegment->eResourceSpan)
1648 {
1649 case IMPORTED_RESOURCE_SPAN_LIVE:
1650
1651 if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
1652 (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
1653 (eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
1654 {
1655 /* error - next span must be live, free or end */
1656 PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
1657 pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
1658
1659 PVR_DBG_BREAK;
1660 }
1661 break;
1662
1663 case IMPORTED_RESOURCE_SPAN_FREE:
1664
1665 if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
1666 (eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
1667 {
1668 /* error - next span must be live or end */
1669 PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
1670 pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
1671
1672 PVR_DBG_BREAK;
1673 }
1674 break;
1675
1676 case IMPORTED_RESOURCE_SPAN_END:
1677
1678 if ((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
1679 (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
1680 (eNextSpan == IMPORTED_RESOURCE_SPAN_END))
1681 {
1682 /* error - next span cannot be live, free or end */
1683 PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
1684 pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
1685
1686 PVR_DBG_BREAK;
1687 }
1688 break;
1689
1690
1691 case IMPORTED_RESOURCE_SPAN_START:
1692
1693 if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
1694 (eNextSpan == IMPORTED_RESOURCE_SPAN_FREE)))
1695 {
1696 /* error - next span must be live or free */
1697 PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
1698 pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
1699
1700 PVR_DBG_BREAK;
1701 }
1702 break;
1703
1704 default:
1705 PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
1706 pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
1707
1708 PVR_DBG_BREAK;
1709 break;
1710 }
1711 pSegment = pSegment->pNextSegment;
1712 }
1713 }
1714 else if (pSegment->eResourceType == NON_IMPORTED_RESOURCE_TYPE)
1715 {
1716 PVR_ASSERT((pSegment->eResourceSpan == RESOURCE_SPAN_FREE) || (pSegment->eResourceSpan == RESOURCE_SPAN_LIVE));
1717
1718 while (pSegment->pNextSegment)
1719 {
1720 eNextSpan = pSegment->pNextSegment->eResourceSpan;
1721
1722 switch (pSegment->eResourceSpan)
1723 {
1724 case RESOURCE_SPAN_LIVE:
1725
1726 if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
1727 (eNextSpan == RESOURCE_SPAN_LIVE)))
1728 {
1729 /* error - next span must be free or live */
1730 PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
1731 pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
1732
1733 PVR_DBG_BREAK;
1734 }
1735 break;
1736
1737 case RESOURCE_SPAN_FREE:
1738
1739 if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
1740 (eNextSpan == RESOURCE_SPAN_LIVE)))
1741 {
1742 /* error - next span must be free or live */
1743 PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
1744 pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
1745
1746 PVR_DBG_BREAK;
1747 }
1748 break;
1749
1750 default:
1751 PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
1752 pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
1753
1754 PVR_DBG_BREAK;
1755 break;
1756 }
1757 pSegment = pSegment->pNextSegment;
1758 }
1759
1760 }
1761 else
1762 {
1763 PVR_DPF ((PVR_DBG_ERROR,"ValidateArena ERROR: pSegment->eResourceType unrecognized"));
1764
1765 PVR_DBG_BREAK;
1766 }
1767
1768 return 0;
1769}
1770
1771#endif
1772
1773
1774/*!
1775******************************************************************************
1776 @Function RA_Free
1777
1778 @Description To free a resource segment.
1779
1780 @Input pArena - the arena the segment was originally allocated from.
1781 @Input base - the base of the resource span to free.
1782 @Input bFreeBackingStore - Should backing store memory be freed.
1783
1784 @Return None
1785******************************************************************************/
1786IMG_VOID
1787RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore)
1788{
1789 BT *pBT;
1790
1791 PVR_ASSERT (pArena != IMG_NULL);
1792
1793 if (pArena == IMG_NULL)
1794 {
1795 PVR_DPF ((PVR_DBG_ERROR,"RA_Free: invalid parameter - pArena"));
1796 return;
1797 }
1798
1799#ifdef USE_BM_FREESPACE_CHECK
1800 CheckBMFreespace();
1801#endif
1802
1803 PVR_DPF ((PVR_DBG_MESSAGE,
1804 "RA_Free: name='%s', base=0x%x", pArena->name, base));
1805
1806 pBT = (BT *) HASH_Remove (pArena->pSegmentHash, base);
1807 PVR_ASSERT (pBT != IMG_NULL);
1808
1809 if (pBT)
1810 {
1811 PVR_ASSERT (pBT->base == base);
1812
1813#ifdef RA_STATS
1814 pArena->sStatistics.uCumulativeFrees++;
1815#endif
1816
1817#ifdef USE_BM_FREESPACE_CHECK
1818{
1819 IMG_BYTE* p;
1820 IMG_BYTE* endp;
1821
1822 p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset();
1823 endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize));
1824 while ((IMG_UINT32)p & 3)
1825 {
1826 *p++ = 0xAA;
1827 }
1828 while (p < (IMG_BYTE*)((IMG_UINT32)endp & 0xfffffffc))
1829 {
1830 *(IMG_UINT32*)p = 0xAAAAAAAA;
1831 p += sizeof(IMG_UINT32);
1832 }
1833 while (p < endp)
1834 {
1835 *p++ = 0xAA;
1836 }
1837 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));
1838}
1839#endif
1840 _FreeBT (pArena, pBT, bFreeBackingStore);
1841 }
1842}
1843
1844
1845/*!
1846******************************************************************************
1847 @Function RA_GetNextLiveSegment
1848
1849 @Description Returns details of the next live resource segments
1850
1851 @Input pArena - the arena the segment was originally allocated from.
1852 @InOut psSegDetails - rtn details of segments
1853
1854 @Return IMG_TRUE if operation succeeded
1855******************************************************************************/
1856IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails)
1857{
1858 BT *pBT;
1859
1860 if (psSegDetails->hSegment)
1861 {
1862 pBT = (BT *)psSegDetails->hSegment;
1863 }
1864 else
1865 {
1866 RA_ARENA *pArena = (RA_ARENA *)hArena;
1867
1868 pBT = pArena->pHeadSegment;
1869 }
1870 /* walk the arena segments and write live one to the buffer */
1871 while (pBT != IMG_NULL)
1872 {
1873 if (pBT->type == btt_live)
1874 {
1875 psSegDetails->uiSize = pBT->uSize;
1876 psSegDetails->sCpuPhyAddr.uiAddr = pBT->base;
1877 psSegDetails->hSegment = (IMG_HANDLE)pBT->pNextSegment;
1878
1879 return IMG_TRUE;
1880 }
1881
1882 pBT = pBT->pNextSegment;
1883 }
1884
1885 psSegDetails->uiSize = 0;
1886 psSegDetails->sCpuPhyAddr.uiAddr = 0;
1887 psSegDetails->hSegment = (IMG_HANDLE)IMG_UNDEF;
1888
1889 return IMG_FALSE;
1890}
1891
1892
1893#ifdef USE_BM_FREESPACE_CHECK
1894RA_ARENA* pJFSavedArena = IMG_NULL;
1895
1896IMG_VOID CheckBMFreespace(IMG_VOID)
1897{
1898 BT *pBT;
1899 IMG_BYTE* p;
1900 IMG_BYTE* endp;
1901
1902 if (pJFSavedArena != IMG_NULL)
1903 {
1904 for (pBT=pJFSavedArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
1905 {
1906 if (pBT->type == btt_free)
1907 {
1908 p = (IMG_BYTE*)pBT->base + SysGetDevicePhysOffset();
1909 endp = (IMG_BYTE*)((IMG_UINT32)(p + pBT->uSize) & 0xfffffffc);
1910
1911 while ((IMG_UINT32)p & 3)
1912 {
1913 if (*p++ != 0xAA)
1914 {
1915 fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p);
1916 for (;;);
1917 break;
1918 }
1919 }
1920 while (p < endp)
1921 {
1922 if (*(IMG_UINT32*)p != 0xAAAAAAAA)
1923 {
1924 fprintf(stderr,"BM_FREESPACE_CHECK: Blank space at %08X has changed to 0x%x\n",p,*(IMG_UINT32*)p);
1925 for (;;);
1926 break;
1927 }
1928 p += 4;
1929 }
1930 }
1931 }
1932 }
1933}
1934#endif
1935
1936
1937#if (defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS)) || defined (RA_STATS)
1938static IMG_CHAR *
1939_BTType (IMG_INT eType)
1940{
1941 switch (eType)
1942 {
1943 case btt_span: return "span";
1944 case btt_free: return "free";
1945 case btt_live: return "live";
1946 }
1947 return "junk";
1948}
1949#endif /*defined(CONFIG_PROC_FS) && defined(DEBUG)*/
1950
1951#if defined(ENABLE_RA_DUMP)
1952/*!
1953******************************************************************************
1954 @Function RA_Dump
1955
1956 @Description To dump a readable description of an arena. Diagnostic only.
1957
1958 @Input pArena - the arena to dump.
1959
1960 @Return None
1961******************************************************************************/
1962IMG_VOID
1963RA_Dump (RA_ARENA *pArena)
1964{
1965 BT *pBT;
1966 PVR_ASSERT (pArena != IMG_NULL);
1967 PVR_DPF ((PVR_DBG_MESSAGE,"Arena '%s':", pArena->name));
1968 PVR_DPF ((PVR_DBG_MESSAGE," alloc=%08X free=%08X handle=%08X quantum=%d",
1969 pArena->pImportAlloc, pArena->pImportFree, pArena->pImportHandle,
1970 pArena->uQuantum));
1971 PVR_DPF ((PVR_DBG_MESSAGE," segment Chain:"));
1972 if (pArena->pHeadSegment != IMG_NULL &&
1973 pArena->pHeadSegment->pPrevSegment != IMG_NULL)
1974 PVR_DPF ((PVR_DBG_MESSAGE," error: head boundary tag has invalid pPrevSegment"));
1975 if (pArena->pTailSegment != IMG_NULL &&
1976 pArena->pTailSegment->pNextSegment != IMG_NULL)
1977 PVR_DPF ((PVR_DBG_MESSAGE," error: tail boundary tag has invalid pNextSegment"));
1978
1979 for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
1980 {
1981 PVR_DPF ((PVR_DBG_MESSAGE,"\tbase=0x%x size=0x%x type=%s",
1982 (IMG_UINT32) pBT->base, pBT->uSize, _BTType (pBT->type)));
1983 }
1984
1985#ifdef HASH_TRACE
1986 HASH_Dump (pArena->pSegmentHash);
1987#endif
1988}
1989#endif /* #if defined(ENABLE_RA_DUMP) */
1990
1991static PVRSRV_ERROR RA_DumpHeapInfo(RA_ARENA *pArena, IMG_UINT32 ui32DebugLevel)
1992{
1993 BT *pBT;
1994
1995 {
1996 IMG_UINT32 ui32PID = OSGetCurrentProcessIDKM();
1997 IMG_CHAR dirname_buffer[256];
1998 IMG_CHAR dirname[256];
1999 const IMG_CHAR *proc_basename = dirname_buffer;
2000 dirname_buffer[255] = dirname[255] = '\0';
2001
2002 OSGetProcCmdline(ui32PID, dirname_buffer, sizeof(dirname_buffer));
2003 PVR_LOG(("\nCommand Line of the current process with ID %u is %s", ui32PID, dirname_buffer));
2004
2005 proc_basename = OSGetPathBaseName(dirname_buffer, sizeof(dirname_buffer));
2006 PVR_LOG(("Base Name of the current process with ID %u is %s", ui32PID, proc_basename));
2007
2008 }
2009
2010 PVR_LOG(("Arena '%s':", pArena->name));
2011
2012 PVR_LOG(( " allocCB=%p freeCB=%p handle=%p quantum=%d",
2013 pArena->pImportAlloc,
2014 pArena->pImportFree,
2015 pArena->pImportHandle,
2016 pArena->uQuantum));
2017
2018 PVR_LOG(( "span count\t\t%u", pArena->sStatistics.uSpanCount));
2019
2020 PVR_LOG(( "live segment count\t%u", pArena->sStatistics.uLiveSegmentCount));
2021
2022 PVR_LOG(( "free segment count\t%u", pArena->sStatistics.uFreeSegmentCount));
2023
2024 PVR_LOG(( "free resource count\t%u (0x%x)",
2025 pArena->sStatistics.uFreeResourceCount,
2026 (IMG_UINT)pArena->sStatistics.uFreeResourceCount));
2027
2028 PVR_LOG(( "total allocs\t\t%u", pArena->sStatistics.uCumulativeAllocs));
2029
2030 PVR_LOG(( "total failed allocs\t%u", pArena->sStatistics.uFailedAllocCount));
2031
2032 PVR_LOG(( "total frees\t\t%u", pArena->sStatistics.uCumulativeFrees));
2033
2034 PVR_LOG(( "import count\t\t%u", pArena->sStatistics.uImportCount));
2035
2036 PVR_LOG(( "export count\t\t%u", pArena->sStatistics.uExportCount));
2037
2038 PVR_LOG(( " segment Chain:"));
2039
2040 if (pArena->pHeadSegment != IMG_NULL &&
2041 pArena->pHeadSegment->pPrevSegment != IMG_NULL)
2042 {
2043 PVR_LOG(( " error: head boundary tag has invalid pPrevSegment"));
2044 }
2045
2046 if (pArena->pTailSegment != IMG_NULL &&
2047 pArena->pTailSegment->pNextSegment != IMG_NULL)
2048 {
2049 PVR_LOG(( " error: tail boundary tag has invalid pNextSegment"));
2050 }
2051
2052 for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
2053 {
2054 PVR_LOG(( "%s base=0x%08x size=%08d(0x%08x) type=%s ref=%p",
2055 ((pBT->type == btt_span) ? "\t\t" : "\t"),
2056 (IMG_UINT32) pBT->base,
2057 pBT->uSize, pBT->uSize,
2058 _BTType(pBT->type),
2059 pBT->psMapping));
2060 if(pBT->psMapping)
2061 {
2062 BM_MAPPING *psImportMapping = pBT->psMapping;
2063 PVR_LOG(( "\t %p: mapping type %s, mapping count=%d, size=%08d(0x%08x), flags=0x%08x, align=0x%04x",
2064 psImportMapping,
2065 _BMMappingType(psImportMapping->eCpuMemoryOrigin),
2066 psImportMapping->ui32MappingCount,
2067 psImportMapping->uSize, psImportMapping->uSize,
2068 psImportMapping->ui32Flags,
2069 psImportMapping->ui32DevVAddrAlignment));
2070 }
2071 }
2072
2073 return PVRSRV_OK;
2074}
2075
2076#if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS)
2077
2078#if defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG)
2079#define _PROC_SET_ALLOC_TH_BUFFER_SZ 32
2080static int RA_ProcSetAllocFailThreshold(struct file *file, const char __user *buffer, unsigned long count, void *data)
2081{
2082 PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)data;
2083 RA_ARENA *pArena;
2084 IMG_CHAR data_buffer[_PROC_SET_ALLOC_TH_BUFFER_SZ];
2085 IMG_INT32 value = ~0;
2086 IMG_UINT32 mask = ~0;
2087 IMG_INT32 format_ret;
2088
2089 if ((handlers == NULL) || (handlers->data == NULL) || (count > sizeof(data_buffer)))
2090 {
2091 return -EINVAL;
2092 }
2093
2094 pArena = (RA_ARENA *)handlers->data;
2095
2096 count = MIN(count, sizeof(data_buffer));
2097
2098 if (pvr_copy_from_user(data_buffer, buffer, count))
2099 return -EINVAL;
2100
2101 if (data_buffer[count - 1] != '\n')
2102 return -EINVAL;
2103
2104 data_buffer[(sizeof(data_buffer) - 1)] = '\0';
2105 if((sizeof(data_buffer) -1) <= count)
2106 data_buffer[count] = '\0';
2107
2108 PVR_LOG(("Buffer from the user is %s\n", data_buffer));
2109 format_ret = sscanf(data_buffer, "%i:0x%x", &value, &mask);
2110 PVR_LOG(("Value set is %i, type is %x, format %i\n", value, mask, format_ret));
2111 if(format_ret <= 0)
2112 return -EINVAL;
2113
2114/*
2115 Heap Allocation Buffer Threshold Setting - for testing purposes only
2116 Causes allocation of a GFX buffer of type MASK for the respective heap to
2117 fail.
2118 Format is <threshold value number>:<buffer type mask hex value>
2119 for example: 1000:0x01.
2120 Value of -1 disables the allocation fail test
2121 Value bigger than and eq. to 0 enables the allocation fail test for
2122 the first buffer only.
2123 Value smaller than -1 enables the buffer allocation failure for this
2124 heap until the test disables it.
2125*/
2126 if(value < 0)
2127 {
2128 if(value == -1)
2129 {
2130 pArena->bFailAllocationPersist = pArena->bFailAllocationOnce = IMG_FALSE;
2131 }
2132 else if(value == -2)
2133 {
2134 RA_DumpHeapInfo(pArena, ~0);
2135 }
2136 else
2137 {
2138 pArena->bFailAllocationPersist = pArena->bFailAllocationOnce = IMG_TRUE;
2139 pArena->uAllocFailThreshold = -value;
2140 }
2141 }
2142 else
2143 {
2144 pArena->bFailAllocationPersist = 0;
2145 pArena->bFailAllocationOnce = 1;
2146 pArena->uAllocFailThreshold = value;
2147 }
2148
2149 if(format_ret > 1)
2150 {
2151 if((pArena->bFailAllocationOnce == IMG_TRUE) && (mask == 0))
2152 pArena->uAllocFailMask = ~0;
2153 else
2154 pArena->uAllocFailMask = mask;
2155 }
2156 PVR_LOG(("*************** User Fail Heap Allocation Settings for %s *******************************\n",
2157 pArena->name));
2158 PVR_LOG(("Fail Heap Allocation is %s in %s mode\n", (pArena->bFailAllocationOnce ? "Enabled": "Disabled"),
2159 (pArena->bFailAllocationPersist ? "Persistent": "One-Shot")));
2160 PVR_LOG(("Fail Heap Allocation Buffer Size Threshold is %u with a Mask of 0x%x\n",
2161 pArena->uAllocFailThreshold, pArena->uAllocFailMask));
2162 PVR_LOG(("*******************************************************************************************\n"));
2163 return (count);
2164}
2165
2166static void* RA_ProcSeqOff2AllocFailThreshold(struct seq_file * sfile, loff_t off)
2167{
2168
2169 if(off <= 1)
2170 return (void*)(IMG_INT)(off+1);
2171
2172 return 0;
2173}
2174
2175static void RA_ProcSeqShowAllocFailThreshold(struct seq_file *sfile,void* el)
2176{
2177 PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
2178 RA_ARENA *pArena = (RA_ARENA *)handlers->data;
2179 IMG_INT off = (IMG_INT)el;
2180
2181 switch (off)
2182 {
2183 case 1:
2184 seq_printf(sfile, "Heap Allocation Buffer Threshold Setting - for testing purposes only\n");
2185 seq_printf(sfile, "Format is <threshold value number>:<buffer type mask hex value> for example: 1000:0x01\n");
2186 seq_printf(sfile, "Value of -1 disables the allocation fail test\n");
2187 seq_printf(sfile, "Value of -2 dumps the heap entries to the kernel log\n");
2188 seq_printf(sfile, "Value => 0 enables the allocation fail test for the first buffer with the met threshold only\n");
2189 seq_printf(sfile, "Value < -2 enables the buffer allocation failure for this heap until the test disables it\n");
2190 break;
2191 case 2:
2192 seq_printf(sfile, "*********** Current Settings: ********************\n");
2193 seq_printf(sfile,"Fail Heap Allocation is %s in %s mode\n", (pArena->bFailAllocationOnce ? "Enabled": "Disabled"),
2194 (pArena->bFailAllocationPersist ? "Persistent": "One-Shot"));
2195 seq_printf(sfile, "Fail Heap Allocation Buffer Size Threshold is %u with a Mask of 0x%x\n",
2196 pArena->uAllocFailThreshold, pArena->uAllocFailMask);
2197 break;
2198 }
2199}
2200#endif //defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG)
2201
2202static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el)
2203{
2204 PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
2205 RA_ARENA *pArena = (RA_ARENA *)handlers->data;
2206 IMG_INT off = (IMG_INT)el;
2207
2208 switch (off)
2209 {
2210 case 1:
2211 seq_printf(sfile, "quantum\t\t\t%u\n", pArena->uQuantum);
2212 break;
2213 case 2:
2214 seq_printf(sfile, "import_handle\t\t%08X\n", (IMG_UINT)pArena->pImportHandle);
2215 break;
2216#ifdef RA_STATS
2217 case 3:
2218 seq_printf(sfile,"span count\t\t%u\n", pArena->sStatistics.uSpanCount);
2219 break;
2220 case 4:
2221 seq_printf(sfile, "live segment count\t%u\n", pArena->sStatistics.uLiveSegmentCount);
2222 break;
2223 case 5:
2224 seq_printf(sfile, "free segment count\t%u\n", pArena->sStatistics.uFreeSegmentCount);
2225 break;
2226 case 6:
2227 seq_printf(sfile, "free resource count\t%u (0x%x)\n",
2228 pArena->sStatistics.uFreeResourceCount,
2229 (IMG_UINT)pArena->sStatistics.uFreeResourceCount);
2230 break;
2231 case 7:
2232 seq_printf(sfile, "total allocs\t\t%u\n", pArena->sStatistics.uCumulativeAllocs);
2233 break;
2234 case 8:
2235 seq_printf(sfile, "total frees\t\t%u\n", pArena->sStatistics.uCumulativeFrees);
2236 break;
2237 case 9:
2238 seq_printf(sfile, "import count\t\t%u\n", pArena->sStatistics.uImportCount);
2239 break;
2240 case 10:
2241 seq_printf(sfile, "export count\t\t%u\n", pArena->sStatistics.uExportCount);
2242 break;
2243#endif
2244 }
2245
2246}
2247
2248static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off)
2249{
2250#ifdef RA_STATS
2251 if(off <= 9)
2252#else
2253 if(off <= 1)
2254#endif
2255 return (void*)(IMG_INT)(off+1);
2256 return 0;
2257}
2258
2259static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el)
2260{
2261 PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
2262 RA_ARENA *pArena = (RA_ARENA *)handlers->data;
2263 BT *pBT = (BT*)el;
2264
2265 if (el == PVR_PROC_SEQ_START_TOKEN)
2266 {
2267 seq_printf(sfile, "Arena \"%s\"\nBase Size Type Ref\n", pArena->name);
2268 return;
2269 }
2270
2271 if (pBT)
2272 {
2273 seq_printf(sfile, "%08x %8x %4s %08x\n",
2274 (IMG_UINT)pBT->base, (IMG_UINT)pBT->uSize, _BTType (pBT->type),
2275 (IMG_UINT)pBT->psMapping);
2276 }
2277}
2278
2279static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off)
2280{
2281 PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)sfile->private;
2282 RA_ARENA *pArena = (RA_ARENA *)handlers->data;
2283 BT *pBT = 0;
2284
2285 if(off == 0)
2286 return PVR_PROC_SEQ_START_TOKEN;
2287
2288 for (pBT=pArena->pHeadSegment; --off && pBT; pBT=pBT->pNextSegment);
2289
2290 return (void*)pBT;
2291}
2292
2293#endif /* defined(CONFIG_PROC_FS) && defined(DEBUG) */
2294
2295
2296#ifdef RA_STATS
2297/*!
2298******************************************************************************
2299 @Function RA_GetStats
2300
2301 @Description Gets the arena stats and places in client buffer
2302
2303 @Input pArena - the arena to print statistics for.
2304 @Input ppszStr - caller string to fill
2305 @Input pui32StrLen - length of caller string
2306
2307 @Return PVRSRV_ERROR
2308******************************************************************************/
2309PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
2310 IMG_CHAR **ppszStr,
2311 IMG_UINT32 *pui32StrLen)
2312{
2313 IMG_CHAR *pszStr = *ppszStr;
2314 IMG_UINT32 ui32StrLen = *pui32StrLen;
2315 IMG_INT32 i32Count;
2316 BT *pBT;
2317
2318 CHECK_SPACE(ui32StrLen);
2319 i32Count = OSSNPrintf(pszStr, 100, "\nArena '%s':\n", pArena->name);
2320 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
2321
2322
2323 CHECK_SPACE(ui32StrLen);
2324 i32Count = OSSNPrintf(pszStr, 100, " allocCB=%p freeCB=%p handle=%p quantum=%d\n",
2325 pArena->pImportAlloc,
2326 pArena->pImportFree,
2327 pArena->pImportHandle,
2328 pArena->uQuantum);
2329 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
2330
2331 CHECK_SPACE(ui32StrLen);
2332 i32Count = OSSNPrintf(pszStr, 100, "span count\t\t%u\n", pArena->sStatistics.uSpanCount);
2333 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
2334
2335 CHECK_SPACE(ui32StrLen);
2336 i32Count = OSSNPrintf(pszStr, 100, "live segment count\t%u\n", pArena->sStatistics.uLiveSegmentCount);
2337 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
2338
2339 CHECK_SPACE(ui32StrLen);
2340 i32Count = OSSNPrintf(pszStr, 100, "free segment count\t%u\n", pArena->sStatistics.uFreeSegmentCount);
2341 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
2342
2343 CHECK_SPACE(ui32StrLen);
2344 i32Count = OSSNPrintf(pszStr, 100, "free resource count\t%u (0x%x)\n",
2345 pArena->sStatistics.uFreeResourceCount,
2346 (IMG_UINT)pArena->sStatistics.uFreeResourceCount);
2347 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
2348
2349 CHECK_SPACE(ui32StrLen);
2350 i32Count = OSSNPrintf(pszStr, 100, "total allocs\t\t%u\n", pArena->sStatistics.uCumulativeAllocs);
2351 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
2352
2353 CHECK_SPACE(ui32StrLen);
2354 i32Count = OSSNPrintf(pszStr, 100, "total frees\t\t%u\n", pArena->sStatistics.uCumulativeFrees);
2355 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
2356
2357 CHECK_SPACE(ui32StrLen);
2358 i32Count = OSSNPrintf(pszStr, 100, "import count\t\t%u\n", pArena->sStatistics.uImportCount);
2359 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
2360
2361 CHECK_SPACE(ui32StrLen);
2362 i32Count = OSSNPrintf(pszStr, 100, "export count\t\t%u\n", pArena->sStatistics.uExportCount);
2363 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
2364
2365 CHECK_SPACE(ui32StrLen);
2366 i32Count = OSSNPrintf(pszStr, 100, " segment Chain:\n");
2367 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
2368
2369 if (pArena->pHeadSegment != IMG_NULL &&
2370 pArena->pHeadSegment->pPrevSegment != IMG_NULL)
2371 {
2372 CHECK_SPACE(ui32StrLen);
2373 i32Count = OSSNPrintf(pszStr, 100, " error: head boundary tag has invalid pPrevSegment\n");
2374 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
2375 }
2376
2377 if (pArena->pTailSegment != IMG_NULL &&
2378 pArena->pTailSegment->pNextSegment != IMG_NULL)
2379 {
2380 CHECK_SPACE(ui32StrLen);
2381 i32Count = OSSNPrintf(pszStr, 100, " error: tail boundary tag has invalid pNextSegment\n");
2382 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
2383 }
2384
2385 for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
2386 {
2387 CHECK_SPACE(ui32StrLen);
2388 i32Count = OSSNPrintf(pszStr, 100, "\tbase=0x%x size=0x%x type=%s ref=%p\n",
2389 (IMG_UINT32) pBT->base,
2390 pBT->uSize,
2391 _BTType(pBT->type),
2392 pBT->psMapping);
2393 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
2394 }
2395
2396 *ppszStr = pszStr;
2397 *pui32StrLen = ui32StrLen;
2398
2399 return PVRSRV_OK;
2400}
2401
2402PVRSRV_ERROR RA_GetStatsFreeMem(RA_ARENA *pArena,
2403 IMG_CHAR **ppszStr,
2404 IMG_UINT32 *pui32StrLen)
2405{
2406 IMG_CHAR *pszStr = *ppszStr;
2407 IMG_UINT32 ui32StrLen = *pui32StrLen;
2408 IMG_INT32 i32Count;
2409 CHECK_SPACE(ui32StrLen);
2410 i32Count = OSSNPrintf(pszStr, 100, "Bytes free: Arena %-30s: %u (0x%x)\n", pArena->name,
2411 pArena->sStatistics.uFreeResourceCount,
2412 pArena->sStatistics.uFreeResourceCount);
2413 UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
2414 *ppszStr = pszStr;
2415 *pui32StrLen = ui32StrLen;
2416
2417 return PVRSRV_OK;
2418}
2419#endif
2420
2421/******************************************************************************
2422 End of file (ra.c)
2423******************************************************************************/
2424
2425
2426
2427