1 /****************************************************************************
3 * Copyright (C) 2005 - 2011 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 *****************************************************************************/
24 #include "gc_hal_kernel_precomp.h"
26 #define _GC_OBJ_ZONE gcvZONE_DATABASE
28 /*******************************************************************************
29 ***** Private fuctions ********************************************************/
31 /*******************************************************************************
32 ** gckKERNEL_NewDatabase
34 ** Create a new database structure and insert it to the head of the hash list.
39 ** Pointer to a gckKERNEL object.
41 ** gctUINT32 ProcessID
42 ** ProcessID that identifies the database.
46 ** gcsDATABASE_PTR * Database
47 ** Pointer to a variable receiving the database structure pointer on
51 gckKERNEL_NewDatabase(
53 IN gctUINT32 ProcessID
,
54 OUT gcsDATABASE_PTR
* Database
58 gcsDATABASE_PTR database
;
59 gctBOOL acquired
= gcvFALSE
;
62 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel
, ProcessID
);
64 /* Acquire the database mutex. */
65 gcmkONERROR(gckOS_AcquireMutex(Kernel
->os
, Kernel
->db
->dbMutex
, gcvINFINITE
));
68 if (Kernel
->db
->freeDatabase
!= gcvNULL
)
70 /* Allocate a database from the free list. */
71 database
= Kernel
->db
->freeDatabase
;
72 Kernel
->db
->freeDatabase
= database
->next
;
76 gctPOINTER pointer
= gcvNULL
;
78 /* Allocate a new database from the heap. */
79 gcmkONERROR(gckOS_Allocate(Kernel
->os
,
80 gcmSIZEOF(gcsDATABASE
),
86 /* Compute the hash for the database. */
87 slot
= ProcessID
% gcmCOUNTOF(Kernel
->db
->db
);
89 /* Insert the database into the hash. */
90 database
->next
= Kernel
->db
->db
[slot
];
91 Kernel
->db
->db
[slot
] = database
;
93 /* Save the hash slot. */
94 database
->slot
= slot
;
96 /* Release the database mutex. */
97 gcmkONERROR(gckOS_ReleaseMutex(Kernel
->os
, Kernel
->db
->dbMutex
));
99 /* Return the database. */
100 *Database
= database
;
103 gcmkFOOTER_ARG("*Database=0x%x", *Database
);
109 /* Release the database mutex. */
110 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel
->os
, Kernel
->db
->dbMutex
));
113 /* Return the status. */
118 /*******************************************************************************
119 ** gckKERNEL_FindDatabase
121 ** Find a database identified by a process ID and move it to the head of the
127 ** Pointer to a gckKERNEL object.
129 ** gctUINT32 ProcessID
130 ** ProcessID that identifies the database.
132 ** gctBOOL LastProcessID
133 ** gcvTRUE if searching for the last known process ID. gcvFALSE if
134 ** we need to search for the process ID specified by the ProcessID
139 ** gcsDATABASE_PTR * Database
140 ** Pointer to a variable receiving the database structure pointer on
144 gckKERNEL_FindDatabase(
146 IN gctUINT32 ProcessID
,
147 IN gctBOOL LastProcessID
,
148 OUT gcsDATABASE_PTR
* Database
152 gcsDATABASE_PTR database
, previous
;
154 gctBOOL acquired
= gcvFALSE
;
156 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d LastProcessID=%d",
157 Kernel
, ProcessID
, LastProcessID
);
159 /* Compute the hash for the database. */
160 slot
= ProcessID
% gcmCOUNTOF(Kernel
->db
->db
);
162 /* Acquire the database mutex. */
164 gckOS_AcquireMutex(Kernel
->os
, Kernel
->db
->dbMutex
, gcvINFINITE
));
167 /* Check whether we are getting the last known database. */
170 /* Use last database. */
171 database
= Kernel
->db
->lastDatabase
;
173 if (database
== gcvNULL
)
175 /* Database not found. */
176 gcmkONERROR(gcvSTATUS_INVALID_DATA
);
181 /* Walk the hash list. */
182 for (previous
= gcvNULL
, database
= Kernel
->db
->db
[slot
];
184 database
= database
->next
)
186 if (database
->processID
== ProcessID
)
195 if (database
== gcvNULL
)
197 /* Database not found. */
198 gcmkONERROR(gcvSTATUS_INVALID_DATA
);
201 if (previous
!= gcvNULL
)
203 /* Move database to the head of the hash list. */
204 previous
->next
= database
->next
;
205 database
->next
= Kernel
->db
->db
[slot
];
206 Kernel
->db
->db
[slot
] = database
;
210 /* Release the database mutex. */
211 gcmkONERROR(gckOS_ReleaseMutex(Kernel
->os
, Kernel
->db
->dbMutex
));
213 /* Return the database. */
214 *Database
= database
;
217 gcmkFOOTER_ARG("*Database=0x%x", *Database
);
223 /* Release the database mutex. */
224 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel
->os
, Kernel
->db
->dbMutex
));
227 /* Return the status. */
232 /*******************************************************************************
233 ** gckKERNEL_DeleteDatabase
235 ** Remove a database from the hash list and delete its structure.
240 ** Pointer to a gckKERNEL object.
242 ** gcsDATABASE_PTR Database
243 ** Pointer to the database structure to remove.
250 gckKERNEL_DeleteDatabase(
252 IN gcsDATABASE_PTR Database
256 gctBOOL acquired
= gcvFALSE
;
257 gcsDATABASE_PTR database
;
259 gcmkHEADER_ARG("Kernel=0x%x Database=0x%x", Kernel
, Database
);
261 /* Acquire the database mutex. */
263 gckOS_AcquireMutex(Kernel
->os
, Kernel
->db
->dbMutex
, gcvINFINITE
));
266 /* Check slot value. */
267 gcmkVERIFY_ARGUMENT(Database
->slot
< gcmCOUNTOF(Kernel
->db
->db
));
269 if (Database
->slot
< gcmCOUNTOF(Kernel
->db
->db
))
271 /* Check if database if the head of the hash list. */
272 if (Kernel
->db
->db
[Database
->slot
] == Database
)
274 /* Remove the database from the hash list. */
275 Kernel
->db
->db
[Database
->slot
] = Database
->next
;
279 /* Walk the has list to find the database. */
280 for (database
= Kernel
->db
->db
[Database
->slot
];
282 database
= database
->next
285 /* Check if the next list entry is this database. */
286 if (database
->next
== Database
)
288 /* Remove the database from the hash list. */
289 database
->next
= Database
->next
;
294 if (database
== gcvNULL
)
296 /* Ouch! Something got corrupted. */
297 gcmkONERROR(gcvSTATUS_INVALID_DATA
);
302 if (Kernel
->db
->lastDatabase
!= gcvNULL
)
304 /* Insert database to the free list. */
305 Kernel
->db
->lastDatabase
->next
= Kernel
->db
->freeDatabase
;
306 Kernel
->db
->freeDatabase
= Kernel
->db
->lastDatabase
;
309 /* Keep database as the last database. */
310 Kernel
->db
->lastDatabase
= Database
;
312 /* Release the database mutex. */
313 gcmkONERROR(gckOS_ReleaseMutex(Kernel
->os
, Kernel
->db
->dbMutex
));
322 /* Release the database mutex. */
323 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel
->os
, Kernel
->db
->dbMutex
));
326 /* Return the status. */
331 /*******************************************************************************
332 ** gckKERNEL_NewRecord
334 ** Create a new database record structure and insert it to the head of the
340 ** Pointer to a gckKERNEL object.
342 ** gcsDATABASE_PTR Database
343 ** Pointer to a database structure.
347 ** gcsDATABASE_RECORD_PTR * Record
348 ** Pointer to a variable receiving the database record structure
349 ** pointer on success.
354 IN gcsDATABASE_PTR Database
,
355 OUT gcsDATABASE_RECORD_PTR
* Record
359 gctBOOL acquired
= gcvFALSE
;
360 gcsDATABASE_RECORD_PTR record
= gcvNULL
;
362 gcmkHEADER_ARG("Kernel=0x%x Database=0x%x", Kernel
, Database
);
364 /* Acquire the database mutex. */
366 gckOS_AcquireMutex(Kernel
->os
, Kernel
->db
->dbMutex
, gcvINFINITE
));
369 if (Kernel
->db
->freeRecord
!= gcvNULL
)
371 /* Allocate the record from the free list. */
372 record
= Kernel
->db
->freeRecord
;
373 Kernel
->db
->freeRecord
= record
->next
;
377 gctPOINTER pointer
= gcvNULL
;
379 /* Allocate the record from the heap. */
380 gcmkONERROR(gckOS_Allocate(Kernel
->os
,
381 gcmSIZEOF(gcsDATABASE_RECORD
),
387 /* Insert the record in the database. */
388 record
->next
= Database
->list
;
389 Database
->list
= record
;
391 /* Release the database mutex. */
392 gcmkONERROR(gckOS_ReleaseMutex(Kernel
->os
, Kernel
->db
->dbMutex
));
394 /* Return the record. */
398 gcmkFOOTER_ARG("*Record=0x%x", *Record
);
404 /* Release the database mutex. */
405 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel
->os
, Kernel
->db
->dbMutex
));
407 if (record
!= gcvNULL
)
409 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Kernel
->os
, record
));
412 /* Return the status. */
417 /*******************************************************************************
418 ** gckKERNEL_DeleteRecord
420 ** Remove a database record from the database and delete its structure.
425 ** Pointer to a gckKERNEL object.
427 ** gcsDATABASE_PTR Database
428 ** Pointer to a database structure.
430 ** gceDATABASE_TYPE Type
431 ** Type of the record to remove.
434 ** Data of the record to remove.
438 ** gctSIZE_T_PTR Bytes
439 ** Pointer to a variable that receives the size of the record deleted.
440 ** Can be gcvNULL if the size is not required.
443 gckKERNEL_DeleteRecord(
445 IN gcsDATABASE_PTR Database
,
446 IN gceDATABASE_TYPE Type
,
448 OUT gctSIZE_T_PTR Bytes OPTIONAL
452 gctBOOL acquired
= gcvFALSE
;
453 gcsDATABASE_RECORD_PTR record
, previous
;
455 gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
456 Kernel
, Database
, Type
, Data
);
458 /* Acquire the database mutex. */
460 gckOS_AcquireMutex(Kernel
->os
, Kernel
->db
->dbMutex
, gcvINFINITE
));
463 /* Scan the database for this record. */
464 for (record
= Database
->list
, previous
= gcvNULL
;
466 record
= record
->next
469 if ((record
->type
== Type
)
470 && (record
->data
== Data
)
480 if (record
== gcvNULL
)
482 /* Ouch! This record is not found? */
483 gcmkONERROR(gcvSTATUS_INVALID_DATA
);
486 if (Bytes
!= gcvNULL
)
488 /* Return size of record. */
489 *Bytes
= record
->bytes
;
492 /* Remove record from database. */
493 if (previous
== gcvNULL
)
495 Database
->list
= record
->next
;
499 previous
->next
= record
->next
;
502 /* Insert record in free list. */
503 record
->next
= Kernel
->db
->freeRecord
;
504 Kernel
->db
->freeRecord
= record
;
506 /* Release the database mutex. */
507 gcmkONERROR(gckOS_ReleaseMutex(Kernel
->os
, Kernel
->db
->dbMutex
));
510 gcmkFOOTER_ARG("*Bytes=%lu", gcmOPT_VALUE(Bytes
));
516 /* Release the database mutex. */
517 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel
->os
, Kernel
->db
->dbMutex
));
520 /* Return the status. */
525 /*******************************************************************************
526 ** gckKERNEL_FindRecord
528 ** Find a database record from the database.
533 ** Pointer to a gckKERNEL object.
535 ** gcsDATABASE_PTR Database
536 ** Pointer to a database structure.
538 ** gceDATABASE_TYPE Type
539 ** Type of the record to remove.
542 ** Data of the record to remove.
546 ** gctSIZE_T_PTR Bytes
547 ** Pointer to a variable that receives the size of the record deleted.
548 ** Can be gcvNULL if the size is not required.
551 gckKERNEL_FindRecord(
553 IN gcsDATABASE_PTR Database
,
554 IN gceDATABASE_TYPE Type
,
556 OUT gcsDATABASE_RECORD_PTR Record
560 gctBOOL acquired
= gcvFALSE
;
561 gcsDATABASE_RECORD_PTR record
, previous
;
563 gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
564 Kernel
, Database
, Type
, Data
);
566 /* Acquire the database mutex. */
568 gckOS_AcquireMutex(Kernel
->os
, Kernel
->db
->dbMutex
, gcvINFINITE
));
571 /* Scan the database for this record. */
572 for (record
= Database
->list
, previous
= gcvNULL
;
574 record
= record
->next
577 if ((record
->type
== Type
)
578 && (record
->data
== Data
)
588 if (record
== gcvNULL
)
590 /* Ouch! This record is not found? */
591 gcmkONERROR(gcvSTATUS_INVALID_DATA
);
594 if (Record
!= gcvNULL
)
596 /* Return information of record. */
598 gckOS_MemCopy(Record
, record
, sizeof(gcsDATABASE_RECORD
)));
601 /* Release the database mutex. */
602 gcmkONERROR(gckOS_ReleaseMutex(Kernel
->os
, Kernel
->db
->dbMutex
));
605 gcmkFOOTER_ARG("Record=0x%x", Record
);
611 /* Release the database mutex. */
612 gcmkVERIFY_OK(gckOS_ReleaseMutex(Kernel
->os
, Kernel
->db
->dbMutex
));
615 /* Return the status. */
621 /*******************************************************************************
622 ***** Public API **************************************************************/
624 /*******************************************************************************
625 ** gckKERNEL_CreateProcessDB
627 ** Create a new process database.
632 ** Pointer to a gckKERNEL object.
634 ** gctUINT32 ProcessID
635 ** Process ID used to identify the database.
642 gckKERNEL_CreateProcessDB(
644 IN gctUINT32 ProcessID
648 gcsDATABASE_PTR database
= gcvNULL
;
650 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel
, ProcessID
);
652 /* Verify the arguments. */
653 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
655 /* Create a new database. */
656 gcmkONERROR(gckKERNEL_NewDatabase(Kernel
, ProcessID
, &database
));
658 /* Initialize the database. */
659 database
->processID
= ProcessID
;
660 database
->vidMem
.bytes
= 0;
661 database
->vidMem
.maxBytes
= 0;
662 database
->vidMem
.totalBytes
= 0;
663 database
->nonPaged
.bytes
= 0;
664 database
->nonPaged
.maxBytes
= 0;
665 database
->nonPaged
.totalBytes
= 0;
666 database
->contiguous
.bytes
= 0;
667 database
->contiguous
.maxBytes
= 0;
668 database
->contiguous
.totalBytes
= 0;
669 database
->mapMemory
.bytes
= 0;
670 database
->mapMemory
.maxBytes
= 0;
671 database
->mapMemory
.totalBytes
= 0;
672 database
->mapUserMemory
.bytes
= 0;
673 database
->mapUserMemory
.maxBytes
= 0;
674 database
->mapUserMemory
.totalBytes
= 0;
675 database
->list
= gcvNULL
;
680 gcskSECURE_CACHE
* cache
= &database
->cache
;
682 /* Setup the linked list of cache nodes. */
683 for (slot
= 1; slot
<= gcdSECURE_CACHE_SLOTS
; ++slot
)
685 cache
->cache
[slot
].logical
= gcvNULL
;
687 #if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
688 cache
->cache
[slot
].prev
= &cache
->cache
[slot
- 1];
689 cache
->cache
[slot
].next
= &cache
->cache
[slot
+ 1];
691 #if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
692 cache
->cache
[slot
].nextHash
= gcvNULL
;
693 cache
->cache
[slot
].prevHash
= gcvNULL
;
697 #if gcdSECURE_CACHE_METHOD != gcdSECURE_CACHE_TABLE
698 /* Setup the head and tail of the cache. */
699 cache
->cache
[0].next
= &cache
->cache
[1];
700 cache
->cache
[0].prev
= &cache
->cache
[gcdSECURE_CACHE_SLOTS
];
701 cache
->cache
[0].logical
= gcvNULL
;
703 /* Fix up the head and tail pointers. */
704 cache
->cache
[0].next
->prev
= &cache
->cache
[0];
705 cache
->cache
[0].prev
->next
= &cache
->cache
[0];
708 #if gcdSECURE_CACHE_METHOD == gcdSECURE_CACHE_HASH
709 /* Zero out the hash table. */
710 for (slot
= 0; slot
< gcmCOUNTOF(cache
->hash
); ++slot
)
712 cache
->hash
[slot
].logical
= gcvNULL
;
713 cache
->hash
[slot
].nextHash
= gcvNULL
;
717 /* Initialize cache index. */
718 cache
->cacheIndex
= gcvNULL
;
719 cache
->cacheFree
= 1;
720 cache
->cacheStamp
= 0;
724 /* Reset idle timer. */
725 Kernel
->db
->lastIdle
= 0;
732 /* Return the status. */
737 /*******************************************************************************
738 ** gckKERNEL_AddProcessDB
740 ** Add a record to a process database.
745 ** Pointer to a gckKERNEL object.
747 ** gctUINT32 ProcessID
748 ** Process ID used to identify the database.
750 ** gceDATABASE_TYPE TYPE
751 ** Type of the record to add.
753 ** gctPOINTER Pointer
754 ** Data of the record to add.
756 ** gctPHYS_ADDR Physical
757 ** Physical address of the record to add.
760 ** Size of the record to add.
767 gckKERNEL_AddProcessDB(
769 IN gctUINT32 ProcessID
,
770 IN gceDATABASE_TYPE Type
,
771 IN gctPOINTER Pointer
,
772 IN gctPHYS_ADDR Physical
,
777 gcsDATABASE_PTR database
;
778 gcsDATABASE_RECORD_PTR record
= gcvNULL
;
779 gcsDATABASE_COUNTERS
* count
;
781 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x "
782 "Physical=0x%x Size=%lu",
783 Kernel
, ProcessID
, Type
, Pointer
, Physical
, Size
);
785 /* Verify the arguments. */
786 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
788 /* Special case the idle record. */
789 if (Type
== gcvDB_IDLE
)
793 /* Get the current profile time. */
794 gcmkONERROR(gckOS_GetProfileTick(&time
));
796 if ((ProcessID
== 0) && (Kernel
->db
->lastIdle
!= 0))
798 /* Out of idle, adjust time it was idle. */
799 Kernel
->db
->idleTime
+= time
- Kernel
->db
->lastIdle
;
800 Kernel
->db
->lastIdle
= 0;
802 else if (ProcessID
== 1)
804 /* Save current idle time. */
805 Kernel
->db
->lastIdle
= time
;
810 /* Test for first call. */
811 if (Kernel
->db
->lastSlowdown
== 0)
813 /* Save milliseconds. */
814 Kernel
->db
->lastSlowdown
= time
;
815 Kernel
->db
->lastSlowdownIdle
= Kernel
->db
->idleTime
;
819 /* Compute ellapsed time in milliseconds. */
820 gctUINT delta
= gckOS_ProfileToMS(time
- Kernel
->db
->lastSlowdown
);
822 /* Test for end of period. */
823 if (delta
>= gcdDYNAMIC_SPEED
)
825 /* Compute number of idle milliseconds. */
826 gctUINT idle
= gckOS_ProfileToMS(
827 Kernel
->db
->idleTime
- Kernel
->db
->lastSlowdownIdle
);
829 /* Broadcast to slow down the GPU. */
830 gcmkONERROR(gckOS_BroadcastCalibrateSpeed(Kernel
->os
,
835 /* Save current time. */
836 Kernel
->db
->lastSlowdown
= time
;
837 Kernel
->db
->lastSlowdownIdle
= Kernel
->db
->idleTime
;
848 /* Verify the arguments. */
849 gcmkVERIFY_ARGUMENT(Pointer
!= gcvNULL
);
851 /* Find the database. */
852 gcmkONERROR(gckKERNEL_FindDatabase(Kernel
, ProcessID
, gcvFALSE
, &database
));
854 /* Create a new record in the database. */
855 gcmkONERROR(gckKERNEL_NewRecord(Kernel
, database
, &record
));
857 /* Initialize the record. */
858 record
->kernel
= Kernel
;
860 record
->data
= Pointer
;
861 record
->physical
= Physical
;
862 record
->bytes
= Size
;
864 /* Get pointer to counters. */
867 case gcvDB_VIDEO_MEMORY
:
868 count
= &database
->vidMem
;
871 case gcvDB_NON_PAGED
:
872 count
= &database
->nonPaged
;
875 case gcvDB_CONTIGUOUS
:
876 count
= &database
->contiguous
;
879 case gcvDB_MAP_MEMORY
:
880 count
= &database
->mapMemory
;
883 case gcvDB_MAP_USER_MEMORY
:
884 count
= &database
->mapUserMemory
;
892 if (count
!= gcvNULL
)
894 /* Adjust counters. */
895 count
->totalBytes
+= Size
;
896 count
->bytes
+= Size
;
898 if (count
->bytes
> count
->maxBytes
)
900 count
->maxBytes
= count
->bytes
;
909 /* Return the status. */
914 /*******************************************************************************
915 ** gckKERNEL_RemoveProcessDB
917 ** Remove a record from a process database.
922 ** Pointer to a gckKERNEL object.
924 ** gctUINT32 ProcessID
925 ** Process ID used to identify the database.
927 ** gceDATABASE_TYPE TYPE
928 ** Type of the record to remove.
930 ** gctPOINTER Pointer
931 ** Data of the record to remove.
938 gckKERNEL_RemoveProcessDB(
940 IN gctUINT32 ProcessID
,
941 IN gceDATABASE_TYPE Type
,
942 IN gctPOINTER Pointer
946 gcsDATABASE_PTR database
;
949 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x",
950 Kernel
, ProcessID
, Type
, Pointer
);
952 /* Verify the arguments. */
953 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
954 gcmkVERIFY_ARGUMENT(Pointer
!= gcvNULL
);
956 /* Find the database. */
957 gcmkONERROR(gckKERNEL_FindDatabase(Kernel
, ProcessID
, gcvFALSE
, &database
));
959 /* Delete the record. */
961 gckKERNEL_DeleteRecord(Kernel
, database
, Type
, Pointer
, &bytes
));
963 /* Update counters. */
966 case gcvDB_VIDEO_MEMORY
:
967 database
->vidMem
.bytes
-= bytes
;
970 case gcvDB_NON_PAGED
:
971 database
->nonPaged
.bytes
-= bytes
;
974 case gcvDB_CONTIGUOUS
:
975 database
->contiguous
.bytes
-= bytes
;
978 case gcvDB_MAP_MEMORY
:
979 database
->mapMemory
.bytes
-= bytes
;
982 case gcvDB_MAP_USER_MEMORY
:
983 database
->mapUserMemory
.bytes
-= bytes
;
995 /* Return the status. */
1000 /*******************************************************************************
1001 ** gckKERNEL_FindProcessDB
1003 ** Find a record from a process database.
1008 ** Pointer to a gckKERNEL object.
1010 ** gctUINT32 ProcessID
1011 ** Process ID used to identify the database.
1013 ** gceDATABASE_TYPE TYPE
1014 ** Type of the record to remove.
1016 ** gctPOINTER Pointer
1017 ** Data of the record to remove.
1021 ** gcsDATABASE_RECORD_PTR Record
1025 gckKERNEL_FindProcessDB(
1026 IN gckKERNEL Kernel
,
1027 IN gctUINT32 ProcessID
,
1028 IN gctUINT32 ThreadID
,
1029 IN gceDATABASE_TYPE Type
,
1030 IN gctPOINTER Pointer
,
1031 OUT gcsDATABASE_RECORD_PTR Record
1035 gcsDATABASE_PTR database
;
1037 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Pointer=0x%x",
1038 Kernel
, ProcessID
, ThreadID
, Type
, Pointer
);
1040 /* Verify the arguments. */
1041 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
1042 gcmkVERIFY_ARGUMENT(Pointer
!= gcvNULL
);
1044 /* Find the database. */
1045 gcmkONERROR(gckKERNEL_FindDatabase(Kernel
, ProcessID
, gcvFALSE
, &database
));
1047 /* Find the record. */
1049 gckKERNEL_FindRecord(Kernel
, database
, Type
, Pointer
, Record
));
1053 return gcvSTATUS_OK
;
1056 /* Return the status. */
1061 /*******************************************************************************
1062 ** gckKERNEL_DestroyProcessDB
1064 ** Destroy a process database. If the database contains any records, the data
1065 ** inside those records will be deleted as well. This aids in the cleanup if
1066 ** a process has died unexpectedly or has memory leaks.
1071 ** Pointer to a gckKERNEL object.
1073 ** gctUINT32 ProcessID
1074 ** Process ID used to identify the database.
1081 gckKERNEL_DestroyProcessDB(
1082 IN gckKERNEL Kernel
,
1083 IN gctUINT32 ProcessID
1087 gcsDATABASE_PTR database
;
1088 gcsDATABASE_RECORD_PTR record
, next
;
1089 gctBOOL asynchronous
;
1091 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel
, ProcessID
);
1093 /* Verify the arguments. */
1094 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
1096 /* Find the database. */
1097 gcmkONERROR(gckKERNEL_FindDatabase(Kernel
, ProcessID
, gcvFALSE
, &database
));
1099 gcmkTRACE_ZONE(gcvLEVEL_INFO
, gcvZONE_DATABASE
,
1100 "DB(%d): VidMem: total=%lu max=%lu",
1101 ProcessID
, database
->vidMem
.totalBytes
,
1102 database
->vidMem
.maxBytes
);
1103 gcmkTRACE_ZONE(gcvLEVEL_INFO
, gcvZONE_DATABASE
,
1104 "DB(%d): NonPaged: total=%lu max=%lu",
1105 ProcessID
, database
->nonPaged
.totalBytes
,
1106 database
->nonPaged
.maxBytes
);
1107 gcmkTRACE_ZONE(gcvLEVEL_INFO
, gcvZONE_DATABASE
,
1108 "DB(%d): Contiguous: total=%lu max=%lu",
1109 ProcessID
, database
->contiguous
.totalBytes
,
1110 database
->contiguous
.maxBytes
);
1111 gcmkTRACE_ZONE(gcvLEVEL_INFO
, gcvZONE_DATABASE
,
1112 "DB(%d): Idle time=%llu",
1113 ProcessID
, Kernel
->db
->idleTime
);
1114 gcmkTRACE_ZONE(gcvLEVEL_INFO
, gcvZONE_DATABASE
,
1115 "DB(%d): Map: total=%lu max=%lu",
1116 ProcessID
, database
->mapMemory
.totalBytes
,
1117 database
->mapMemory
.maxBytes
);
1118 gcmkTRACE_ZONE(gcvLEVEL_INFO
, gcvZONE_DATABASE
,
1119 "DB(%d): Map: total=%lu max=%lu",
1120 ProcessID
, database
->mapUserMemory
.totalBytes
,
1121 database
->mapUserMemory
.maxBytes
);
1123 if (database
->list
!= gcvNULL
)
1125 gcmkTRACE_ZONE(gcvLEVEL_WARNING
, gcvZONE_DATABASE
,
1126 "Process %d has entries in its database:",
1130 /* Walk all records. */
1131 for (record
= database
->list
; record
!= gcvNULL
; record
= next
)
1133 /* Next next record. */
1134 next
= record
->next
;
1136 /* Dispatch on record type. */
1137 switch (record
->type
)
1139 case gcvDB_VIDEO_MEMORY
:
1140 /* Free the video memory. */
1141 status
= gckVIDMEM_Free(record
->data
);
1143 gcmkTRACE_ZONE(gcvLEVEL_WARNING
, gcvZONE_DATABASE
,
1144 "DB: VIDEO_MEMORY 0x%x (status=%d)",
1145 record
->data
, status
);
1148 case gcvDB_NON_PAGED
:
1149 /* Free the non paged memory. */
1150 status
= gckOS_FreeNonPagedMemory(Kernel
->os
,
1155 gcmkTRACE_ZONE(gcvLEVEL_WARNING
, gcvZONE_DATABASE
,
1156 "DB: NON_PAGED 0x%x, bytes=%lu (status=%d)",
1157 record
->data
, record
->bytes
, status
);
1160 case gcvDB_CONTIGUOUS
:
1161 /* Free the contiguous memory. */
1162 status
= gckOS_FreeContiguous(Kernel
->os
,
1167 gcmkTRACE_ZONE(gcvLEVEL_WARNING
, gcvZONE_DATABASE
,
1168 "DB: CONTIGUOUS 0x%x bytes=%lu (status=%d)",
1169 record
->data
, record
->bytes
, status
);
1173 #if USE_NEW_LINUX_SIGNAL
1174 status
= gcvSTATUS_NOT_SUPPORTED
;
1176 /* Free the user signal. */
1177 status
= gckOS_DestroyUserSignal(Kernel
->os
,
1178 gcmPTR2INT(record
->data
));
1179 #endif /* USE_NEW_LINUX_SIGNAL */
1181 gcmkTRACE_ZONE(gcvLEVEL_WARNING
, gcvZONE_DATABASE
,
1182 "DB: SIGNAL %d (status=%d)",
1183 (gctINT
) record
->data
, status
);
1186 case gcvDB_VIDEO_MEMORY_LOCKED
:
1187 /* Unlock what we still locked */
1188 status
= gckVIDMEM_Unlock(record
->kernel
,
1190 gcvSURF_TYPE_UNKNOWN
,
1193 if (gcmIS_SUCCESS(status
) && (gcvTRUE
== asynchronous
))
1195 /* TODO: we maybe need to schedule a event here */
1196 status
= gckVIDMEM_Unlock(record
->kernel
,
1198 gcvSURF_TYPE_UNKNOWN
,
1202 gcmkTRACE_ZONE(gcvLEVEL_WARNING
, gcvZONE_DATABASE
,
1203 "DB: VIDEO_MEMORY_LOCKED 0x%x (status=%d)",
1204 record
->data
, status
);
1208 /* TODO: Free the context */
1209 status
= gckCOMMAND_Detach(Kernel
->command
, record
->data
);
1211 gcmkTRACE_ZONE(gcvLEVEL_WARNING
, gcvZONE_DATABASE
,
1212 "DB: CONTEXT 0x%x (status=%d)",
1213 record
->data
, status
);
1216 case gcvDB_MAP_MEMORY
:
1218 status
= gckKERNEL_UnmapMemory(Kernel
,
1223 gcmkTRACE_ZONE(gcvLEVEL_WARNING
, gcvZONE_DATABASE
,
1224 "DB: MAP MEMORY %d (status=%d)",
1225 gcmPTR2INT(record
->data
), status
);
1228 case gcvDB_MAP_USER_MEMORY
:
1229 /* TODO: Unmap user memory. */
1230 status
= gckOS_UnmapUserMemoryEx(Kernel
->os
,
1237 gcmkTRACE_ZONE(gcvLEVEL_WARNING
, gcvZONE_DATABASE
,
1238 "DB: MAP USER MEMORY %d (status=%d)",
1239 gcmPTR2INT(record
->data
), status
);
1242 case gcvDB_SHARED_INFO
:
1243 status
= gckOS_FreeMemory(Kernel
->os
, record
->physical
);
1247 gcmkTRACE_ZONE(gcvLEVEL_ERROR
, gcvZONE_DATABASE
,
1248 "DB: Correcupted record=0x%08x type=%d",
1249 record
, record
->type
);
1253 /* Delete the record. */
1254 gcmkONERROR(gckKERNEL_DeleteRecord(Kernel
,
1261 /* Delete the database. */
1262 gcmkONERROR(gckKERNEL_DeleteDatabase(Kernel
, database
));
1266 return gcvSTATUS_OK
;
1269 /* Return the status. */
1274 /*******************************************************************************
1275 ** gckKERNEL_QueryProcessDB
1277 ** Query a process database for the current usage of a particular record type.
1282 ** Pointer to a gckKERNEL object.
1284 ** gctUINT32 ProcessID
1285 ** Process ID used to identify the database.
1287 ** gctBOOL LastProcessID
1288 ** gcvTRUE if searching for the last known process ID. gcvFALSE if
1289 ** we need to search for the process ID specified by the ProcessID
1292 ** gceDATABASE_TYPE Type
1293 ** Type of the record to query.
1297 ** gcuDATABASE_INFO * Info
1298 ** Pointer to a variable that receives the requested information.
1301 gckKERNEL_QueryProcessDB(
1302 IN gckKERNEL Kernel
,
1303 IN gctUINT32 ProcessID
,
1304 IN gctBOOL LastProcessID
,
1305 IN gceDATABASE_TYPE Type
,
1306 OUT gcuDATABASE_INFO
* Info
1310 gcsDATABASE_PTR database
;
1312 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d Type=%d Info=0x%x",
1313 Kernel
, ProcessID
, Type
, Info
);
1315 /* Verify the arguments. */
1316 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
1317 gcmkVERIFY_ARGUMENT(Info
!= gcvNULL
);
1319 /* Find the database. */
1321 gckKERNEL_FindDatabase(Kernel
, ProcessID
, LastProcessID
, &database
));
1323 /* Get pointer to counters. */
1326 case gcvDB_VIDEO_MEMORY
:
1327 gcmkONERROR(gckOS_MemCopy(&Info
->counters
,
1329 gcmSIZEOF(database
->vidMem
)));
1332 case gcvDB_NON_PAGED
:
1333 gcmkONERROR(gckOS_MemCopy(&Info
->counters
,
1334 &database
->nonPaged
,
1335 gcmSIZEOF(database
->vidMem
)));
1338 case gcvDB_CONTIGUOUS
:
1339 gcmkONERROR(gckOS_MemCopy(&Info
->counters
,
1340 &database
->contiguous
,
1341 gcmSIZEOF(database
->vidMem
)));
1345 Info
->time
= Kernel
->db
->idleTime
;
1346 Kernel
->db
->idleTime
= 0;
1349 case gcvDB_MAP_MEMORY
:
1350 gcmkONERROR(gckOS_MemCopy(&Info
->counters
,
1351 &database
->mapMemory
,
1352 gcmSIZEOF(database
->mapMemory
)));
1355 case gcvDB_MAP_USER_MEMORY
:
1356 gcmkONERROR(gckOS_MemCopy(&Info
->counters
,
1357 &database
->mapUserMemory
,
1358 gcmSIZEOF(database
->mapUserMemory
)));
1367 return gcvSTATUS_OK
;
1370 /* Return the status. */
1376 /*******************************************************************************
1377 ** gckKERNEL_GetProcessDBCache
1379 ** Get teh secure cache from a process database.
1384 ** Pointer to a gckKERNEL object.
1386 ** gctUINT32 ProcessID
1387 ** Process ID used to identify the database.
1391 ** gcskSECURE_CACHE_PTR * Cache
1392 ** Pointer to a variable that receives the secure cache pointer.
1395 gckKERNEL_GetProcessDBCache(
1396 IN gckKERNEL Kernel
,
1397 IN gctUINT32 ProcessID
,
1398 OUT gcskSECURE_CACHE_PTR
* Cache
1402 gcsDATABASE_PTR database
;
1404 gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel
, ProcessID
);
1406 /* Verify the arguments. */
1407 gcmkVERIFY_OBJECT(Kernel
, gcvOBJ_KERNEL
);
1408 gcmkVERIFY_ARGUMENT(Cache
!= gcvNULL
);
1410 /* Find the database. */
1411 gcmkONERROR(gckKERNEL_FindDatabase(Kernel
, ProcessID
, gcvFALSE
, &database
));
1413 /* Return the pointer to the cache. */
1414 *Cache
= &database
->cache
;
1417 gcmkFOOTER_ARG("*Cache=0x%x", *Cache
);
1418 return gcvSTATUS_OK
;
1421 /* Return the status. */