diff options
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.c | 2427 |
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 | |||
46 | The contents of this file are subject to the MIT license as set out below. | ||
47 | |||
48 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
49 | of this software and associated documentation files (the "Software"), to deal | ||
50 | in the Software without restriction, including without limitation the rights | ||
51 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
52 | copies of the Software, and to permit persons to whom the Software is | ||
53 | furnished to do so, subject to the following conditions: | ||
54 | |||
55 | The above copyright notice and this permission notice shall be included in | ||
56 | all copies or substantial portions of the Software. | ||
57 | |||
58 | Alternatively, the contents of this file may be used under the terms of | ||
59 | the GNU General Public License Version 2 ("GPL") in which case the provisions | ||
60 | of GPL are applicable instead of those above. | ||
61 | |||
62 | If you wish to allow use of your version of this file only under the terms of | ||
63 | GPL, and not to allow others to use your version of this file under the terms | ||
64 | of the MIT license, indicate your decision by deleting the provisions above | ||
65 | and replace them with the notice and other provisions required by GPL as set | ||
66 | out in the file called "GPL-COPYING" included in this distribution. If you do | ||
67 | not delete the provisions above, a recipient may use your version of this file | ||
68 | under the terms of either the MIT license or GPL. | ||
69 | |||
70 | This License is also included in this distribution in the file called | ||
71 | "MIT-COPYING". | ||
72 | |||
73 | EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS | ||
74 | PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING | ||
75 | BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
76 | PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR | ||
77 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER | ||
78 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | ||
79 | CONNECTION 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 | ||
114 | checking that adjacent members of the list have compatible eResourceSpan | ||
115 | and eResourceType values. */ | ||
116 | |||
117 | typedef 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 | |||
128 | typedef enum RESOURCE_TYPE_TAG { | ||
129 | |||
130 | IMPORTED_RESOURCE_TYPE = 20, | ||
131 | NON_IMPORTED_RESOURCE_TYPE | ||
132 | |||
133 | } RESOURCE_TYPE; | ||
134 | |||
135 | |||
136 | static IMG_UINT32 ui32BoundaryTagID = 0; | ||
137 | |||
138 | IMG_UINT32 ValidateArena(RA_ARENA *pArena); | ||
139 | #endif | ||
140 | |||
141 | /* boundary tags, used to describe a resource segment */ | ||
142 | struct _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 | }; | ||
175 | typedef struct _BT_ BT; | ||
176 | |||
177 | |||
178 | /* resource allocation arena */ | ||
179 | struct _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) | ||
244 | IMG_VOID RA_Dump (RA_ARENA *pArena); | ||
245 | #endif | ||
246 | |||
247 | static 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 | |||
265 | static void RA_ProcSeqShowInfo(struct seq_file *sfile, void* el); | ||
266 | static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off); | ||
267 | |||
268 | static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el); | ||
269 | static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off); | ||
270 | |||
271 | #if defined(CONFIG_PVR_PROC_FS_HEAP_ALLOC_DEBUG) | ||
272 | static int RA_ProcSetAllocFailThreshold(struct file *file, const char __user *buffer, unsigned long count, void *data); | ||
273 | static void* RA_ProcSeqOff2AllocFailThreshold(struct seq_file * sfile, loff_t off); | ||
274 | static 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 | |||
279 | static PVRSRV_ERROR RA_DumpHeapInfo(RA_ARENA *pArena, IMG_UINT32 ui32DebugLevel); | ||
280 | |||
281 | #ifdef USE_BM_FREESPACE_CHECK | ||
282 | IMG_VOID CheckBMFreespace(IMG_VOID); | ||
283 | #endif | ||
284 | |||
285 | #if defined(CONFIG_PROC_FS) && defined(CONFIG_PVR_PROC_FS) | ||
286 | static 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 | ******************************************************************************/ | ||
321 | static 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 | ******************************************************************************/ | ||
353 | static IMG_UINT32 | ||
354 | pvr_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 | ******************************************************************************/ | ||
379 | static 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 | ******************************************************************************/ | ||
416 | static 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 | ******************************************************************************/ | ||
475 | static 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 | ******************************************************************************/ | ||
506 | static 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 | ******************************************************************************/ | ||
580 | static 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 | ******************************************************************************/ | ||
605 | static 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 | ******************************************************************************/ | ||
630 | static 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 | ******************************************************************************/ | ||
669 | static 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 | ******************************************************************************/ | ||
709 | static 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 | ******************************************************************************/ | ||
757 | static 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 | ******************************************************************************/ | ||
865 | static 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 | ******************************************************************************/ | ||
996 | static 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 | ******************************************************************************/ | ||
1168 | RA_ARENA * | ||
1169 | RA_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 | |||
1296 | insert_fail: | ||
1297 | HASH_Delete (pArena->pSegmentHash); | ||
1298 | hash_fail: | ||
1299 | OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL); | ||
1300 | /*not nulling pointer, out of scope*/ | ||
1301 | arena_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 | ******************************************************************************/ | ||
1316 | IMG_VOID | ||
1317 | RA_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 | ******************************************************************************/ | ||
1393 | IMG_BOOL | ||
1394 | RA_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 | ******************************************************************************/ | ||
1429 | IMG_BOOL | ||
1430 | RA_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 | ******************************************************************************/ | ||
1470 | IMG_BOOL | ||
1471 | RA_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 | ******************************************************************************/ | ||
1627 | IMG_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 | ******************************************************************************/ | ||
1786 | IMG_VOID | ||
1787 | RA_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 | ******************************************************************************/ | ||
1856 | IMG_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 | ||
1894 | RA_ARENA* pJFSavedArena = IMG_NULL; | ||
1895 | |||
1896 | IMG_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) | ||
1938 | static 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 | ******************************************************************************/ | ||
1962 | IMG_VOID | ||
1963 | RA_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 | |||
1991 | static 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 | ||
2080 | static 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 | |||
2166 | static 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 | |||
2175 | static 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 | |||
2202 | static 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 | |||
2248 | static 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 | |||
2259 | static 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 | |||
2279 | static 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 | ******************************************************************************/ | ||
2309 | PVRSRV_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 | |||
2402 | PVRSRV_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 | |||