1 /****************************************************************************
3 * Copyright (C) 2005 - 2013 by Vivante Corp.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the license, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *****************************************************************************/
22 #include "gc_hal_kernel_precomp.h"
24 #define _GC_OBJ_ZONE gcvZONE_DATABASE
26 /*******************************************************************************
27 ***** Private fuctions ********************************************************/
29 #define _GetSlot(database, x) \
30 (gctUINT32)(((gcmPTR_TO_UINT64(x) >> 7) % gcmCOUNTOF(database->list)))
32 /*******************************************************************************
33 ** gckKERNEL_NewDatabase
35 ** Create a new database structure and insert it to the head of the hash list.
40 ** Pointer to a gckKERNEL object.
42 ** gctUINT32 ProcessID
43 ** ProcessID that identifies the database.
47 ** gcsDATABASE_PTR * Database
48 ** Pointer to a variable receiving the database structure pointer on
52 gckKERNEL_NewDatabase(
54 IN gctUINT32 ProcessID,
55 OUT gcsDATABASE_PTR * Database
59 gcsDATABASE_PTR database;
60 gctBOOL acquired = gcvFALSE;
62 gcsDATABASE_PTR existingDatabase;
64 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
66 /* Acquire the database mutex. */
67 gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
70 /* Compute the hash for the database. */
71 slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
73 /* Walk the hash list. */
74 for (existingDatabase = Kernel->db->db[slot];
75 existingDatabase != gcvNULL;
76 existingDatabase = existingDatabase->next)
78 if (existingDatabase->processID == ProcessID)
80 /* One process can't be added twice. */
81 gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
85 if (Kernel->db->freeDatabase != gcvNULL)
87 /* Allocate a database from the free list. */
88 database = Kernel->db->freeDatabase;
89 Kernel->db->freeDatabase = database->next;
93 gctPOINTER pointer = gcvNULL;
95 /* Allocate a new database from the heap. */
96 gcmkONERROR(gckOS_Allocate(Kernel->os,
97 gcmSIZEOF(gcsDATABASE),
103 /* Insert the database into the hash. */
104 database->next = Kernel->db->db[slot];
105 Kernel->db->db[slot] = database;
107 /* Save the hash slot. */
108 database->slot = slot;
110 /* Release the database mutex. */
111 gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
113 /* Return the database. */
114 *Database = database;
117 gcmkFOOTER_ARG("*Database=0x%x", *Database);
123 /* Release the database mutex. */
124 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
127 /* Return the status. */
132 /*******************************************************************************
133 ** gckKERNEL_FindDatabase
135 ** Find a database identified by a process ID and move it to the head of the
141 ** Pointer to a gckKERNEL object.
143 ** gctUINT32 ProcessID
144 ** ProcessID that identifies the database.
146 ** gctBOOL LastProcessID
147 ** gcvTRUE if searching for the last known process ID. gcvFALSE if
148 ** we need to search for the process ID specified by the ProcessID
153 ** gcsDATABASE_PTR * Database
154 ** Pointer to a variable receiving the database structure pointer on
158 gckKERNEL_FindDatabase(
160 IN gctUINT32 ProcessID,
161 IN gctBOOL LastProcessID,
162 OUT gcsDATABASE_PTR * Database
166 gcsDATABASE_PTR database, previous;
168 gctBOOL acquired = gcvFALSE;
170 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d LastProcessID=%d",
171 Kernel, ProcessID, LastProcessID);
173 /* Compute the hash for the database. */
174 slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
176 /* Acquire the database mutex. */
178 gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
181 /* Check whether we are getting the last known database. */
184 /* Use last database. */
185 database = Kernel->db->lastDatabase;
187 if (database == gcvNULL)
189 /* Database not found. */
190 gcmkONERROR(gcvSTATUS_INVALID_DATA);
195 /* Walk the hash list. */
196 for (previous = gcvNULL, database = Kernel->db->db[slot];
198 database = database->next)
200 if (database->processID == ProcessID)
209 if (database == gcvNULL)
211 /* Database not found. */
212 gcmkONERROR(gcvSTATUS_INVALID_DATA);
215 if (previous != gcvNULL)
217 /* Move database to the head of the hash list. */
218 previous->next = database->next;
219 database->next = Kernel->db->db[slot];
220 Kernel->db->db[slot] = database;
224 /* Release the database mutex. */
225 gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
227 /* Return the database. */
228 *Database = database;
231 gcmkFOOTER_ARG("*Database=0x%x", *Database);
237 /* Release the database mutex. */
238 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
241 /* Return the status. */
246 /*******************************************************************************
247 ** gckKERNEL_DeleteDatabase
249 ** Remove a database from the hash list and delete its structure.
254 ** Pointer to a gckKERNEL object.
256 ** gcsDATABASE_PTR Database
257 ** Pointer to the database structure to remove.
264 gckKERNEL_DeleteDatabase(
266 IN gcsDATABASE_PTR Database
270 gctBOOL acquired = gcvFALSE;
271 gcsDATABASE_PTR database;
273 gcmkHEADER_ARG("Kernel=0x%x Database=0x%x", Kernel, Database);
275 /* Acquire the database mutex. */
277 gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
280 /* Check slot value. */
281 gcmkVERIFY_ARGUMENT(Database->slot < gcmCOUNTOF(Kernel->db->db));
283 if (Database->slot < gcmCOUNTOF(Kernel->db->db))
285 /* Check if database if the head of the hash list. */
286 if (Kernel->db->db[Database->slot] == Database)
288 /* Remove the database from the hash list. */
289 Kernel->db->db[Database->slot] = Database->next;
293 /* Walk the has list to find the database. */
294 for (database = Kernel->db->db[Database->slot];
296 database = database->next
299 /* Check if the next list entry is this database. */
300 if (database->next == Database)
302 /* Remove the database from the hash list. */
303 database->next = Database->next;
308 if (database == gcvNULL)
310 /* Ouch! Something got corrupted. */
311 gcmkONERROR(gcvSTATUS_INVALID_DATA);
316 if (Kernel->db->lastDatabase != gcvNULL)
318 /* Insert database to the free list. */
319 Kernel->db->lastDatabase->next = Kernel->db->freeDatabase;
320 Kernel->db->freeDatabase = Kernel->db->lastDatabase;
323 /* Keep database as the last database. */
324 Kernel->db->lastDatabase = Database;
326 /* Release the database mutex. */
327 gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
336 /* Release the database mutex. */
337 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
340 /* Return the status. */
345 /*******************************************************************************
346 ** gckKERNEL_NewRecord
348 ** Create a new database record structure and insert it to the head of the
354 ** Pointer to a gckKERNEL object.
356 ** gcsDATABASE_PTR Database
357 ** Pointer to a database structure.
361 ** gcsDATABASE_RECORD_PTR * Record
362 ** Pointer to a variable receiving the database record structure
363 ** pointer on success.
368 IN gcsDATABASE_PTR Database,
370 OUT gcsDATABASE_RECORD_PTR * Record
374 gctBOOL acquired = gcvFALSE;
375 gcsDATABASE_RECORD_PTR record = gcvNULL;
377 gcmkHEADER_ARG("Kernel=0x%x Database=0x%x", Kernel, Database);
379 /* Acquire the database mutex. */
381 gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
384 if (Kernel->db->freeRecord != gcvNULL)
386 /* Allocate the record from the free list. */
387 record = Kernel->db->freeRecord;
388 Kernel->db->freeRecord = record->next;
392 gctPOINTER pointer = gcvNULL;
394 /* Allocate the record from the heap. */
395 gcmkONERROR(gckOS_Allocate(Kernel->os,
396 gcmSIZEOF(gcsDATABASE_RECORD),
402 /* Insert the record in the database. */
403 record->next = Database->list[Slot];
404 Database->list[Slot] = record;
406 /* Release the database mutex. */
407 gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
409 /* Return the record. */
413 gcmkFOOTER_ARG("*Record=0x%x", *Record);
419 /* Release the database mutex. */
420 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
422 if (record != gcvNULL)
424 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel->os, record));
427 /* Return the status. */
432 /*******************************************************************************
433 ** gckKERNEL_DeleteRecord
435 ** Remove a database record from the database and delete its structure.
440 ** Pointer to a gckKERNEL object.
442 ** gcsDATABASE_PTR Database
443 ** Pointer to a database structure.
445 ** gceDATABASE_TYPE Type
446 ** Type of the record to remove.
449 ** Data of the record to remove.
453 ** gctSIZE_T_PTR Bytes
454 ** Pointer to a variable that receives the size of the record deleted.
455 ** Can be gcvNULL if the size is not required.
458 gckKERNEL_DeleteRecord(
460 IN gcsDATABASE_PTR Database,
461 IN gceDATABASE_TYPE Type,
463 OUT gctSIZE_T_PTR Bytes OPTIONAL
467 gctBOOL acquired = gcvFALSE;
468 gcsDATABASE_RECORD_PTR record, previous;
469 gctUINT32 slot = _GetSlot(Database, Data);
471 gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
472 Kernel, Database, Type, Data);
474 /* Acquire the database mutex. */
476 gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
480 /* Scan the database for this record. */
481 for (record = Database->list[slot], previous = gcvNULL;
483 record = record->next
486 if ((record->type == Type)
487 && (record->data == Data)
497 if (record == gcvNULL)
499 /* Ouch! This record is not found? */
500 gcmkONERROR(gcvSTATUS_INVALID_DATA);
503 if (Bytes != gcvNULL)
505 /* Return size of record. */
506 *Bytes = record->bytes;
509 /* Remove record from database. */
510 if (previous == gcvNULL)
512 Database->list[slot] = record->next;
516 previous->next = record->next;
519 /* Insert record in free list. */
520 record->next = Kernel->db->freeRecord;
521 Kernel->db->freeRecord = record;
523 /* Release the database mutex. */
524 gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
527 gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes));
533 /* Release the database mutex. */
534 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
537 /* Return the status. */
542 /*******************************************************************************
543 ** gckKERNEL_FindRecord
545 ** Find a database record from the database.
550 ** Pointer to a gckKERNEL object.
552 ** gcsDATABASE_PTR Database
553 ** Pointer to a database structure.
555 ** gceDATABASE_TYPE Type
556 ** Type of the record to remove.
559 ** Data of the record to remove.
563 ** gctSIZE_T_PTR Bytes
564 ** Pointer to a variable that receives the size of the record deleted.
565 ** Can be gcvNULL if the size is not required.
568 gckKERNEL_FindRecord(
570 IN gcsDATABASE_PTR Database,
571 IN gceDATABASE_TYPE Type,
573 OUT gcsDATABASE_RECORD_PTR Record
577 gctBOOL acquired = gcvFALSE;
578 gcsDATABASE_RECORD_PTR record;
579 gctUINT32 slot = _GetSlot(Database, Data);
581 gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
582 Kernel, Database, Type, Data);
584 /* Acquire the database mutex. */
586 gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
589 /* Scan the database for this record. */
590 for (record = Database->list[slot];
592 record = record->next
595 if ((record->type == Type)
596 && (record->data == Data)
604 if (record == gcvNULL)
606 /* Ouch! This record is not found? */
607 gcmkONERROR(gcvSTATUS_INVALID_DATA);
610 if (Record != gcvNULL)
612 /* Return information of record. */
614 gckOS_MemCopy(Record, record, sizeof(gcsDATABASE_RECORD)));
617 /* Release the database mutex. */
618 gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
621 gcmkFOOTER_ARG("Record=0x%x", Record);
627 /* Release the database mutex. */
628 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
631 /* Return the status. */
637 /*******************************************************************************
638 ***** Public API **************************************************************/
640 /*******************************************************************************
641 ** gckKERNEL_CreateProcessDB
643 ** Create a new process database.
648 ** Pointer to a gckKERNEL object.
650 ** gctUINT32 ProcessID
651 ** Process ID used to identify the database.
658 gckKERNEL_CreateProcessDB(
660 IN gctUINT32 ProcessID
664 gcsDATABASE_PTR database = gcvNULL;
667 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
669 /* Verify the arguments. */
670 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
672 /* Create a new database. */
673 gcmkONERROR(gckKERNEL_NewDatabase(Kernel, ProcessID, &database));
675 /* Initialize the database. */
676 database->processID = ProcessID;
677 database->vidMem.bytes = 0;
678 database->vidMem.maxBytes = 0;
679 database->vidMem.totalBytes = 0;
680 database->nonPaged.bytes = 0;
681 database->nonPaged.maxBytes = 0;
682 database->nonPaged.totalBytes = 0;
683 database->contiguous.bytes = 0;
684 database->contiguous.maxBytes = 0;
685 database->contiguous.totalBytes = 0;
686 database->mapMemory.bytes = 0;
687 database->mapMemory.maxBytes = 0;
688 database->mapMemory.totalBytes = 0;
689 database->mapUserMemory.bytes = 0;
690 database->mapUserMemory.maxBytes = 0;
691 database->mapUserMemory.totalBytes = 0;
692 database->vidMemResv.bytes = 0;
693 database->vidMemResv.maxBytes = 0;
694 database->vidMemResv.totalBytes = 0;
695 database->vidMemCont.bytes = 0;
696 database->vidMemCont.maxBytes = 0;
697 database->vidMemCont.totalBytes = 0;
698 database->vidMemVirt.bytes = 0;
699 database->vidMemVirt.maxBytes = 0;
700 database->vidMemVirt.totalBytes = 0;
702 for (i = 0; i < gcmCOUNTOF(database->list); i++)
704 database->list[i] = gcvNULL;
710 gcskSECURE_CACHE * cache = &database->cache;
712 /* Setup the linked list of cache nodes. */
713 for (slot = 1; slot <= gcdSECURE_CACHE_SLOTS; ++slot)
715 cache->cache[slot].logical = gcvNULL;
717 #if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
718 cache->cache[slot].prev = &cache->cache[slot - 1];
719 cache->cache[slot].next = &cache->cache[slot + 1];
721 #if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
722 cache->cache[slot].nextHash = gcvNULL;
723 cache->cache[slot].prevHash = gcvNULL;
727 #if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
728 /* Setup the head and tail of the cache. */
729 cache->cache[0].next = &cache->cache[1];
730 cache->cache[0].prev = &cache->cache[gcdSECURE_CACHE_SLOTS];
731 cache->cache[0].logical = gcvNULL;
733 /* Fix up the head and tail pointers. */
734 cache->cache[0].next->prev = &cache->cache[0];
735 cache->cache[0].prev->next = &cache->cache[0];
738 #if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
739 /* Zero out the hash table. */
740 for (slot = 0; slot < gcmCOUNTOF(cache->hash); ++slot)
742 cache->hash[slot].logical = gcvNULL;
743 cache->hash[slot].nextHash = gcvNULL;
747 /* Initialize cache index. */
748 cache->cacheIndex = gcvNULL;
749 cache->cacheFree = 1;
750 cache->cacheStamp = 0;
754 /* Reset idle timer. */
755 Kernel->db->lastIdle = 0;
762 /* Return the status. */
767 /*******************************************************************************
768 ** gckKERNEL_AddProcessDB
770 ** Add a record to a process database.
775 ** Pointer to a gckKERNEL object.
777 ** gctUINT32 ProcessID
778 ** Process ID used to identify the database.
780 ** gceDATABASE_TYPE TYPE
781 ** Type of the record to add.
783 ** gctPOINTER Pointer
784 ** Data of the record to add.
786 ** gctPHYS_ADDR Physical
787 ** Physical address of the record to add.
790 ** Size of the record to add.
797 gckKERNEL_AddProcessDB(
799 IN gctUINT32 ProcessID,
800 IN gceDATABASE_TYPE Type,
801 IN gctPOINTER Pointer,
802 IN gctPHYS_ADDR Physical,
807 gcsDATABASE_PTR database;
808 gcsDATABASE_RECORD_PTR record = gcvNULL;
809 gcsDATABASE_COUNTERS * count;
811 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x "
812 "Physical=0x%x Size=%lu",
813 Kernel, ProcessID, Type, Pointer, Physical, Size);
815 /* Verify the arguments. */
816 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
818 /* Special case the idle record. */
819 if (Type == gcvDB_IDLE)
823 /* Get the current profile time. */
824 gcmkONERROR(gckOS_GetProfileTick(&time));
826 if ((ProcessID == 0) && (Kernel->db->lastIdle != 0))
828 /* Out of idle, adjust time it was idle. */
829 Kernel->db->idleTime += time - Kernel->db->lastIdle;
830 Kernel->db->lastIdle = 0;
832 else if (ProcessID == 1)
834 /* Save current idle time. */
835 Kernel->db->lastIdle = time;
840 /* Test for first call. */
841 if (Kernel->db->lastSlowdown == 0)
843 /* Save milliseconds. */
844 Kernel->db->lastSlowdown = time;
845 Kernel->db->lastSlowdownIdle = Kernel->db->idleTime;
849 /* Compute ellapsed time in milliseconds. */
850 gctUINT delta = gckOS_ProfileToMS(time - Kernel->db->lastSlowdown);
852 /* Test for end of period. */
853 if (delta >= gcdDYNAMIC_SPEED)
855 /* Compute number of idle milliseconds. */
856 gctUINT idle = gckOS_ProfileToMS(
857 Kernel->db->idleTime - Kernel->db->lastSlowdownIdle);
859 /* Broadcast to slow down the GPU. */
860 gcmkONERROR(gckOS_BroadcastCalibrateSpeed(Kernel->os,
865 /* Save current time. */
866 Kernel->db->lastSlowdown = time;
867 Kernel->db->lastSlowdownIdle = Kernel->db->idleTime;
878 /* Verify the arguments. */
879 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
881 /* Find the database. */
882 gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
884 /* Create a new record in the database. */
885 gcmkONERROR(gckKERNEL_NewRecord(Kernel, database, _GetSlot(database, Pointer), &record));
887 /* Initialize the record. */
888 record->kernel = Kernel;
890 record->data = Pointer;
891 record->physical = Physical;
892 record->bytes = Size;
894 /* Get pointer to counters. */
897 case gcvDB_VIDEO_MEMORY:
898 count = &database->vidMem;
901 case gcvDB_NON_PAGED:
902 count = &database->nonPaged;
905 case gcvDB_CONTIGUOUS:
906 count = &database->contiguous;
909 case gcvDB_MAP_MEMORY:
910 count = &database->mapMemory;
913 case gcvDB_MAP_USER_MEMORY:
914 count = &database->mapUserMemory;
917 case gcvDB_VIDEO_MEMORY_RESERVED:
918 count = &database->vidMemResv;
921 case gcvDB_VIDEO_MEMORY_CONTIGUOUS:
922 count = &database->vidMemCont;
925 case gcvDB_VIDEO_MEMORY_VIRTUAL:
926 count = &database->vidMemVirt;
934 if (count != gcvNULL)
936 /* Adjust counters. */
937 count->totalBytes += Size;
938 count->bytes += Size;
940 if (count->bytes > count->maxBytes)
942 count->maxBytes = count->bytes;
951 /* Return the status. */
956 /*******************************************************************************
957 ** gckKERNEL_RemoveProcessDB
959 ** Remove a record from a process database.
964 ** Pointer to a gckKERNEL object.
966 ** gctUINT32 ProcessID
967 ** Process ID used to identify the database.
969 ** gceDATABASE_TYPE TYPE
970 ** Type of the record to remove.
972 ** gctPOINTER Pointer
973 ** Data of the record to remove.
980 gckKERNEL_RemoveProcessDB(
982 IN gctUINT32 ProcessID,
983 IN gceDATABASE_TYPE Type,
984 IN gctPOINTER Pointer
988 gcsDATABASE_PTR database;
991 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x",
992 Kernel, ProcessID, Type, Pointer);
994 /* Verify the arguments. */
995 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
996 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
998 /* Find the database. */
999 gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
1001 /* Delete the record. */
1003 gckKERNEL_DeleteRecord(Kernel, database, Type, Pointer, &bytes));
1005 /* Update counters. */
1008 case gcvDB_VIDEO_MEMORY:
1009 database->vidMem.bytes -= bytes;
1012 case gcvDB_NON_PAGED:
1013 database->nonPaged.bytes -= bytes;
1016 case gcvDB_CONTIGUOUS:
1017 database->contiguous.bytes -= bytes;
1020 case gcvDB_MAP_MEMORY:
1021 database->mapMemory.bytes -= bytes;
1024 case gcvDB_MAP_USER_MEMORY:
1025 database->mapUserMemory.bytes -= bytes;
1028 case gcvDB_VIDEO_MEMORY_RESERVED:
1029 database->vidMemResv.bytes -= bytes;
1032 case gcvDB_VIDEO_MEMORY_CONTIGUOUS:
1033 database->vidMemCont.bytes -= bytes;
1036 case gcvDB_VIDEO_MEMORY_VIRTUAL:
1037 database->vidMemVirt.bytes -= bytes;
1046 return gcvSTATUS_OK;
1049 /* Return the status. */
1054 /*******************************************************************************
1055 ** gckKERNEL_FindProcessDB
1057 ** Find a record from a process database.
1062 ** Pointer to a gckKERNEL object.
1064 ** gctUINT32 ProcessID
1065 ** Process ID used to identify the database.
1067 ** gceDATABASE_TYPE TYPE
1068 ** Type of the record to remove.
1070 ** gctPOINTER Pointer
1071 ** Data of the record to remove.
1075 ** gcsDATABASE_RECORD_PTR Record
1079 gckKERNEL_FindProcessDB(
1080 IN gckKERNEL Kernel,
1081 IN gctUINT32 ProcessID,
1082 IN gctUINT32 ThreadID,
1083 IN gceDATABASE_TYPE Type,
1084 IN gctPOINTER Pointer,
1085 OUT gcsDATABASE_RECORD_PTR Record
1089 gcsDATABASE_PTR database;
1091 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x",
1092 Kernel, ProcessID, ThreadID, Type, Pointer);
1094 /* Verify the arguments. */
1095 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1096 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
1098 /* Find the database. */
1099 gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
1101 /* Find the record. */
1103 gckKERNEL_FindRecord(Kernel, database, Type, Pointer, Record));
1107 return gcvSTATUS_OK;
1110 /* Return the status. */
1115 /*******************************************************************************
1116 ** gckKERNEL_DestroyProcessDB
1118 ** Destroy a process database. If the database contains any records, the data
1119 ** inside those records will be deleted as well. This aids in the cleanup if
1120 ** a process has died unexpectedly or has memory leaks.
1125 ** Pointer to a gckKERNEL object.
1127 ** gctUINT32 ProcessID
1128 ** Process ID used to identify the database.
1135 gckKERNEL_DestroyProcessDB(
1136 IN gckKERNEL Kernel,
1137 IN gctUINT32 ProcessID
1141 gcsDATABASE_PTR database;
1142 gcsDATABASE_RECORD_PTR record, next;
1143 gctBOOL asynchronous;
1144 gctPHYS_ADDR physical;
1145 gcuVIDMEM_NODE_PTR node;
1146 gckKERNEL kernel = Kernel;
1149 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
1151 /* Verify the arguments. */
1152 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1154 /* Find the database. */
1155 gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
1157 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
1158 "DB(%d): VidMem: total=%lu max=%lu",
1159 ProcessID, database->vidMem.totalBytes,
1160 database->vidMem.maxBytes);
1161 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
1162 "DB(%d): NonPaged: total=%lu max=%lu",
1163 ProcessID, database->nonPaged.totalBytes,
1164 database->nonPaged.maxBytes);
1165 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
1166 "DB(%d): Contiguous: total=%lu max=%lu",
1167 ProcessID, database->contiguous.totalBytes,
1168 database->contiguous.maxBytes);
1169 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
1170 "DB(%d): Idle time=%llu",
1171 ProcessID, Kernel->db->idleTime);
1172 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
1173 "DB(%d): Map: total=%lu max=%lu",
1174 ProcessID, database->mapMemory.totalBytes,
1175 database->mapMemory.maxBytes);
1176 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_DATABASE,
1177 "DB(%d): Map: total=%lu max=%lu",
1178 ProcessID, database->mapUserMemory.totalBytes,
1179 database->mapUserMemory.maxBytes);
1181 if (database->list != gcvNULL)
1183 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1184 "Process %d has entries in its database:",
1188 for(i = 0; i < gcmCOUNTOF(database->list); i++)
1191 /* Walk all records. */
1192 for (record = database->list[i]; record != gcvNULL; record = next)
1194 /* Next next record. */
1195 next = record->next;
1197 /* Dispatch on record type. */
1198 switch (record->type)
1200 case gcvDB_VIDEO_MEMORY:
1201 /* Free the video memory. */
1202 status = gckVIDMEM_Free(gcmUINT64_TO_PTR(record->data));
1204 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1205 "DB: VIDEO_MEMORY 0x%x (status=%d)",
1206 record->data, status);
1209 case gcvDB_NON_PAGED:
1210 physical = gcmNAME_TO_PTR(record->physical);
1211 /* Unmap user logical memory first. */
1212 status = gckOS_UnmapUserLogical(Kernel->os,
1217 /* Free the non paged memory. */
1218 status = gckOS_FreeNonPagedMemory(Kernel->os,
1222 gcmRELEASE_NAME(record->physical);
1224 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1225 "DB: NON_PAGED 0x%x, bytes=%lu (status=%d)",
1226 record->data, record->bytes, status);
1229 #if gcdVIRTUAL_COMMAND_BUFFER
1230 case gcvDB_COMMAND_BUFFER:
1231 /* Free the command buffer. */
1232 status = gckEVENT_DestroyVirtualCommandBuffer(record->kernel->eventObj,
1234 gcmNAME_TO_PTR(record->physical),
1237 gcmRELEASE_NAME(record->physical);
1239 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1240 "DB: COMMAND_BUFFER 0x%x, bytes=%lu (status=%d)",
1241 record->data, record->bytes, status);
1245 case gcvDB_CONTIGUOUS:
1246 physical = gcmNAME_TO_PTR(record->physical);
1247 /* Unmap user logical memory first. */
1248 status = gckOS_UnmapUserLogical(Kernel->os,
1253 /* Free the contiguous memory. */
1254 status = gckEVENT_FreeContiguousMemory(Kernel->eventObj,
1259 gcmRELEASE_NAME(record->physical);
1261 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1262 "DB: CONTIGUOUS 0x%x bytes=%lu (status=%d)",
1263 record->data, record->bytes, status);
1267 #if USE_NEW_LINUX_SIGNAL
1268 status = gcvSTATUS_NOT_SUPPORTED;
1270 /* Free the user signal. */
1271 status = gckOS_DestroyUserSignal(Kernel->os,
1272 gcmPTR2INT(record->data));
1273 #endif /* USE_NEW_LINUX_SIGNAL */
1275 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1276 "DB: SIGNAL %d (status=%d)",
1277 (gctINT)(gctUINTPTR_T)record->data, status);
1280 case gcvDB_VIDEO_MEMORY_LOCKED:
1281 node = gcmUINT64_TO_PTR(record->data);
1282 /* Unlock what we still locked */
1283 status = gckVIDMEM_Unlock(record->kernel,
1285 gcvSURF_TYPE_UNKNOWN,
1288 if (gcmIS_SUCCESS(status) && (gcvTRUE == asynchronous))
1290 /* TODO: we maybe need to schedule a event here */
1291 status = gckVIDMEM_Unlock(record->kernel,
1293 gcvSURF_TYPE_UNKNOWN,
1297 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1298 "DB: VIDEO_MEMORY_LOCKED 0x%x (status=%d)",
1303 /* TODO: Free the context */
1304 status = gckCOMMAND_Detach(Kernel->command, gcmNAME_TO_PTR(record->data));
1305 gcmRELEASE_NAME(record->data);
1307 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1308 "DB: CONTEXT 0x%x (status=%d)",
1309 record->data, status);
1312 case gcvDB_MAP_MEMORY:
1314 status = gckKERNEL_UnmapMemory(Kernel,
1319 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1320 "DB: MAP MEMORY %d (status=%d)",
1321 gcmPTR2INT(record->data), status);
1324 case gcvDB_MAP_USER_MEMORY:
1325 /* TODO: Unmap user memory. */
1326 status = gckOS_UnmapUserMemory(Kernel->os,
1330 gcmNAME_TO_PTR(record->data),
1332 gcmRELEASE_NAME(record->data);
1334 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1335 "DB: MAP USER MEMORY %d (status=%d)",
1336 gcmPTR2INT(record->data), status);
1339 case gcvDB_SHARED_INFO:
1340 status = gckOS_FreeMemory(Kernel->os, record->physical);
1343 #if gcdANDROID_NATIVE_FENCE_SYNC
1344 case gcvDB_SYNC_POINT:
1345 /* Free the user signal. */
1346 status = gckOS_DestroySyncPoint(Kernel->os,
1347 (gctSYNC_POINT) record->data);
1349 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_DATABASE,
1350 "DB: SYNC POINT %d (status=%d)",
1351 (gctINT)(gctUINTPTR_T)record->data, status);
1355 case gcvDB_VIDEO_MEMORY_RESERVED:
1356 case gcvDB_VIDEO_MEMORY_CONTIGUOUS:
1357 case gcvDB_VIDEO_MEMORY_VIRTUAL:
1358 break;//Nothing to do
1361 gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_DATABASE,
1362 "DB: Correcupted record=0x%08x type=%d",
1363 record, record->type);
1367 /* Delete the record. */
1368 gcmkONERROR(gckKERNEL_DeleteRecord(Kernel,
1377 /* Delete the database. */
1378 gcmkONERROR(gckKERNEL_DeleteDatabase(Kernel, database));
1382 return gcvSTATUS_OK;
1385 /* Return the status. */
1390 /*******************************************************************************
1391 ** gckKERNEL_QueryProcessDB
1393 ** Query a process database for the current usage of a particular record type.
1398 ** Pointer to a gckKERNEL object.
1400 ** gctUINT32 ProcessID
1401 ** Process ID used to identify the database.
1403 ** gctBOOL LastProcessID
1404 ** gcvTRUE if searching for the last known process ID. gcvFALSE if
1405 ** we need to search for the process ID specified by the ProcessID
1408 ** gceDATABASE_TYPE Type
1409 ** Type of the record to query.
1413 ** gcuDATABASE_INFO * Info
1414 ** Pointer to a variable that receives the requested information.
1417 gckKERNEL_QueryProcessDB(
1418 IN gckKERNEL Kernel,
1419 IN gctUINT32 ProcessID,
1420 IN gctBOOL LastProcessID,
1421 IN gceDATABASE_TYPE Type,
1422 OUT gcuDATABASE_INFO * Info
1426 gcsDATABASE_PTR database;
1428 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Info=0x%x",
1429 Kernel, ProcessID, Type, Info);
1431 /* Verify the arguments. */
1432 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1433 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
1435 /* Find the database. */
1437 gckKERNEL_FindDatabase(Kernel, ProcessID, LastProcessID, &database));
1439 /* Get pointer to counters. */
1442 case gcvDB_VIDEO_MEMORY:
1443 gckOS_MemCopy(&Info->counters,
1445 gcmSIZEOF(database->vidMem));
1448 case gcvDB_NON_PAGED:
1449 gckOS_MemCopy(&Info->counters,
1450 &database->nonPaged,
1451 gcmSIZEOF(database->vidMem));
1454 case gcvDB_CONTIGUOUS:
1455 gckOS_MemCopy(&Info->counters,
1456 &database->contiguous,
1457 gcmSIZEOF(database->vidMem));
1461 Info->time = Kernel->db->idleTime;
1462 Kernel->db->idleTime = 0;
1465 case gcvDB_MAP_MEMORY:
1466 gckOS_MemCopy(&Info->counters,
1467 &database->mapMemory,
1468 gcmSIZEOF(database->mapMemory));
1471 case gcvDB_MAP_USER_MEMORY:
1472 gckOS_MemCopy(&Info->counters,
1473 &database->mapUserMemory,
1474 gcmSIZEOF(database->mapUserMemory));
1477 case gcvDB_VIDEO_MEMORY_RESERVED:
1478 gckOS_MemCopy(&Info->counters,
1479 &database->vidMemResv,
1480 gcmSIZEOF(database->vidMemResv));
1483 case gcvDB_VIDEO_MEMORY_CONTIGUOUS:
1484 gckOS_MemCopy(&Info->counters,
1485 &database->vidMemCont,
1486 gcmSIZEOF(database->vidMemCont));
1489 case gcvDB_VIDEO_MEMORY_VIRTUAL:
1490 gckOS_MemCopy(&Info->counters,
1491 &database->vidMemVirt,
1492 gcmSIZEOF(database->vidMemVirt));
1501 return gcvSTATUS_OK;
1504 /* Return the status. */
1510 /*******************************************************************************
1511 ** gckKERNEL_GetProcessDBCache
1513 ** Get teh secure cache from a process database.
1518 ** Pointer to a gckKERNEL object.
1520 ** gctUINT32 ProcessID
1521 ** Process ID used to identify the database.
1525 ** gcskSECURE_CACHE_PTR * Cache
1526 ** Pointer to a variable that receives the secure cache pointer.
1529 gckKERNEL_GetProcessDBCache(
1530 IN gckKERNEL Kernel,
1531 IN gctUINT32 ProcessID,
1532 OUT gcskSECURE_CACHE_PTR * Cache
1536 gcsDATABASE_PTR database;
1538 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
1540 /* Verify the arguments. */
1541 gcmkVERIFY_OBJECT(Kernel, gcvOBJ_KERNEL);
1542 gcmkVERIFY_ARGUMENT(Cache != gcvNULL);
1544 /* Find the database. */
1545 gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
1547 /* Return the pointer to the cache. */
1548 *Cache = &database->cache;
1551 gcmkFOOTER_ARG("*Cache=0x%x", *Cache);
1552 return gcvSTATUS_OK;
1555 /* Return the status. */
1562 gckKERNEL_DumpProcessDB(
1566 gcsDATABASE_PTR database;
1570 gcmkHEADER_ARG("Kernel=0x%x", Kernel);
1572 /* Acquire the database mutex. */
1574 gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
1576 gcmkPRINT("**************************\n");
1577 gcmkPRINT("*** PROCESS DB DUMP ***\n");
1578 gcmkPRINT("**************************\n");
1580 gcmkPRINT_N(8, "%-8s%s\n", "PID", "NAME");
1581 /* Walk the databases. */
1582 for (i = 0; i < gcmCOUNTOF(Kernel->db->db); ++i)
1584 for (database = Kernel->db->db[i];
1585 database != gcvNULL;
1586 database = database->next)
1588 pid = database->processID;
1590 gcmkVERIFY_OK(gckOS_ZeroMemory(name, gcmSIZEOF(name)));
1592 gcmkVERIFY_OK(gckOS_GetProcessNameByPid(pid, gcmSIZEOF(name), name));
1594 gcmkPRINT_N(8, "%-8d%s\n", pid, name);
1598 /* Release the database mutex. */
1599 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
1603 return gcvSTATUS_OK;