1 /**********************************************************************
3 * Copyright(c) 2008 Imagination Technologies Ltd. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful but, except
10 * as otherwise stated in writing, without any warranty; without even the
11 * implied warranty of merchantability or fitness for a particular purpose.
12 * See the GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18 * The full GNU General Public License is included in this distribution in
19 * the file called "COPYING".
21 * Contact Information:
22 * Imagination Technologies Ltd. <gpl-support@imgtec.com>
23 * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
25 ******************************************************************************/
29 #include "services_headers.h"
32 #ifdef CONFIG_PVR_DEBUG_EXTRA
33 #define HANDLE_BLOCK_SIZE 1
35 #define HANDLE_BLOCK_SIZE 256
38 #define HANDLE_HASH_TAB_INIT_SIZE 32
40 #define DEFAULT_MAX_INDEX_PLUS_ONE 0xfffffffful
41 #define DEFAULT_MAX_HANDLE DEFAULT_MAX_INDEX_PLUS_ONE
43 #define INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount)
45 #define INDEX_TO_HANDLE(psBase, idx) ((void *)((idx) + 1))
46 #define HANDLE_TO_INDEX(psBase, hand) ((u32)(hand) - 1)
48 #define INDEX_TO_HANDLE_PTR(psBase, i) (((psBase)->psHandleArray) + (i))
50 #define HANDLE_TO_HANDLE_PTR(psBase, h) \
51 (INDEX_TO_HANDLE_PTR(psBase, HANDLE_TO_INDEX(psBase, h)))
53 #define HANDLE_PTR_TO_INDEX(psBase, psHandle) \
54 ((psHandle) - ((psBase)->psHandleArray))
56 #define HANDLE_PTR_TO_HANDLE(psBase, psHandle) \
57 INDEX_TO_HANDLE(psBase, HANDLE_PTR_TO_INDEX(psBase, psHandle))
59 #define ROUND_UP_TO_MULTIPLE(a, b) ((((a) + (b) - 1) / (b)) * (b))
61 #define HANDLES_BATCHED(psBase) ((psBase)->ui32HandBatchSize != 0)
63 #define SET_FLAG(v, f) ((void)((v) |= (f)))
64 #define CLEAR_FLAG(v, f) ((void)((v) &= ~(f)))
65 #define TEST_FLAG(v, f) ((IMG_BOOL)(((v) & (f)) != 0))
67 #define TEST_ALLOC_FLAG(psHandle, f) \
68 TEST_FLAG((psHandle)->eFlag, f)
70 #define SET_INTERNAL_FLAG(psHandle, f) \
71 SET_FLAG((psHandle)->eInternalFlag, f)
72 #define CLEAR_INTERNAL_FLAG(psHandle, f) \
73 CLEAR_FLAG((psHandle)->eInternalFlag, f)
74 #define TEST_INTERNAL_FLAG(psHandle, f) \
75 TEST_FLAG((psHandle)->eInternalFlag, f)
77 #define BATCHED_HANDLE(psHandle) \
78 TEST_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
80 #define SET_BATCHED_HANDLE(psHandle) \
81 SET_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
83 #define SET_UNBATCHED_HANDLE(psHandle) \
84 CLEAR_INTERNAL_FLAG(psHandle, INTERNAL_HANDLE_FLAG_BATCHED)
86 #define BATCHED_HANDLE_PARTIALLY_FREE(psHandle) \
87 TEST_INTERNAL_FLAG(psHandle, \
88 INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
90 #define SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle) \
91 SET_INTERNAL_FLAG(psHandle, \
92 INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE)
94 #define HANDLE_STRUCT_IS_FREE(psHandle) \
95 ((psHandle)->eType == PVRSRV_HANDLE_TYPE_NONE && \
96 (psHandle)->eInternalFlag == INTERNAL_HANDLE_FLAG_NONE)
102 #define MIN(x, y) (((x) < (y)) ? (x) : (y))
110 enum ePVRSRVInternalHandleFlag {
111 INTERNAL_HANDLE_FLAG_NONE = 0x00,
112 INTERNAL_HANDLE_FLAG_BATCHED = 0x01,
113 INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE = 0x02,
117 enum PVRSRV_HANDLE_TYPE eType;
119 u32 ui32NextIndexPlusOne;
120 enum ePVRSRVInternalHandleFlag eInternalFlag;
121 enum PVRSRV_HANDLE_ALLOC_FLAG eFlag;
124 struct sHandleList sChildren;
125 struct sHandleList sSiblings;
128 struct PVRSRV_HANDLE_BASE {
129 void *hBaseBlockAlloc;
131 void *hHandBlockAlloc;
133 struct sHandle *psHandleArray;
134 struct HASH_TABLE *psHashTab;
135 u32 ui32FreeHandCount;
136 u32 ui32FirstFreeIndex;
138 u32 ui32MaxIndexPlusOne;
140 u32 ui32TotalHandCount;
141 u32 ui32LastFreeIndexPlusOne;
142 u32 ui32HandBatchSize;
143 u32 ui32TotalHandCountPreBatch;
144 u32 ui32FirstBatchIndexPlusOne;
145 u32 ui32BatchHandAllocFailures;
147 IMG_BOOL bPurgingEnabled;
157 struct PVRSRV_HANDLE_BASE *gpsKernelHandleBase;
159 static inline void HandleListInit(u32 ui32Index, struct sHandleList *psList,
162 psList->ui32Next = ui32Index;
163 psList->ui32Prev = ui32Index;
164 psList->hParent = hParent;
167 static inline void InitParentList(struct PVRSRV_HANDLE_BASE *psBase,
168 struct sHandle *psHandle)
170 u32 ui32Parent = HANDLE_PTR_TO_INDEX(psBase, psHandle);
172 HandleListInit(ui32Parent, &psHandle->sChildren,
173 INDEX_TO_HANDLE(psBase, ui32Parent));
176 static inline void InitChildEntry(struct PVRSRV_HANDLE_BASE *psBase,
177 struct sHandle *psHandle)
179 HandleListInit(HANDLE_PTR_TO_INDEX(psBase, psHandle),
180 &psHandle->sSiblings, NULL);
183 static inline IMG_BOOL HandleListIsEmpty(u32 ui32Index,
184 struct sHandleList *psList)
188 bIsEmpty = (IMG_BOOL) (psList->ui32Next == ui32Index);
190 #ifdef CONFIG_PVR_DEBUG_EXTRA
194 bIsEmpty2 = (IMG_BOOL) (psList->ui32Prev == ui32Index);
195 PVR_ASSERT(bIsEmpty == bIsEmpty2);
202 #ifdef CONFIG_PVR_DEBUG
203 static inline IMG_BOOL NoChildren(struct PVRSRV_HANDLE_BASE *psBase,
204 struct sHandle *psHandle)
206 PVR_ASSERT(psHandle->sChildren.hParent ==
207 HANDLE_PTR_TO_HANDLE(psBase, psHandle));
209 return HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psBase, psHandle),
210 &psHandle->sChildren);
213 static inline IMG_BOOL NoParent(struct PVRSRV_HANDLE_BASE *psBase,
214 struct sHandle *psHandle)
216 if (HandleListIsEmpty
217 (HANDLE_PTR_TO_INDEX(psBase, psHandle), &psHandle->sSiblings)) {
218 PVR_ASSERT(psHandle->sSiblings.hParent == NULL);
222 PVR_ASSERT(psHandle->sSiblings.hParent != NULL);
227 static inline void *ParentHandle(struct sHandle *psHandle)
229 return psHandle->sSiblings.hParent;
232 #define LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, i, p, po, eo) \
233 ((struct sHandleList *) \
234 ((char *)(INDEX_TO_HANDLE_PTR(psBase, i)) + \
235 (((i) == (p)) ? (po) : (eo))))
237 static inline void HandleListInsertBefore(struct PVRSRV_HANDLE_BASE *psBase,
238 u32 ui32InsIndex, struct sHandleList *psIns,
239 size_t uiParentOffset, u32 ui32EntryIndex,
240 struct sHandleList *psEntry,
241 size_t uiEntryOffset, u32 ui32ParentIndex)
243 struct sHandleList *psPrevIns =
244 LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev,
245 ui32ParentIndex, uiParentOffset,
248 PVR_ASSERT(psEntry->hParent == NULL);
249 PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next);
250 PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET
251 (psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset,
252 uiParentOffset)->hParent == INDEX_TO_HANDLE(psBase,
255 psEntry->ui32Prev = psIns->ui32Prev;
256 psIns->ui32Prev = ui32EntryIndex;
257 psEntry->ui32Next = ui32InsIndex;
258 psPrevIns->ui32Next = ui32EntryIndex;
260 psEntry->hParent = INDEX_TO_HANDLE(psBase, ui32ParentIndex);
263 static inline void AdoptChild(struct PVRSRV_HANDLE_BASE *psBase,
264 struct sHandle *psParent, struct sHandle *psChild)
267 HANDLE_TO_INDEX(psBase, psParent->sChildren.hParent);
269 PVR_ASSERT(ui32Parent ==
270 (u32) HANDLE_PTR_TO_INDEX(psBase, psParent));
272 HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren,
273 offsetof(struct sHandle, sChildren),
274 HANDLE_PTR_TO_INDEX(psBase, psChild),
275 &psChild->sSiblings, offsetof(struct sHandle,
281 static inline void HandleListRemove(struct PVRSRV_HANDLE_BASE *psBase,
282 u32 ui32EntryIndex, struct sHandleList *psEntry,
283 size_t uiEntryOffset, size_t uiParentOffset)
285 if (!HandleListIsEmpty(ui32EntryIndex, psEntry)) {
286 struct sHandleList *psPrev =
287 LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev,
288 HANDLE_TO_INDEX(psBase,
293 struct sHandleList *psNext =
294 LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next,
295 HANDLE_TO_INDEX(psBase,
301 PVR_ASSERT(psEntry->hParent != NULL);
303 psPrev->ui32Next = psEntry->ui32Next;
304 psNext->ui32Prev = psEntry->ui32Prev;
306 HandleListInit(ui32EntryIndex, psEntry, NULL);
310 static inline void UnlinkFromParent(struct PVRSRV_HANDLE_BASE *psBase,
311 struct sHandle *psHandle)
313 HandleListRemove(psBase, HANDLE_PTR_TO_INDEX(psBase, psHandle),
314 &psHandle->sSiblings, offsetof(struct sHandle,
316 offsetof(struct sHandle, sChildren));
319 static inline enum PVRSRV_ERROR HandleListIterate(
320 struct PVRSRV_HANDLE_BASE *psBase, struct sHandleList *psHead,
321 size_t uiParentOffset, size_t uiEntryOffset,
322 enum PVRSRV_ERROR(*pfnIterFunc)(struct PVRSRV_HANDLE_BASE *,
326 u32 ui32Parent = HANDLE_TO_INDEX(psBase, psHead->hParent);
328 PVR_ASSERT(psHead->hParent != NULL);
330 for (ui32Index = psHead->ui32Next; ui32Index != ui32Parent;) {
331 struct sHandle *psHandle =
332 INDEX_TO_HANDLE_PTR(psBase, ui32Index);
333 struct sHandleList *psEntry =
334 LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32Index,
335 ui32Parent, uiParentOffset,
337 enum PVRSRV_ERROR eError;
339 PVR_ASSERT(psEntry->hParent == psHead->hParent);
341 ui32Index = psEntry->ui32Next;
343 eError = (*pfnIterFunc)(psBase, psHandle);
344 if (eError != PVRSRV_OK)
351 static inline enum PVRSRV_ERROR IterateOverChildren(
352 struct PVRSRV_HANDLE_BASE *psBase,
353 struct sHandle *psParent,
354 enum PVRSRV_ERROR(*pfnIterFunc)
355 (struct PVRSRV_HANDLE_BASE *, struct sHandle *))
357 return HandleListIterate(psBase, &psParent->sChildren,
358 offsetof(struct sHandle, sChildren),
359 offsetof(struct sHandle, sSiblings),
363 static inline enum PVRSRV_ERROR GetHandleStructure(
364 struct PVRSRV_HANDLE_BASE *psBase,
365 struct sHandle **ppsHandle, void *hHandle,
366 enum PVRSRV_HANDLE_TYPE eType)
368 u32 ui32Index = HANDLE_TO_INDEX(psBase, hHandle);
369 struct sHandle *psHandle;
371 if (!INDEX_IS_VALID(psBase, ui32Index)) {
372 PVR_DPF(PVR_DBG_ERROR,
373 "GetHandleStructure: Handle index out of range (%u >= %u)",
374 ui32Index, psBase->ui32TotalHandCount);
375 return PVRSRV_ERROR_GENERIC;
378 psHandle = INDEX_TO_HANDLE_PTR(psBase, ui32Index);
379 if (psHandle->eType == PVRSRV_HANDLE_TYPE_NONE) {
380 PVR_DPF(PVR_DBG_ERROR,
381 "GetHandleStructure: Handle not allocated (index: %u)",
383 return PVRSRV_ERROR_GENERIC;
386 if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandle->eType) {
387 PVR_DPF(PVR_DBG_ERROR,
388 "GetHandleStructure: Handle type mismatch (%d != %d)",
389 eType, psHandle->eType);
390 return PVRSRV_ERROR_GENERIC;
393 *ppsHandle = psHandle;
398 static inline void *ParentIfPrivate(struct sHandle *psHandle)
400 return TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
401 ParentHandle(psHandle) : NULL;
404 static inline void InitKey(u32 aKey[HAND_KEY_LEN],
405 struct PVRSRV_HANDLE_BASE *psBase,
406 void *pvData, enum PVRSRV_HANDLE_TYPE eType,
409 PVR_UNREFERENCED_PARAMETER(psBase);
411 aKey[HAND_KEY_DATA] = (u32) pvData;
412 aKey[HAND_KEY_TYPE] = (u32) eType;
413 aKey[HAND_KEY_PARENT] = (u32) hParent;
416 static void FreeHandleArray(struct PVRSRV_HANDLE_BASE *psBase)
418 if (psBase->psHandleArray != NULL) {
419 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
420 psBase->ui32TotalHandCount *
421 sizeof(struct sHandle),
422 psBase->psHandleArray,
423 psBase->hHandBlockAlloc);
424 psBase->psHandleArray = NULL;
428 static enum PVRSRV_ERROR FreeHandle(struct PVRSRV_HANDLE_BASE *psBase,
429 struct sHandle *psHandle)
431 u32 aKey[HAND_KEY_LEN];
432 u32 ui32Index = HANDLE_PTR_TO_INDEX(psBase, psHandle);
433 enum PVRSRV_ERROR eError;
435 InitKey(aKey, psBase, psHandle->pvData, psHandle->eType,
436 ParentIfPrivate(psHandle));
438 if (!TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_MULTI) &&
439 !BATCHED_HANDLE_PARTIALLY_FREE(psHandle)) {
441 hHandle = (void *)HASH_Remove_Extended(psBase->psHashTab, aKey);
443 PVR_ASSERT(hHandle != NULL);
444 PVR_ASSERT(hHandle == INDEX_TO_HANDLE(psBase, ui32Index));
445 PVR_UNREFERENCED_PARAMETER(hHandle);
448 UnlinkFromParent(psBase, psHandle);
450 eError = IterateOverChildren(psBase, psHandle, FreeHandle);
451 if (eError != PVRSRV_OK) {
452 PVR_DPF(PVR_DBG_ERROR,
453 "FreeHandle: Error whilst freeing subhandles (%d)",
458 psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
460 if (BATCHED_HANDLE(psHandle) &&
461 !BATCHED_HANDLE_PARTIALLY_FREE(psHandle)) {
462 SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle);
466 if (!psBase->bPurgingEnabled) {
467 if (psBase->ui32FreeHandCount == 0) {
468 PVR_ASSERT(psBase->ui32FirstFreeIndex == 0);
469 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
471 psBase->ui32FirstFreeIndex = ui32Index;
473 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
474 PVR_ASSERT(INDEX_TO_HANDLE_PTR
476 psBase->ui32LastFreeIndexPlusOne -
477 1)->ui32NextIndexPlusOne == 0);
478 INDEX_TO_HANDLE_PTR(psBase,
479 psBase->ui32LastFreeIndexPlusOne -
480 1)->ui32NextIndexPlusOne =
483 PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0);
484 psBase->ui32LastFreeIndexPlusOne = ui32Index + 1;
487 psBase->ui32FreeHandCount++;
492 static enum PVRSRV_ERROR FreeAllHandles(struct PVRSRV_HANDLE_BASE *psBase)
495 enum PVRSRV_ERROR eError = PVRSRV_OK;
497 if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
500 for (i = 0; i < psBase->ui32TotalHandCount; i++) {
501 struct sHandle *psHandle;
503 psHandle = INDEX_TO_HANDLE_PTR(psBase, i);
505 if (psHandle->eType != PVRSRV_HANDLE_TYPE_NONE) {
506 eError = FreeHandle(psBase, psHandle);
507 if (eError != PVRSRV_OK) {
508 PVR_DPF(PVR_DBG_ERROR,
509 "FreeAllHandles: FreeHandle failed (%d)",
514 if (psBase->ui32FreeHandCount ==
515 psBase->ui32TotalHandCount)
523 static enum PVRSRV_ERROR FreeHandleBase(struct PVRSRV_HANDLE_BASE *psBase)
525 enum PVRSRV_ERROR eError;
527 if (HANDLES_BATCHED(psBase)) {
528 PVR_DPF(PVR_DBG_WARNING,
529 "FreeHandleBase: Uncommitted/Unreleased handle batch");
530 PVRSRVReleaseHandleBatch(psBase);
533 eError = FreeAllHandles(psBase);
534 if (eError != PVRSRV_OK) {
535 PVR_DPF(PVR_DBG_ERROR,
536 "FreeHandleBase: Couldn't free handles (%d)", eError);
540 FreeHandleArray(psBase);
542 if (psBase->psHashTab != NULL)
543 HASH_Delete(psBase->psHashTab);
545 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psBase), psBase,
546 psBase->hBaseBlockAlloc);
551 static inline void *FindHandle(struct PVRSRV_HANDLE_BASE *psBase, void *pvData,
552 enum PVRSRV_HANDLE_TYPE eType, void *hParent)
554 u32 aKey[HAND_KEY_LEN];
556 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
558 InitKey(aKey, psBase, pvData, eType, hParent);
560 return (void *)HASH_Retrieve_Extended(psBase->psHashTab, aKey);
563 static enum PVRSRV_ERROR ReallocMem(void **ppvMem, void **phBlockAlloc,
564 u32 ui32NewSize, u32 ui32OldSize)
566 void *pvOldMem = *ppvMem;
567 void *hOldBlockAlloc = *phBlockAlloc;
568 u32 ui32CopySize = MIN(ui32NewSize, ui32OldSize);
569 void *pvNewMem = NULL;
570 void *hNewBlockAlloc = NULL;
571 enum PVRSRV_ERROR eError;
573 if (ui32NewSize == ui32OldSize)
576 if (ui32NewSize != 0) {
577 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
578 ui32NewSize, &pvNewMem, &hNewBlockAlloc);
579 if (eError != PVRSRV_OK) {
580 PVR_DPF(PVR_DBG_ERROR,
581 "ReallocMem: Couldn't allocate new memory area (%d)",
587 if (ui32CopySize != 0)
588 OSMemCopy(pvNewMem, pvOldMem, ui32CopySize);
590 if (ui32OldSize != 0)
591 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32OldSize, pvOldMem,
595 *phBlockAlloc = hNewBlockAlloc;
600 static inline enum PVRSRV_ERROR ReallocHandleArray(struct PVRSRV_HANDLE_BASE
601 *psBase, u32 ui32NewCount,
604 return ReallocMem((void **)&psBase->psHandleArray,
605 &psBase->hHandBlockAlloc,
606 ui32NewCount * sizeof(struct sHandle),
607 ui32OldCount * sizeof(struct sHandle));
610 static enum PVRSRV_ERROR IncreaseHandleArraySize(struct PVRSRV_HANDLE_BASE
611 *psBase, u32 ui32Delta)
613 enum PVRSRV_ERROR eError;
614 struct sHandle *psHandle;
615 u32 ui32DeltaAdjusted =
616 ROUND_UP_TO_MULTIPLE(ui32Delta, HANDLE_BLOCK_SIZE);
617 u32 ui32NewTotalHandCount =
618 psBase->ui32TotalHandCount + ui32DeltaAdjusted;
620 PVR_ASSERT(ui32Delta != 0);
622 if (ui32NewTotalHandCount > psBase->ui32MaxIndexPlusOne ||
623 ui32NewTotalHandCount <= psBase->ui32TotalHandCount) {
624 ui32NewTotalHandCount = psBase->ui32MaxIndexPlusOne;
627 ui32NewTotalHandCount - psBase->ui32TotalHandCount;
629 if (ui32DeltaAdjusted < ui32Delta) {
630 PVR_DPF(PVR_DBG_ERROR, "IncreaseHandleArraySize: "
631 "Maximum handle limit reached (%d)",
632 psBase->ui32MaxIndexPlusOne);
633 return PVRSRV_ERROR_OUT_OF_MEMORY;
637 PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta);
639 eError = ReallocHandleArray(psBase, ui32NewTotalHandCount,
640 psBase->ui32TotalHandCount);
641 if (eError != PVRSRV_OK) {
642 PVR_DPF(PVR_DBG_ERROR, "IncreaseHandleArraySize: "
643 "ReallocHandleArray failed (%d)",
648 for (psHandle = psBase->psHandleArray + psBase->ui32TotalHandCount;
649 psHandle < psBase->psHandleArray + ui32NewTotalHandCount;
651 psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
652 psHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
653 psHandle->ui32NextIndexPlusOne = 0;
656 psBase->ui32FreeHandCount += ui32DeltaAdjusted;
658 if (psBase->ui32FirstFreeIndex == 0) {
659 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
661 psBase->ui32FirstFreeIndex = psBase->ui32TotalHandCount;
663 if (!psBase->bPurgingEnabled) {
664 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
665 PVR_ASSERT(INDEX_TO_HANDLE_PTR
667 psBase->ui32LastFreeIndexPlusOne -
668 1)->ui32NextIndexPlusOne == 0);
670 INDEX_TO_HANDLE_PTR(psBase,
671 psBase->ui32LastFreeIndexPlusOne -
672 1)->ui32NextIndexPlusOne =
673 psBase->ui32TotalHandCount + 1;
677 if (!psBase->bPurgingEnabled)
678 psBase->ui32LastFreeIndexPlusOne = ui32NewTotalHandCount;
680 psBase->ui32TotalHandCount = ui32NewTotalHandCount;
685 static enum PVRSRV_ERROR EnsureFreeHandles(struct PVRSRV_HANDLE_BASE *psBase,
688 enum PVRSRV_ERROR eError;
690 if (ui32Free > psBase->ui32FreeHandCount) {
691 u32 ui32FreeHandDelta =
692 ui32Free - psBase->ui32FreeHandCount;
693 eError = IncreaseHandleArraySize(psBase, ui32FreeHandDelta);
694 if (eError != PVRSRV_OK) {
695 PVR_DPF(PVR_DBG_ERROR, "EnsureFreeHandles: "
696 "Couldn't allocate %u handles to ensure %u "
697 "free handles (IncreaseHandleArraySize "
698 "failed with error %d)",
699 ui32FreeHandDelta, ui32Free, eError);
708 static enum PVRSRV_ERROR AllocHandle(struct PVRSRV_HANDLE_BASE *psBase,
709 void **phHandle, void *pvData,
710 enum PVRSRV_HANDLE_TYPE eType,
711 enum PVRSRV_HANDLE_ALLOC_FLAG eFlag,
715 struct sHandle *psNewHandle = NULL;
717 u32 aKey[HAND_KEY_LEN];
718 enum PVRSRV_ERROR eError;
720 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
722 PVR_ASSERT(psBase->psHashTab != NULL);
724 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
725 PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == NULL);
727 if (psBase->ui32FreeHandCount == 0 && HANDLES_BATCHED(psBase))
728 PVR_DPF(PVR_DBG_WARNING, "AllocHandle: "
729 "Handle batch size (%u) was too small, "
730 "allocating additional space",
731 psBase->ui32HandBatchSize);
733 eError = EnsureFreeHandles(psBase, 1);
734 if (eError != PVRSRV_OK) {
735 PVR_DPF(PVR_DBG_ERROR,
736 "AllocHandle: EnsureFreeHandles failed (%d)", eError);
739 PVR_ASSERT(psBase->ui32FreeHandCount != 0);
741 if (!psBase->bPurgingEnabled) {
742 ui32NewIndex = psBase->ui32FirstFreeIndex;
743 psNewHandle = INDEX_TO_HANDLE_PTR(psBase, ui32NewIndex);
745 for (ui32NewIndex = psBase->ui32FirstFreeIndex;
746 ui32NewIndex < psBase->ui32TotalHandCount;
748 psNewHandle = INDEX_TO_HANDLE_PTR(psBase, ui32NewIndex);
749 if (HANDLE_STRUCT_IS_FREE(psNewHandle))
753 psBase->ui32FirstFreeIndex = 0;
754 PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount);
756 PVR_ASSERT(psNewHandle != NULL);
758 hHandle = INDEX_TO_HANDLE(psBase, ui32NewIndex);
760 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) {
762 InitKey(aKey, psBase, pvData, eType, hParent);
764 if (!HASH_Insert_Extended
765 (psBase->psHashTab, aKey, (u32) hHandle)) {
766 PVR_DPF(PVR_DBG_ERROR, "AllocHandle: "
767 "Couldn't add handle to hash table");
769 return PVRSRV_ERROR_GENERIC;
773 psBase->ui32FreeHandCount--;
775 if (!psBase->bPurgingEnabled) {
776 if (psBase->ui32FreeHandCount == 0) {
777 PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex);
778 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne ==
781 psBase->ui32LastFreeIndexPlusOne = 0;
782 psBase->ui32FirstFreeIndex = 0;
784 psBase->ui32FirstFreeIndex =
785 (psNewHandle->ui32NextIndexPlusOne ==
787 1 : psNewHandle->ui32NextIndexPlusOne - 1;
791 psNewHandle->eType = eType;
792 psNewHandle->pvData = pvData;
793 psNewHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
794 psNewHandle->eFlag = eFlag;
795 psNewHandle->ui32Index = ui32NewIndex;
797 InitParentList(psBase, psNewHandle);
798 PVR_ASSERT(NoChildren(psBase, psNewHandle));
800 InitChildEntry(psBase, psNewHandle);
801 PVR_ASSERT(NoParent(psBase, psNewHandle));
803 if (HANDLES_BATCHED(psBase)) {
805 psNewHandle->ui32NextIndexPlusOne =
806 psBase->ui32FirstBatchIndexPlusOne;
808 psBase->ui32FirstBatchIndexPlusOne = ui32NewIndex + 1;
810 SET_BATCHED_HANDLE(psNewHandle);
812 psNewHandle->ui32NextIndexPlusOne = 0;
820 enum PVRSRV_ERROR PVRSRVAllocHandle(struct PVRSRV_HANDLE_BASE *psBase,
821 void **phHandle, void *pvData,
822 enum PVRSRV_HANDLE_TYPE eType,
823 enum PVRSRV_HANDLE_ALLOC_FLAG eFlag)
826 enum PVRSRV_ERROR eError;
830 if (HANDLES_BATCHED(psBase))
831 psBase->ui32BatchHandAllocFailures++;
833 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
835 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) {
836 hHandle = FindHandle(psBase, pvData, eType, NULL);
837 if (hHandle != NULL) {
838 struct sHandle *psHandle;
841 GetHandleStructure(psBase, &psHandle, hHandle,
843 if (eError != PVRSRV_OK) {
844 PVR_DPF(PVR_DBG_ERROR,
845 "PVRSRVAllocHandle: "
846 "Lookup of existing handle failed");
850 if (TEST_FLAG(psHandle->eFlag & eFlag,
851 PVRSRV_HANDLE_ALLOC_FLAG_SHARED)) {
856 return PVRSRV_ERROR_GENERIC;
860 eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, NULL);
863 if (HANDLES_BATCHED(psBase) && (eError == PVRSRV_OK))
864 psBase->ui32BatchHandAllocFailures--;
869 enum PVRSRV_ERROR PVRSRVAllocSubHandle(struct PVRSRV_HANDLE_BASE *psBase,
870 void **phHandle, void *pvData,
871 enum PVRSRV_HANDLE_TYPE eType,
872 enum PVRSRV_HANDLE_ALLOC_FLAG eFlag,
875 struct sHandle *psPHand;
876 struct sHandle *psCHand;
877 enum PVRSRV_ERROR eError;
883 if (HANDLES_BATCHED(psBase))
885 psBase->ui32BatchHandAllocFailures++;
887 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
889 hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
892 eError = GetHandleStructure(psBase, &psPHand, hParent,
893 PVRSRV_HANDLE_TYPE_NONE);
894 if (eError != PVRSRV_OK)
895 return PVRSRV_ERROR_GENERIC;
897 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) {
899 hHandle = FindHandle(psBase, pvData, eType, hParentKey);
900 if (hHandle != NULL) {
901 struct sHandle *psCHandle;
902 enum PVRSRV_ERROR eErr;
904 eErr = GetHandleStructure(psBase, &psCHandle, hHandle,
906 if (eErr != PVRSRV_OK) {
907 PVR_DPF(PVR_DBG_ERROR, "PVRSRVAllocSubHandle: "
908 "Lookup of existing handle failed");
912 PVR_ASSERT(hParentKey != NULL &&
913 ParentHandle(HANDLE_TO_HANDLE_PTR
914 (psBase, hHandle)) == hParent);
916 if (TEST_FLAG(psCHandle->eFlag & eFlag,
917 PVRSRV_HANDLE_ALLOC_FLAG_SHARED) &&
918 ParentHandle(HANDLE_TO_HANDLE_PTR(psBase, hHandle))
923 return PVRSRV_ERROR_GENERIC;
927 eError = AllocHandle(psBase, &hHandle, pvData, eType, eFlag,
929 if (eError != PVRSRV_OK)
932 psPHand = HANDLE_TO_HANDLE_PTR(psBase, hParent);
934 psCHand = HANDLE_TO_HANDLE_PTR(psBase, hHandle);
936 AdoptChild(psBase, psPHand, psCHand);
941 if (HANDLES_BATCHED(psBase))
942 psBase->ui32BatchHandAllocFailures--;
947 enum PVRSRV_ERROR PVRSRVFindHandle(struct PVRSRV_HANDLE_BASE *psBase,
948 void **phHandle, void *pvData,
949 enum PVRSRV_HANDLE_TYPE eType)
953 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
955 hHandle = (void *)FindHandle(psBase, pvData, eType, NULL);
957 return PVRSRV_ERROR_GENERIC;
964 enum PVRSRV_ERROR PVRSRVLookupHandleAnyType(struct PVRSRV_HANDLE_BASE *psBase,
966 enum PVRSRV_HANDLE_TYPE *peType,
969 struct sHandle *psHandle;
970 enum PVRSRV_ERROR eError;
972 eError = GetHandleStructure(psBase, &psHandle, hHandle,
973 PVRSRV_HANDLE_TYPE_NONE);
974 if (eError != PVRSRV_OK) {
975 PVR_DPF(PVR_DBG_ERROR, "PVRSRVLookupHandleAnyType: "
976 "Error looking up handle (%d)",
981 *ppvData = psHandle->pvData;
982 *peType = psHandle->eType;
987 enum PVRSRV_ERROR PVRSRVLookupHandle(struct PVRSRV_HANDLE_BASE *psBase,
988 void **ppvData, void *hHandle,
989 enum PVRSRV_HANDLE_TYPE eType)
991 struct sHandle *psHandle;
992 enum PVRSRV_ERROR eError;
994 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
996 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
997 if (eError != PVRSRV_OK) {
998 PVR_DPF(PVR_DBG_ERROR,
999 "PVRSRVLookupHandle: Error looking up handle (%d)",
1004 *ppvData = psHandle->pvData;
1009 enum PVRSRV_ERROR PVRSRVLookupSubHandle(struct PVRSRV_HANDLE_BASE *psBase,
1010 void **ppvData, void *hHandle,
1011 enum PVRSRV_HANDLE_TYPE eType,
1014 struct sHandle *psPHand;
1015 struct sHandle *psCHand;
1016 enum PVRSRV_ERROR eError;
1018 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1020 eError = GetHandleStructure(psBase, &psCHand, hHandle, eType);
1021 if (eError != PVRSRV_OK) {
1022 PVR_DPF(PVR_DBG_ERROR, "PVRSRVLookupSubHandle: "
1023 "Error looking up subhandle (%d)",
1028 for (psPHand = psCHand; ParentHandle(psPHand) != hAncestor;) {
1030 GetHandleStructure(psBase, &psPHand, ParentHandle(psPHand),
1031 PVRSRV_HANDLE_TYPE_NONE);
1032 if (eError != PVRSRV_OK) {
1033 PVR_DPF(PVR_DBG_ERROR, "PVRSRVLookupSubHandle: "
1034 "Subhandle doesn't belong to given ancestor");
1035 return PVRSRV_ERROR_GENERIC;
1039 *ppvData = psCHand->pvData;
1044 enum PVRSRV_ERROR PVRSRVGetParentHandle(struct PVRSRV_HANDLE_BASE *psBase,
1045 void **phParent, void *hHandle,
1046 enum PVRSRV_HANDLE_TYPE eType)
1048 struct sHandle *psHandle;
1049 enum PVRSRV_ERROR eError;
1051 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1053 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
1054 if (eError != PVRSRV_OK) {
1055 PVR_DPF(PVR_DBG_ERROR, "PVRSRVGetParentHandle: "
1056 "Error looking up subhandle (%d)",
1061 *phParent = ParentHandle(psHandle);
1066 enum PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(
1067 struct PVRSRV_HANDLE_BASE *psBase,
1068 void **ppvData, void *hHandle,
1069 enum PVRSRV_HANDLE_TYPE eType)
1071 struct sHandle *psHandle;
1072 enum PVRSRV_ERROR eError;
1074 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1076 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
1077 if (eError != PVRSRV_OK) {
1078 PVR_DPF(PVR_DBG_ERROR, "PVRSRVLookupAndReleaseHandle: "
1079 "Error looking up handle (%d)",
1084 *ppvData = psHandle->pvData;
1086 eError = FreeHandle(psBase, psHandle);
1091 enum PVRSRV_ERROR PVRSRVReleaseHandle(struct PVRSRV_HANDLE_BASE *psBase,
1092 void *hHandle, enum PVRSRV_HANDLE_TYPE eType)
1094 struct sHandle *psHandle;
1095 enum PVRSRV_ERROR eError;
1097 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1099 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
1100 if (eError != PVRSRV_OK) {
1101 PVR_DPF(PVR_DBG_ERROR,
1102 "PVRSRVReleaseHandle: Error looking up handle (%d)",
1107 eError = FreeHandle(psBase, psHandle);
1112 enum PVRSRV_ERROR PVRSRVNewHandleBatch(struct PVRSRV_HANDLE_BASE *psBase,
1115 enum PVRSRV_ERROR eError;
1117 if (HANDLES_BATCHED(psBase)) {
1118 PVR_DPF(PVR_DBG_ERROR, "PVRSRVNewHandleBatch: "
1119 "There is a handle batch already in use (size %u)",
1120 psBase->ui32HandBatchSize);
1121 return PVRSRV_ERROR_GENERIC;
1124 if (ui32BatchSize == 0) {
1125 PVR_DPF(PVR_DBG_ERROR,
1126 "PVRSRVNewHandleBatch: Invalid batch size (%u)",
1128 return PVRSRV_ERROR_INVALID_PARAMS;
1131 eError = EnsureFreeHandles(psBase, ui32BatchSize);
1132 if (eError != PVRSRV_OK) {
1133 PVR_DPF(PVR_DBG_ERROR, "PVRSRVNewHandleBatch: "
1134 "EnsureFreeHandles failed (error %d)",
1139 psBase->ui32HandBatchSize = ui32BatchSize;
1140 psBase->ui32TotalHandCountPreBatch = psBase->ui32TotalHandCount;
1142 PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0);
1143 PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0);
1144 PVR_ASSERT(HANDLES_BATCHED(psBase));
1149 static enum PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(
1150 struct PVRSRV_HANDLE_BASE *psBase, IMG_BOOL bCommit)
1152 u32 ui32IndexPlusOne;
1153 IMG_BOOL bCommitBatch = bCommit;
1155 if (!HANDLES_BATCHED(psBase)) {
1156 PVR_DPF(PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: "
1157 "There is no handle batch");
1158 return PVRSRV_ERROR_INVALID_PARAMS;
1162 if (psBase->ui32BatchHandAllocFailures != 0) {
1164 PVR_DPF(PVR_DBG_ERROR,
1165 "PVRSRVHandleBatchCommitOrRelease: "
1166 "Attempting to commit batch with handle "
1167 "allocation failures.");
1168 bCommitBatch = IMG_FALSE;
1171 PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit);
1173 ui32IndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
1174 while (ui32IndexPlusOne != 0) {
1175 struct sHandle *psHandle =
1176 INDEX_TO_HANDLE_PTR(psBase, ui32IndexPlusOne - 1);
1177 u32 ui32NextIndexPlusOne =
1178 psHandle->ui32NextIndexPlusOne;
1179 PVR_ASSERT(BATCHED_HANDLE(psHandle));
1181 psHandle->ui32NextIndexPlusOne = 0;
1183 if (!bCommitBatch || BATCHED_HANDLE_PARTIALLY_FREE(psHandle)) {
1184 enum PVRSRV_ERROR eError;
1186 if (!BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
1187 SET_UNBATCHED_HANDLE(psHandle);
1189 eError = FreeHandle(psBase, psHandle);
1190 if (eError != PVRSRV_OK)
1191 PVR_DPF(PVR_DBG_ERROR,
1192 "PVRSRVHandleBatchCommitOrRelease: "
1193 "Error freeing handle (%d)",
1195 PVR_ASSERT(eError == PVRSRV_OK);
1197 SET_UNBATCHED_HANDLE(psHandle);
1200 ui32IndexPlusOne = ui32NextIndexPlusOne;
1203 #ifdef CONFIG_PVR_DEBUG_EXTRA
1204 if (psBase->ui32TotalHandCountPreBatch != psBase->ui32TotalHandCount) {
1206 psBase->ui32TotalHandCount -
1207 psBase->ui32TotalHandCountPreBatch;
1209 PVR_ASSERT(psBase->ui32TotalHandCount >
1210 psBase->ui32TotalHandCountPreBatch);
1212 PVR_DPF(PVR_DBG_WARNING,
1213 "PVRSRVHandleBatchCommitOrRelease: "
1214 "The batch size was too small. "
1215 "Batch size was %u, but needs to be %u",
1216 psBase->ui32HandBatchSize,
1217 psBase->ui32HandBatchSize + ui32Delta);
1222 psBase->ui32HandBatchSize = 0;
1223 psBase->ui32FirstBatchIndexPlusOne = 0;
1224 psBase->ui32TotalHandCountPreBatch = 0;
1225 psBase->ui32BatchHandAllocFailures = 0;
1227 if (psBase->ui32BatchHandAllocFailures != 0 && bCommit) {
1228 PVR_ASSERT(!bCommitBatch);
1230 return PVRSRV_ERROR_GENERIC;
1236 enum PVRSRV_ERROR PVRSRVCommitHandleBatch(struct PVRSRV_HANDLE_BASE *psBase)
1238 return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE);
1241 void PVRSRVReleaseHandleBatch(struct PVRSRV_HANDLE_BASE *psBase)
1243 (void)PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE);
1246 enum PVRSRV_ERROR PVRSRVSetMaxHandle(struct PVRSRV_HANDLE_BASE *psBase,
1249 if (HANDLES_BATCHED(psBase)) {
1250 PVR_DPF(PVR_DBG_ERROR, "PVRSRVSetMaxHandle: "
1251 "Limit cannot be set whilst in batch mode");
1252 return PVRSRV_ERROR_INVALID_PARAMS;
1255 if (ui32MaxHandle == 0 || ui32MaxHandle > DEFAULT_MAX_HANDLE) {
1256 PVR_DPF(PVR_DBG_ERROR, "PVRSRVSetMaxHandle: "
1257 "Limit must be between %u and %u, inclusive",
1258 0, DEFAULT_MAX_HANDLE);
1260 return PVRSRV_ERROR_INVALID_PARAMS;
1263 if (psBase->ui32TotalHandCount != 0) {
1264 PVR_DPF(PVR_DBG_ERROR, "PVRSRVSetMaxHandle: "
1265 "Limit cannot be set becuase handles "
1266 "have already been allocated");
1268 return PVRSRV_ERROR_INVALID_PARAMS;
1271 psBase->ui32MaxIndexPlusOne = ui32MaxHandle;
1276 u32 PVRSRVGetMaxHandle(struct PVRSRV_HANDLE_BASE *psBase)
1278 return psBase->ui32MaxIndexPlusOne;
1281 enum PVRSRV_ERROR PVRSRVEnableHandlePurging(struct PVRSRV_HANDLE_BASE *psBase)
1283 if (psBase->bPurgingEnabled) {
1284 PVR_DPF(PVR_DBG_WARNING,
1285 "PVRSRVEnableHandlePurging: Purging already enabled");
1289 if (psBase->ui32TotalHandCount != 0) {
1290 PVR_DPF(PVR_DBG_ERROR, "PVRSRVEnableHandlePurging: "
1291 "Handles have already been allocated");
1292 return PVRSRV_ERROR_INVALID_PARAMS;
1295 psBase->bPurgingEnabled = IMG_TRUE;
1300 enum PVRSRV_ERROR PVRSRVPurgeHandles(struct PVRSRV_HANDLE_BASE *psBase)
1303 u32 ui32NewHandCount;
1305 if (!psBase->bPurgingEnabled) {
1306 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPurgeHandles: "
1307 "Purging not enabled for this handle base");
1308 return PVRSRV_ERROR_NOT_SUPPORTED;
1311 if (HANDLES_BATCHED(psBase)) {
1312 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPurgeHandles: "
1313 "Purging not allowed whilst in batch mode");
1314 return PVRSRV_ERROR_INVALID_PARAMS;
1317 for (ui32Handle = psBase->ui32TotalHandCount; ui32Handle != 0;
1319 struct sHandle *psHandle =
1320 HANDLE_TO_HANDLE_PTR(psBase, ui32Handle);
1321 if (!HANDLE_STRUCT_IS_FREE(psHandle))
1325 ui32NewHandCount = ROUND_UP_TO_MULTIPLE(ui32Handle, HANDLE_BLOCK_SIZE);
1327 if (ui32NewHandCount >= ui32Handle
1328 && ui32NewHandCount <= (psBase->ui32TotalHandCount / 2)) {
1329 u32 ui32Delta = psBase->ui32TotalHandCount - ui32NewHandCount;
1330 enum PVRSRV_ERROR eError;
1333 ReallocHandleArray(psBase, ui32NewHandCount,
1334 psBase->ui32TotalHandCount);
1335 if (eError != PVRSRV_OK)
1338 psBase->ui32TotalHandCount = ui32NewHandCount;
1339 psBase->ui32FreeHandCount -= ui32Delta;
1340 psBase->ui32FirstFreeIndex = 0;
1346 enum PVRSRV_ERROR PVRSRVAllocHandleBase(struct PVRSRV_HANDLE_BASE **ppsBase)
1348 struct PVRSRV_HANDLE_BASE *psBase;
1350 enum PVRSRV_ERROR eError;
1352 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
1353 sizeof(*psBase), (void **)&psBase, &hBlockAlloc);
1354 if (eError != PVRSRV_OK) {
1355 PVR_DPF(PVR_DBG_ERROR, "PVRSRVAllocHandleBase: "
1356 "Couldn't allocate handle base (%d)",
1360 OSMemSet(psBase, 0, sizeof(*psBase));
1363 HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE,
1364 HAND_KEY_LEN * sizeof(u32),
1365 HASH_Func_Default, HASH_Key_Comp_Default);
1366 if (psBase->psHashTab == NULL) {
1367 PVR_DPF(PVR_DBG_ERROR, "PVRSRVAllocHandleBase: "
1368 "Couldn't create data pointer hash table\n");
1372 psBase->hBaseBlockAlloc = hBlockAlloc;
1374 psBase->ui32MaxIndexPlusOne = DEFAULT_MAX_INDEX_PLUS_ONE;
1380 (void)PVRSRVFreeHandleBase(psBase);
1381 return PVRSRV_ERROR_GENERIC;
1384 enum PVRSRV_ERROR PVRSRVFreeHandleBase(struct PVRSRV_HANDLE_BASE *psBase)
1386 enum PVRSRV_ERROR eError;
1388 PVR_ASSERT(psBase != gpsKernelHandleBase);
1390 eError = FreeHandleBase(psBase);
1391 if (eError != PVRSRV_OK)
1392 PVR_DPF(PVR_DBG_ERROR,
1393 "PVRSRVFreeHandleBase: FreeHandleBase failed (%d)",
1399 enum PVRSRV_ERROR PVRSRVHandleInit(void)
1401 enum PVRSRV_ERROR eError;
1403 PVR_ASSERT(gpsKernelHandleBase == NULL);
1405 eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
1406 if (eError != PVRSRV_OK) {
1407 PVR_DPF(PVR_DBG_ERROR,
1408 "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%d)",
1413 eError = PVRSRVEnableHandlePurging(gpsKernelHandleBase);
1414 if (eError != PVRSRV_OK) {
1415 PVR_DPF(PVR_DBG_ERROR, "PVRSRVHandleInit: "
1416 "PVRSRVEnableHandlePurging failed (%d)",
1423 (void)PVRSRVHandleDeInit();
1427 enum PVRSRV_ERROR PVRSRVHandleDeInit(void)
1429 enum PVRSRV_ERROR eError = PVRSRV_OK;
1431 if (gpsKernelHandleBase != NULL) {
1432 eError = FreeHandleBase(gpsKernelHandleBase);
1433 if (eError == PVRSRV_OK) {
1434 gpsKernelHandleBase = NULL;
1436 PVR_DPF(PVR_DBG_ERROR, "PVRSRVHandleDeInit: "
1437 "FreeHandleBase failed (%d)",