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)",
585 if (ui32OldSize != 0)
586 OSMemCopy(pvNewMem, pvOldMem, ui32CopySize);
589 if (ui32OldSize != 0)
590 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32OldSize, pvOldMem,
594 *phBlockAlloc = hNewBlockAlloc;
599 static inline enum PVRSRV_ERROR ReallocHandleArray(struct PVRSRV_HANDLE_BASE
600 *psBase, u32 ui32NewCount,
603 return ReallocMem((void **)&psBase->psHandleArray,
604 &psBase->hHandBlockAlloc,
605 ui32NewCount * sizeof(struct sHandle),
606 ui32OldCount * sizeof(struct sHandle));
609 static enum PVRSRV_ERROR IncreaseHandleArraySize(struct PVRSRV_HANDLE_BASE
610 *psBase, u32 ui32Delta)
612 enum PVRSRV_ERROR eError;
613 struct sHandle *psHandle;
614 u32 ui32DeltaAdjusted =
615 ROUND_UP_TO_MULTIPLE(ui32Delta, HANDLE_BLOCK_SIZE);
616 u32 ui32NewTotalHandCount =
617 psBase->ui32TotalHandCount + ui32DeltaAdjusted;
619 PVR_ASSERT(ui32Delta != 0);
621 if (ui32NewTotalHandCount > psBase->ui32MaxIndexPlusOne ||
622 ui32NewTotalHandCount <= psBase->ui32TotalHandCount) {
623 ui32NewTotalHandCount = psBase->ui32MaxIndexPlusOne;
626 ui32NewTotalHandCount - psBase->ui32TotalHandCount;
628 if (ui32DeltaAdjusted < ui32Delta) {
629 PVR_DPF(PVR_DBG_ERROR, "IncreaseHandleArraySize: "
630 "Maximum handle limit reached (%d)",
631 psBase->ui32MaxIndexPlusOne);
632 return PVRSRV_ERROR_OUT_OF_MEMORY;
636 PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta);
638 eError = ReallocHandleArray(psBase, ui32NewTotalHandCount,
639 psBase->ui32TotalHandCount);
640 if (eError != PVRSRV_OK) {
641 PVR_DPF(PVR_DBG_ERROR, "IncreaseHandleArraySize: "
642 "ReallocHandleArray failed (%d)",
647 for (psHandle = psBase->psHandleArray + psBase->ui32TotalHandCount;
648 psHandle < psBase->psHandleArray + ui32NewTotalHandCount;
650 psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
651 psHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
652 psHandle->ui32NextIndexPlusOne = 0;
655 psBase->ui32FreeHandCount += ui32DeltaAdjusted;
657 if (psBase->ui32FirstFreeIndex == 0) {
658 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
660 psBase->ui32FirstFreeIndex = psBase->ui32TotalHandCount;
662 if (!psBase->bPurgingEnabled) {
663 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
664 PVR_ASSERT(INDEX_TO_HANDLE_PTR
666 psBase->ui32LastFreeIndexPlusOne -
667 1)->ui32NextIndexPlusOne == 0);
669 INDEX_TO_HANDLE_PTR(psBase,
670 psBase->ui32LastFreeIndexPlusOne -
671 1)->ui32NextIndexPlusOne =
672 psBase->ui32TotalHandCount + 1;
676 if (!psBase->bPurgingEnabled)
677 psBase->ui32LastFreeIndexPlusOne = ui32NewTotalHandCount;
679 psBase->ui32TotalHandCount = ui32NewTotalHandCount;
684 static enum PVRSRV_ERROR EnsureFreeHandles(struct PVRSRV_HANDLE_BASE *psBase,
687 enum PVRSRV_ERROR eError;
689 if (ui32Free > psBase->ui32FreeHandCount) {
690 u32 ui32FreeHandDelta =
691 ui32Free - psBase->ui32FreeHandCount;
692 eError = IncreaseHandleArraySize(psBase, ui32FreeHandDelta);
693 if (eError != PVRSRV_OK) {
694 PVR_DPF(PVR_DBG_ERROR, "EnsureFreeHandles: "
695 "Couldn't allocate %u handles to ensure %u "
696 "free handles (IncreaseHandleArraySize "
697 "failed with error %d)",
698 ui32FreeHandDelta, ui32Free, eError);
707 static enum PVRSRV_ERROR AllocHandle(struct PVRSRV_HANDLE_BASE *psBase,
708 void **phHandle, void *pvData,
709 enum PVRSRV_HANDLE_TYPE eType,
710 enum PVRSRV_HANDLE_ALLOC_FLAG eFlag,
714 struct sHandle *psNewHandle = NULL;
716 u32 aKey[HAND_KEY_LEN];
717 enum PVRSRV_ERROR eError;
719 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
721 PVR_ASSERT(psBase->psHashTab != NULL);
723 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
724 PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == NULL);
726 if (psBase->ui32FreeHandCount == 0 && HANDLES_BATCHED(psBase))
727 PVR_DPF(PVR_DBG_WARNING, "AllocHandle: "
728 "Handle batch size (%u) was too small, "
729 "allocating additional space",
730 psBase->ui32HandBatchSize);
732 eError = EnsureFreeHandles(psBase, 1);
733 if (eError != PVRSRV_OK) {
734 PVR_DPF(PVR_DBG_ERROR,
735 "AllocHandle: EnsureFreeHandles failed (%d)", eError);
738 PVR_ASSERT(psBase->ui32FreeHandCount != 0);
740 if (!psBase->bPurgingEnabled) {
741 ui32NewIndex = psBase->ui32FirstFreeIndex;
742 psNewHandle = INDEX_TO_HANDLE_PTR(psBase, ui32NewIndex);
744 for (ui32NewIndex = psBase->ui32FirstFreeIndex;
745 ui32NewIndex < psBase->ui32TotalHandCount;
747 psNewHandle = INDEX_TO_HANDLE_PTR(psBase, ui32NewIndex);
748 if (HANDLE_STRUCT_IS_FREE(psNewHandle))
752 psBase->ui32FirstFreeIndex = 0;
753 PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount);
755 PVR_ASSERT(psNewHandle != NULL);
757 hHandle = INDEX_TO_HANDLE(psBase, ui32NewIndex);
759 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) {
761 InitKey(aKey, psBase, pvData, eType, hParent);
763 if (!HASH_Insert_Extended
764 (psBase->psHashTab, aKey, (u32) hHandle)) {
765 PVR_DPF(PVR_DBG_ERROR, "AllocHandle: "
766 "Couldn't add handle to hash table");
768 return PVRSRV_ERROR_GENERIC;
772 psBase->ui32FreeHandCount--;
774 if (!psBase->bPurgingEnabled) {
775 if (psBase->ui32FreeHandCount == 0) {
776 PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex);
777 PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne ==
780 psBase->ui32LastFreeIndexPlusOne = 0;
781 psBase->ui32FirstFreeIndex = 0;
783 psBase->ui32FirstFreeIndex =
784 (psNewHandle->ui32NextIndexPlusOne ==
786 1 : psNewHandle->ui32NextIndexPlusOne - 1;
790 psNewHandle->eType = eType;
791 psNewHandle->pvData = pvData;
792 psNewHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
793 psNewHandle->eFlag = eFlag;
794 psNewHandle->ui32Index = ui32NewIndex;
796 InitParentList(psBase, psNewHandle);
797 PVR_ASSERT(NoChildren(psBase, psNewHandle));
799 InitChildEntry(psBase, psNewHandle);
800 PVR_ASSERT(NoParent(psBase, psNewHandle));
802 if (HANDLES_BATCHED(psBase)) {
804 psNewHandle->ui32NextIndexPlusOne =
805 psBase->ui32FirstBatchIndexPlusOne;
807 psBase->ui32FirstBatchIndexPlusOne = ui32NewIndex + 1;
809 SET_BATCHED_HANDLE(psNewHandle);
811 psNewHandle->ui32NextIndexPlusOne = 0;
819 enum PVRSRV_ERROR PVRSRVAllocHandle(struct PVRSRV_HANDLE_BASE *psBase,
820 void **phHandle, void *pvData,
821 enum PVRSRV_HANDLE_TYPE eType,
822 enum PVRSRV_HANDLE_ALLOC_FLAG eFlag)
825 enum PVRSRV_ERROR eError;
829 if (HANDLES_BATCHED(psBase))
830 psBase->ui32BatchHandAllocFailures++;
832 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
834 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) {
835 hHandle = FindHandle(psBase, pvData, eType, NULL);
836 if (hHandle != NULL) {
837 struct sHandle *psHandle;
840 GetHandleStructure(psBase, &psHandle, hHandle,
842 if (eError != PVRSRV_OK) {
843 PVR_DPF(PVR_DBG_ERROR,
844 "PVRSRVAllocHandle: "
845 "Lookup of existing handle failed");
849 if (TEST_FLAG(psHandle->eFlag & eFlag,
850 PVRSRV_HANDLE_ALLOC_FLAG_SHARED)) {
855 return PVRSRV_ERROR_GENERIC;
859 eError = AllocHandle(psBase, phHandle, pvData, eType, eFlag, NULL);
862 if (HANDLES_BATCHED(psBase) && (eError == PVRSRV_OK))
863 psBase->ui32BatchHandAllocFailures--;
868 enum PVRSRV_ERROR PVRSRVAllocSubHandle(struct PVRSRV_HANDLE_BASE *psBase,
869 void **phHandle, void *pvData,
870 enum PVRSRV_HANDLE_TYPE eType,
871 enum PVRSRV_HANDLE_ALLOC_FLAG eFlag,
874 struct sHandle *psPHand;
875 struct sHandle *psCHand;
876 enum PVRSRV_ERROR eError;
882 if (HANDLES_BATCHED(psBase))
884 psBase->ui32BatchHandAllocFailures++;
886 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
888 hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
891 eError = GetHandleStructure(psBase, &psPHand, hParent,
892 PVRSRV_HANDLE_TYPE_NONE);
893 if (eError != PVRSRV_OK)
894 return PVRSRV_ERROR_GENERIC;
896 if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI)) {
898 hHandle = FindHandle(psBase, pvData, eType, hParentKey);
899 if (hHandle != NULL) {
900 struct sHandle *psCHandle;
901 enum PVRSRV_ERROR eErr;
903 eErr = GetHandleStructure(psBase, &psCHandle, hHandle,
905 if (eErr != PVRSRV_OK) {
906 PVR_DPF(PVR_DBG_ERROR, "PVRSRVAllocSubHandle: "
907 "Lookup of existing handle failed");
911 PVR_ASSERT(hParentKey != NULL &&
912 ParentHandle(HANDLE_TO_HANDLE_PTR
913 (psBase, hHandle)) == hParent);
915 if (TEST_FLAG(psCHandle->eFlag & eFlag,
916 PVRSRV_HANDLE_ALLOC_FLAG_SHARED) &&
917 ParentHandle(HANDLE_TO_HANDLE_PTR(psBase, hHandle))
922 return PVRSRV_ERROR_GENERIC;
926 eError = AllocHandle(psBase, &hHandle, pvData, eType, eFlag,
928 if (eError != PVRSRV_OK)
931 psPHand = HANDLE_TO_HANDLE_PTR(psBase, hParent);
933 psCHand = HANDLE_TO_HANDLE_PTR(psBase, hHandle);
935 AdoptChild(psBase, psPHand, psCHand);
940 if (HANDLES_BATCHED(psBase))
941 psBase->ui32BatchHandAllocFailures--;
946 enum PVRSRV_ERROR PVRSRVFindHandle(struct PVRSRV_HANDLE_BASE *psBase,
947 void **phHandle, void *pvData,
948 enum PVRSRV_HANDLE_TYPE eType)
952 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
954 hHandle = (void *)FindHandle(psBase, pvData, eType, NULL);
956 return PVRSRV_ERROR_GENERIC;
963 enum PVRSRV_ERROR PVRSRVLookupHandleAnyType(struct PVRSRV_HANDLE_BASE *psBase,
965 enum PVRSRV_HANDLE_TYPE *peType,
968 struct sHandle *psHandle;
969 enum PVRSRV_ERROR eError;
971 eError = GetHandleStructure(psBase, &psHandle, hHandle,
972 PVRSRV_HANDLE_TYPE_NONE);
973 if (eError != PVRSRV_OK) {
974 PVR_DPF(PVR_DBG_ERROR, "PVRSRVLookupHandleAnyType: "
975 "Error looking up handle (%d)",
980 *ppvData = psHandle->pvData;
981 *peType = psHandle->eType;
986 enum PVRSRV_ERROR PVRSRVLookupHandle(struct PVRSRV_HANDLE_BASE *psBase,
987 void **ppvData, void *hHandle,
988 enum PVRSRV_HANDLE_TYPE eType)
990 struct sHandle *psHandle;
991 enum PVRSRV_ERROR eError;
993 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
995 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
996 if (eError != PVRSRV_OK) {
997 PVR_DPF(PVR_DBG_ERROR,
998 "PVRSRVLookupHandle: Error looking up handle (%d)",
1003 *ppvData = psHandle->pvData;
1008 enum PVRSRV_ERROR PVRSRVLookupSubHandle(struct PVRSRV_HANDLE_BASE *psBase,
1009 void **ppvData, void *hHandle,
1010 enum PVRSRV_HANDLE_TYPE eType,
1013 struct sHandle *psPHand;
1014 struct sHandle *psCHand;
1015 enum PVRSRV_ERROR eError;
1017 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1019 eError = GetHandleStructure(psBase, &psCHand, hHandle, eType);
1020 if (eError != PVRSRV_OK) {
1021 PVR_DPF(PVR_DBG_ERROR, "PVRSRVLookupSubHandle: "
1022 "Error looking up subhandle (%d)",
1027 for (psPHand = psCHand; ParentHandle(psPHand) != hAncestor;) {
1029 GetHandleStructure(psBase, &psPHand, ParentHandle(psPHand),
1030 PVRSRV_HANDLE_TYPE_NONE);
1031 if (eError != PVRSRV_OK) {
1032 PVR_DPF(PVR_DBG_ERROR, "PVRSRVLookupSubHandle: "
1033 "Subhandle doesn't belong to given ancestor");
1034 return PVRSRV_ERROR_GENERIC;
1038 *ppvData = psCHand->pvData;
1043 enum PVRSRV_ERROR PVRSRVGetParentHandle(struct PVRSRV_HANDLE_BASE *psBase,
1044 void **phParent, void *hHandle,
1045 enum PVRSRV_HANDLE_TYPE eType)
1047 struct sHandle *psHandle;
1048 enum PVRSRV_ERROR eError;
1050 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1052 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
1053 if (eError != PVRSRV_OK) {
1054 PVR_DPF(PVR_DBG_ERROR, "PVRSRVGetParentHandle: "
1055 "Error looking up subhandle (%d)",
1060 *phParent = ParentHandle(psHandle);
1065 enum PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(
1066 struct PVRSRV_HANDLE_BASE *psBase,
1067 void **ppvData, void *hHandle,
1068 enum PVRSRV_HANDLE_TYPE eType)
1070 struct sHandle *psHandle;
1071 enum PVRSRV_ERROR eError;
1073 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1075 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
1076 if (eError != PVRSRV_OK) {
1077 PVR_DPF(PVR_DBG_ERROR, "PVRSRVLookupAndReleaseHandle: "
1078 "Error looking up handle (%d)",
1083 *ppvData = psHandle->pvData;
1085 eError = FreeHandle(psBase, psHandle);
1090 enum PVRSRV_ERROR PVRSRVReleaseHandle(struct PVRSRV_HANDLE_BASE *psBase,
1091 void *hHandle, enum PVRSRV_HANDLE_TYPE eType)
1093 struct sHandle *psHandle;
1094 enum PVRSRV_ERROR eError;
1096 PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
1098 eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
1099 if (eError != PVRSRV_OK) {
1100 PVR_DPF(PVR_DBG_ERROR,
1101 "PVRSRVReleaseHandle: Error looking up handle (%d)",
1106 eError = FreeHandle(psBase, psHandle);
1111 enum PVRSRV_ERROR PVRSRVNewHandleBatch(struct PVRSRV_HANDLE_BASE *psBase,
1114 enum PVRSRV_ERROR eError;
1116 if (HANDLES_BATCHED(psBase)) {
1117 PVR_DPF(PVR_DBG_ERROR, "PVRSRVNewHandleBatch: "
1118 "There is a handle batch already in use (size %u)",
1119 psBase->ui32HandBatchSize);
1120 return PVRSRV_ERROR_GENERIC;
1123 if (ui32BatchSize == 0) {
1124 PVR_DPF(PVR_DBG_ERROR,
1125 "PVRSRVNewHandleBatch: Invalid batch size (%u)",
1127 return PVRSRV_ERROR_INVALID_PARAMS;
1130 eError = EnsureFreeHandles(psBase, ui32BatchSize);
1131 if (eError != PVRSRV_OK) {
1132 PVR_DPF(PVR_DBG_ERROR, "PVRSRVNewHandleBatch: "
1133 "EnsureFreeHandles failed (error %d)",
1138 psBase->ui32HandBatchSize = ui32BatchSize;
1139 psBase->ui32TotalHandCountPreBatch = psBase->ui32TotalHandCount;
1141 PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0);
1142 PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0);
1143 PVR_ASSERT(HANDLES_BATCHED(psBase));
1148 static enum PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(
1149 struct PVRSRV_HANDLE_BASE *psBase, IMG_BOOL bCommit)
1151 u32 ui32IndexPlusOne;
1152 IMG_BOOL bCommitBatch = bCommit;
1154 if (!HANDLES_BATCHED(psBase)) {
1155 PVR_DPF(PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: "
1156 "There is no handle batch");
1157 return PVRSRV_ERROR_INVALID_PARAMS;
1161 if (psBase->ui32BatchHandAllocFailures != 0) {
1163 PVR_DPF(PVR_DBG_ERROR,
1164 "PVRSRVHandleBatchCommitOrRelease: "
1165 "Attempting to commit batch with handle "
1166 "allocation failures.");
1167 bCommitBatch = IMG_FALSE;
1170 PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit);
1172 ui32IndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
1173 while (ui32IndexPlusOne != 0) {
1174 struct sHandle *psHandle =
1175 INDEX_TO_HANDLE_PTR(psBase, ui32IndexPlusOne - 1);
1176 u32 ui32NextIndexPlusOne =
1177 psHandle->ui32NextIndexPlusOne;
1178 PVR_ASSERT(BATCHED_HANDLE(psHandle));
1180 psHandle->ui32NextIndexPlusOne = 0;
1182 if (!bCommitBatch || BATCHED_HANDLE_PARTIALLY_FREE(psHandle)) {
1183 enum PVRSRV_ERROR eError;
1185 if (!BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
1186 SET_UNBATCHED_HANDLE(psHandle);
1188 eError = FreeHandle(psBase, psHandle);
1189 if (eError != PVRSRV_OK)
1190 PVR_DPF(PVR_DBG_ERROR,
1191 "PVRSRVHandleBatchCommitOrRelease: "
1192 "Error freeing handle (%d)",
1194 PVR_ASSERT(eError == PVRSRV_OK);
1196 SET_UNBATCHED_HANDLE(psHandle);
1199 ui32IndexPlusOne = ui32NextIndexPlusOne;
1202 #ifdef CONFIG_PVR_DEBUG_EXTRA
1203 if (psBase->ui32TotalHandCountPreBatch != psBase->ui32TotalHandCount) {
1205 psBase->ui32TotalHandCount -
1206 psBase->ui32TotalHandCountPreBatch;
1208 PVR_ASSERT(psBase->ui32TotalHandCount >
1209 psBase->ui32TotalHandCountPreBatch);
1211 PVR_DPF(PVR_DBG_WARNING,
1212 "PVRSRVHandleBatchCommitOrRelease: "
1213 "The batch size was too small. "
1214 "Batch size was %u, but needs to be %u",
1215 psBase->ui32HandBatchSize,
1216 psBase->ui32HandBatchSize + ui32Delta);
1221 psBase->ui32HandBatchSize = 0;
1222 psBase->ui32FirstBatchIndexPlusOne = 0;
1223 psBase->ui32TotalHandCountPreBatch = 0;
1224 psBase->ui32BatchHandAllocFailures = 0;
1226 if (psBase->ui32BatchHandAllocFailures != 0 && bCommit) {
1227 PVR_ASSERT(!bCommitBatch);
1229 return PVRSRV_ERROR_GENERIC;
1235 enum PVRSRV_ERROR PVRSRVCommitHandleBatch(struct PVRSRV_HANDLE_BASE *psBase)
1237 return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE);
1240 void PVRSRVReleaseHandleBatch(struct PVRSRV_HANDLE_BASE *psBase)
1242 (void)PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE);
1245 enum PVRSRV_ERROR PVRSRVSetMaxHandle(struct PVRSRV_HANDLE_BASE *psBase,
1248 if (HANDLES_BATCHED(psBase)) {
1249 PVR_DPF(PVR_DBG_ERROR, "PVRSRVSetMaxHandle: "
1250 "Limit cannot be set whilst in batch mode");
1251 return PVRSRV_ERROR_INVALID_PARAMS;
1254 if (ui32MaxHandle == 0 || ui32MaxHandle > DEFAULT_MAX_HANDLE) {
1255 PVR_DPF(PVR_DBG_ERROR, "PVRSRVSetMaxHandle: "
1256 "Limit must be between %u and %u, inclusive",
1257 0, DEFAULT_MAX_HANDLE);
1259 return PVRSRV_ERROR_INVALID_PARAMS;
1262 if (psBase->ui32TotalHandCount != 0) {
1263 PVR_DPF(PVR_DBG_ERROR, "PVRSRVSetMaxHandle: "
1264 "Limit cannot be set becuase handles "
1265 "have already been allocated");
1267 return PVRSRV_ERROR_INVALID_PARAMS;
1270 psBase->ui32MaxIndexPlusOne = ui32MaxHandle;
1275 u32 PVRSRVGetMaxHandle(struct PVRSRV_HANDLE_BASE *psBase)
1277 return psBase->ui32MaxIndexPlusOne;
1280 enum PVRSRV_ERROR PVRSRVEnableHandlePurging(struct PVRSRV_HANDLE_BASE *psBase)
1282 if (psBase->bPurgingEnabled) {
1283 PVR_DPF(PVR_DBG_WARNING,
1284 "PVRSRVEnableHandlePurging: Purging already enabled");
1288 if (psBase->ui32TotalHandCount != 0) {
1289 PVR_DPF(PVR_DBG_ERROR, "PVRSRVEnableHandlePurging: "
1290 "Handles have already been allocated");
1291 return PVRSRV_ERROR_INVALID_PARAMS;
1294 psBase->bPurgingEnabled = IMG_TRUE;
1299 enum PVRSRV_ERROR PVRSRVPurgeHandles(struct PVRSRV_HANDLE_BASE *psBase)
1302 u32 ui32NewHandCount;
1304 if (!psBase->bPurgingEnabled) {
1305 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPurgeHandles: "
1306 "Purging not enabled for this handle base");
1307 return PVRSRV_ERROR_NOT_SUPPORTED;
1310 if (HANDLES_BATCHED(psBase)) {
1311 PVR_DPF(PVR_DBG_ERROR, "PVRSRVPurgeHandles: "
1312 "Purging not allowed whilst in batch mode");
1313 return PVRSRV_ERROR_INVALID_PARAMS;
1316 for (ui32Handle = psBase->ui32TotalHandCount; ui32Handle != 0;
1318 struct sHandle *psHandle =
1319 HANDLE_TO_HANDLE_PTR(psBase, ui32Handle);
1320 if (!HANDLE_STRUCT_IS_FREE(psHandle))
1324 ui32NewHandCount = ROUND_UP_TO_MULTIPLE(ui32Handle, HANDLE_BLOCK_SIZE);
1326 if (ui32NewHandCount >= ui32Handle
1327 && ui32NewHandCount <= (psBase->ui32TotalHandCount / 2)) {
1328 u32 ui32Delta = psBase->ui32TotalHandCount - ui32NewHandCount;
1329 enum PVRSRV_ERROR eError;
1332 ReallocHandleArray(psBase, ui32NewHandCount,
1333 psBase->ui32TotalHandCount);
1334 if (eError != PVRSRV_OK)
1337 psBase->ui32TotalHandCount = ui32NewHandCount;
1338 psBase->ui32FreeHandCount -= ui32Delta;
1339 psBase->ui32FirstFreeIndex = 0;
1345 enum PVRSRV_ERROR PVRSRVAllocHandleBase(struct PVRSRV_HANDLE_BASE **ppsBase)
1347 struct PVRSRV_HANDLE_BASE *psBase;
1349 enum PVRSRV_ERROR eError;
1351 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
1352 sizeof(*psBase), (void **)&psBase, &hBlockAlloc);
1353 if (eError != PVRSRV_OK) {
1354 PVR_DPF(PVR_DBG_ERROR, "PVRSRVAllocHandleBase: "
1355 "Couldn't allocate handle base (%d)",
1359 OSMemSet(psBase, 0, sizeof(*psBase));
1362 HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE,
1363 HAND_KEY_LEN * sizeof(u32),
1364 HASH_Func_Default, HASH_Key_Comp_Default);
1365 if (psBase->psHashTab == NULL) {
1366 PVR_DPF(PVR_DBG_ERROR, "PVRSRVAllocHandleBase: "
1367 "Couldn't create data pointer hash table\n");
1371 psBase->hBaseBlockAlloc = hBlockAlloc;
1373 psBase->ui32MaxIndexPlusOne = DEFAULT_MAX_INDEX_PLUS_ONE;
1379 (void)PVRSRVFreeHandleBase(psBase);
1380 return PVRSRV_ERROR_GENERIC;
1383 enum PVRSRV_ERROR PVRSRVFreeHandleBase(struct PVRSRV_HANDLE_BASE *psBase)
1385 enum PVRSRV_ERROR eError;
1387 PVR_ASSERT(psBase != gpsKernelHandleBase);
1389 eError = FreeHandleBase(psBase);
1390 if (eError != PVRSRV_OK)
1391 PVR_DPF(PVR_DBG_ERROR,
1392 "PVRSRVFreeHandleBase: FreeHandleBase failed (%d)",
1398 enum PVRSRV_ERROR PVRSRVHandleInit(void)
1400 enum PVRSRV_ERROR eError;
1402 PVR_ASSERT(gpsKernelHandleBase == NULL);
1404 eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
1405 if (eError != PVRSRV_OK) {
1406 PVR_DPF(PVR_DBG_ERROR,
1407 "PVRSRVHandleInit: PVRSRVAllocHandleBase failed (%d)",
1412 eError = PVRSRVEnableHandlePurging(gpsKernelHandleBase);
1413 if (eError != PVRSRV_OK) {
1414 PVR_DPF(PVR_DBG_ERROR, "PVRSRVHandleInit: "
1415 "PVRSRVEnableHandlePurging failed (%d)",
1422 (void)PVRSRVHandleDeInit();
1426 enum PVRSRV_ERROR PVRSRVHandleDeInit(void)
1428 enum PVRSRV_ERROR eError = PVRSRV_OK;
1430 if (gpsKernelHandleBase != NULL) {
1431 eError = FreeHandleBase(gpsKernelHandleBase);
1432 if (eError == PVRSRV_OK) {
1433 gpsKernelHandleBase = NULL;
1435 PVR_DPF(PVR_DBG_ERROR, "PVRSRVHandleDeInit: "
1436 "FreeHandleBase failed (%d)",