ENGR00156850 gpu-viv: add gpu-viv driver source
[wandboard.git] / drivers / mxc / gpu-viv / hal / kernel / gc_hal_kernel_heap.c
blob597c97916c52fd65ba6e7997ce400d3b61f3aa3c
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 /**
25 ** @file
26 ** gckHEAP object for kernel HAL layer. The heap implemented here is an arena-
27 ** based memory allocation. An arena-based memory heap allocates data quickly
28 ** from specified arenas and reduces memory fragmentation.
31 #include "gc_hal_kernel_precomp.h"
33 #define _GC_OBJ_ZONE gcvZONE_HEAP
35 /*******************************************************************************
36 ***** Structures ***************************************************************
37 *******************************************************************************/
39 #define gcdIN_USE ((gcskNODE_PTR) ~0)
41 typedef struct _gcskNODE * gcskNODE_PTR;
42 typedef struct _gcskNODE
44 /* Number of byets in node. */
45 gctSIZE_T bytes;
47 /* Pointer to next free node, or gcvNULL to mark the node as freed, or
48 ** gcdIN_USE to mark the node as used. */
49 gcskNODE_PTR next;
51 #if gcmIS_DEBUG(gcdDEBUG_CODE)
52 /* Time stamp of allocation. */
53 gctUINT64 timeStamp;
54 #endif
56 gcskNODE;
58 typedef struct _gcskHEAP * gcskHEAP_PTR;
59 typedef struct _gcskHEAP
61 /* Linked list. */
62 gcskHEAP_PTR next;
63 gcskHEAP_PTR prev;
65 /* Heap size. */
66 gctSIZE_T size;
68 /* Free list. */
69 gcskNODE_PTR freeList;
71 gcskHEAP;
73 struct _gckHEAP
75 /* Object. */
76 gcsOBJECT object;
78 /* Pointer to a gckOS object. */
79 gckOS os;
81 /* Locking mutex. */
82 gctPOINTER mutex;
84 /* Allocation parameters. */
85 gctSIZE_T allocationSize;
87 /* Heap list. */
88 gcskHEAP_PTR heap;
89 #if gcmIS_DEBUG(gcdDEBUG_CODE)
90 gctUINT64 timeStamp;
91 #endif
93 #if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
94 /* Profile information. */
95 gctUINT32 allocCount;
96 gctUINT64 allocBytes;
97 gctUINT64 allocBytesMax;
98 gctUINT64 allocBytesTotal;
99 gctUINT32 heapCount;
100 gctUINT32 heapCountMax;
101 gctUINT64 heapMemory;
102 gctUINT64 heapMemoryMax;
103 #endif
106 /*******************************************************************************
107 ***** Static Support Functions *************************************************
108 *******************************************************************************/
110 #if gcmIS_DEBUG(gcdDEBUG_CODE)
111 static gctSIZE_T
112 _DumpHeap(
113 IN gcskHEAP_PTR Heap
116 gctPOINTER p;
117 gctSIZE_T leaked = 0;
119 /* Start at first node. */
120 for (p = Heap + 1;;)
122 /* Convert the pointer. */
123 gcskNODE_PTR node = (gcskNODE_PTR) p;
125 /* Check if this is a used node. */
126 if (node->next == gcdIN_USE)
128 /* Print the leaking node. */
129 gcmkTRACE_ZONE(gcvLEVEL_WARNING, gcvZONE_HEAP,
130 "Detected leaking: node=0x%x bytes=%lu timeStamp=%llu "
131 "(%08X %c%c%c%c)",
132 node, node->bytes, node->timeStamp,
133 ((gctUINT32_PTR) (node + 1))[0],
134 gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[0]),
135 gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[1]),
136 gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[2]),
137 gcmPRINTABLE(((gctUINT8_PTR) (node + 1))[3]));
139 /* Add leaking byte count. */
140 leaked += node->bytes;
143 /* Test for end of heap. */
144 if (node->bytes == 0)
146 break;
149 else
151 /* Move to next node. */
152 p = (gctUINT8_PTR) node + node->bytes;
156 /* Return the number of leaked bytes. */
157 return leaked;
159 #endif
161 static gceSTATUS
162 _CompactKernelHeap(
163 IN gckHEAP Heap
166 gcskHEAP_PTR heap, next;
167 gctPOINTER p;
168 gcskHEAP_PTR freeList = gcvNULL;
170 gcmkHEADER_ARG("Heap=0x%x", Heap);
172 /* Walk all the heaps. */
173 for (heap = Heap->heap; heap != gcvNULL; heap = next)
175 gcskNODE_PTR lastFree = gcvNULL;
177 /* Zero out the free list. */
178 heap->freeList = gcvNULL;
180 /* Start at the first node. */
181 for (p = (gctUINT8_PTR) (heap + 1);;)
183 /* Convert the pointer. */
184 gcskNODE_PTR node = (gcskNODE_PTR) p;
186 gcmkASSERT(p <= (gctPOINTER) ((gctUINT8_PTR) (heap + 1) + heap->size));
188 /* Test if this node not used. */
189 if (node->next != gcdIN_USE)
191 /* Test if this is the end of the heap. */
192 if (node->bytes == 0)
194 break;
197 /* Test of this is the first free node. */
198 else if (lastFree == gcvNULL)
200 /* Initialzie the free list. */
201 heap->freeList = node;
202 lastFree = node;
205 else
207 /* Test if this free node is contiguous with the previous
208 ** free node. */
209 if ((gctUINT8_PTR) lastFree + lastFree->bytes == p)
211 /* Just increase the size of the previous free node. */
212 lastFree->bytes += node->bytes;
214 else
216 /* Add to linked list. */
217 lastFree->next = node;
218 lastFree = node;
223 /* Move to next node. */
224 p = (gctUINT8_PTR) node + node->bytes;
227 /* Mark the end of the chain. */
228 if (lastFree != gcvNULL)
230 lastFree->next = gcvNULL;
233 /* Get next heap. */
234 next = heap->next;
236 /* Check if the entire heap is free. */
237 if ((heap->freeList != gcvNULL)
238 && (heap->freeList->bytes == heap->size - gcmSIZEOF(gcskNODE))
241 /* Remove the heap from the linked list. */
242 if (heap->prev == gcvNULL)
244 Heap->heap = next;
246 else
248 heap->prev->next = next;
251 if (heap->next != gcvNULL)
253 heap->next->prev = heap->prev;
256 #if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
257 /* Update profiling. */
258 Heap->heapCount -= 1;
259 Heap->heapMemory -= heap->size + gcmSIZEOF(gcskHEAP);
260 #endif
262 /* Add this heap to the list of heaps that need to be freed. */
263 heap->next = freeList;
264 freeList = heap;
268 if (freeList != gcvNULL)
270 /* Release the mutex, remove any chance for a dead lock. */
271 gcmkVERIFY_OK(
272 gckOS_ReleaseMutex(Heap->os, Heap->mutex));
274 /* Free all heaps in the free list. */
275 for (heap = freeList; heap != gcvNULL; heap = next)
277 /* Get pointer to the next heap. */
278 next = heap->next;
280 /* Free the heap. */
281 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
282 "Freeing heap 0x%x (%lu bytes)",
283 heap, heap->size + gcmSIZEOF(gcskHEAP));
284 gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
287 /* Acquire the mutex again. */
288 gcmkVERIFY_OK(
289 gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
292 /* Success. */
293 gcmkFOOTER_NO();
294 return gcvSTATUS_OK;
297 /*******************************************************************************
298 ***** gckHEAP API Code *********************************************************
299 *******************************************************************************/
301 /*******************************************************************************
303 ** gckHEAP_Construct
305 ** Construct a new gckHEAP object.
307 ** INPUT:
309 ** gckOS Os
310 ** Pointer to a gckOS object.
312 ** gctSIZE_T AllocationSize
313 ** Minimum size per arena.
315 ** OUTPUT:
317 ** gckHEAP * Heap
318 ** Pointer to a variable that will hold the pointer to the gckHEAP
319 ** object.
321 gceSTATUS
322 gckHEAP_Construct(
323 IN gckOS Os,
324 IN gctSIZE_T AllocationSize,
325 OUT gckHEAP * Heap
328 gceSTATUS status;
329 gckHEAP heap = gcvNULL;
330 gctPOINTER pointer = gcvNULL;
332 gcmkHEADER_ARG("Os=0x%x AllocationSize=%lu", Os, AllocationSize);
334 /* Verify the arguments. */
335 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
336 gcmkVERIFY_ARGUMENT(Heap != gcvNULL);
338 /* Allocate the gckHEAP object. */
339 gcmkONERROR(gckOS_AllocateMemory(Os,
340 gcmSIZEOF(struct _gckHEAP),
341 &pointer));
343 heap = pointer;
345 /* Initialize the gckHEAP object. */
346 heap->object.type = gcvOBJ_HEAP;
347 heap->os = Os;
348 heap->allocationSize = AllocationSize;
349 heap->heap = gcvNULL;
350 #if gcmIS_DEBUG(gcdDEBUG_CODE)
351 heap->timeStamp = 0;
352 #endif
354 #if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
355 /* Zero the counters. */
356 heap->allocCount = 0;
357 heap->allocBytes = 0;
358 heap->allocBytesMax = 0;
359 heap->allocBytesTotal = 0;
360 heap->heapCount = 0;
361 heap->heapCountMax = 0;
362 heap->heapMemory = 0;
363 heap->heapMemoryMax = 0;
364 #endif
366 /* Create the mutex. */
367 gcmkONERROR(gckOS_CreateMutex(Os, &heap->mutex));
369 /* Return the pointer to the gckHEAP object. */
370 *Heap = heap;
372 /* Success. */
373 gcmkFOOTER_ARG("*Heap=0x%x", *Heap);
374 return gcvSTATUS_OK;
376 OnError:
377 /* Roll back. */
378 if (heap != gcvNULL)
380 /* Free the heap structure. */
381 gcmkVERIFY_OK(gckOS_FreeMemory(Os, heap));
384 /* Return the status. */
385 gcmkFOOTER();
386 return status;
389 /*******************************************************************************
391 ** gckHEAP_Destroy
393 ** Destroy a gckHEAP object.
395 ** INPUT:
397 ** gckHEAP Heap
398 ** Pointer to a gckHEAP object to destroy.
400 ** OUTPUT:
402 ** Nothing.
404 gceSTATUS
405 gckHEAP_Destroy(
406 IN gckHEAP Heap
409 gcskHEAP_PTR heap;
410 #if gcmIS_DEBUG(gcdDEBUG_CODE)
411 gctSIZE_T leaked = 0;
412 #endif
414 gcmkHEADER_ARG("Heap=0x%x", Heap);
416 for (heap = Heap->heap; heap != gcvNULL; heap = Heap->heap)
418 /* Unlink heap from linked list. */
419 Heap->heap = heap->next;
421 #if gcmIS_DEBUG(gcdDEBUG_CODE)
422 /* Check for leaked memory. */
423 leaked += _DumpHeap(heap);
424 #endif
426 /* Free the heap. */
427 gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, heap));
430 /* Free the mutex. */
431 gcmkVERIFY_OK(gckOS_DeleteMutex(Heap->os, Heap->mutex));
433 /* Free the heap structure. */
434 gcmkVERIFY_OK(gckOS_FreeMemory(Heap->os, Heap));
436 /* Success. */
437 #if gcmIS_DEBUG(gcdDEBUG_CODE)
438 gcmkFOOTER_ARG("leaked=%lu", leaked);
439 #else
440 gcmkFOOTER_NO();
441 #endif
442 return gcvSTATUS_OK;
445 /*******************************************************************************
447 ** gckHEAP_Allocate
449 ** Allocate data from the heap.
451 ** INPUT:
453 ** gckHEAP Heap
454 ** Pointer to a gckHEAP object.
456 ** IN gctSIZE_T Bytes
457 ** Number of byte to allocate.
459 ** OUTPUT:
461 ** gctPOINTER * Memory
462 ** Pointer to a variable that will hold the address of the allocated
463 ** memory.
465 gceSTATUS
466 gckHEAP_Allocate(
467 IN gckHEAP Heap,
468 IN gctSIZE_T Bytes,
469 OUT gctPOINTER * Memory
472 gctBOOL acquired = gcvFALSE;
473 gcskHEAP_PTR heap;
474 gceSTATUS status;
475 gctSIZE_T bytes;
476 gcskNODE_PTR node, used, prevFree = gcvNULL;
477 gctPOINTER memory = gcvNULL;
479 gcmkHEADER_ARG("Heap=0x%x Bytes=%lu", Heap, Bytes);
481 /* Verify the arguments. */
482 gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
483 gcmkVERIFY_ARGUMENT(Bytes > 0);
484 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
486 /* Determine number of bytes required for a node. */
487 bytes = gcmALIGN(Bytes + gcmSIZEOF(gcskNODE), 8);
489 /* Acquire the mutex. */
490 gcmkONERROR(
491 gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
493 acquired = gcvTRUE;
495 /* Check if this allocation is bigger than the default allocation size. */
496 if (bytes > Heap->allocationSize - gcmSIZEOF(gcskHEAP) - gcmSIZEOF(gcskNODE))
498 /* Adjust allocation size. */
499 Heap->allocationSize = bytes * 2;
502 else if (Heap->heap != gcvNULL)
504 gctINT i;
506 /* 2 retries, since we might need to compact. */
507 for (i = 0; i < 2; ++i)
509 /* Walk all the heaps. */
510 for (heap = Heap->heap; heap != gcvNULL; heap = heap->next)
512 /* Check if this heap has enough bytes to hold the request. */
513 if (bytes <= heap->size - gcmSIZEOF(gcskNODE))
515 prevFree = gcvNULL;
517 /* Walk the chain of free nodes. */
518 for (node = heap->freeList;
519 node != gcvNULL;
520 node = node->next
523 gcmkASSERT(node->next != gcdIN_USE);
525 /* Check if this free node has enough bytes. */
526 if (node->bytes >= bytes)
528 /* Use the node. */
529 goto UseNode;
532 /* Save current free node for linked list management. */
533 prevFree = node;
538 if (i == 0)
540 /* Compact the heap. */
541 gcmkVERIFY_OK(_CompactKernelHeap(Heap));
543 #if gcmIS_DEBUG(gcdDEBUG_CODE)
544 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
545 "===== KERNEL HEAP =====");
546 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
547 "Number of allocations : %12u",
548 Heap->allocCount);
549 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
550 "Number of bytes allocated : %12llu",
551 Heap->allocBytes);
552 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
553 "Maximum allocation size : %12llu",
554 Heap->allocBytesMax);
555 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
556 "Total number of bytes allocated : %12llu",
557 Heap->allocBytesTotal);
558 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
559 "Number of heaps : %12u",
560 Heap->heapCount);
561 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
562 "Heap memory in bytes : %12llu",
563 Heap->heapMemory);
564 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
565 "Maximum number of heaps : %12u",
566 Heap->heapCountMax);
567 gcmkTRACE_ZONE(gcvLEVEL_VERBOSE, gcvZONE_HEAP,
568 "Maximum heap memory in bytes : %12llu",
569 Heap->heapMemoryMax);
570 #endif
575 /* Release the mutex. */
576 gcmkONERROR(
577 gckOS_ReleaseMutex(Heap->os, Heap->mutex));
579 acquired = gcvFALSE;
581 /* Allocate a new heap. */
582 gcmkONERROR(
583 gckOS_AllocateMemory(Heap->os,
584 Heap->allocationSize,
585 &memory));
587 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_HEAP,
588 "Allocated heap 0x%x (%lu bytes)",
589 memory, Heap->allocationSize);
591 /* Acquire the mutex. */
592 gcmkONERROR(
593 gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
595 acquired = gcvTRUE;
597 /* Use the allocated memory as the heap. */
598 heap = (gcskHEAP_PTR) memory;
600 /* Insert this heap to the head of the chain. */
601 heap->next = Heap->heap;
602 heap->prev = gcvNULL;
603 heap->size = Heap->allocationSize - gcmSIZEOF(gcskHEAP);
605 if (heap->next != gcvNULL)
607 heap->next->prev = heap;
609 Heap->heap = heap;
611 /* Mark the end of the heap. */
612 node = (gcskNODE_PTR) ( (gctUINT8_PTR) heap
613 + Heap->allocationSize
614 - gcmSIZEOF(gcskNODE)
616 node->bytes = 0;
617 node->next = gcvNULL;
619 /* Create a free list. */
620 node = (gcskNODE_PTR) (heap + 1);
621 heap->freeList = node;
623 /* Initialize the free list. */
624 node->bytes = heap->size - gcmSIZEOF(gcskNODE);
625 node->next = gcvNULL;
627 /* No previous free. */
628 prevFree = gcvNULL;
630 #if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
631 /* Update profiling. */
632 Heap->heapCount += 1;
633 Heap->heapMemory += Heap->allocationSize;
635 if (Heap->heapCount > Heap->heapCountMax)
637 Heap->heapCountMax = Heap->heapCount;
639 if (Heap->heapMemory > Heap->heapMemoryMax)
641 Heap->heapMemoryMax = Heap->heapMemory;
643 #endif
645 UseNode:
646 /* Verify some stuff. */
647 gcmkASSERT(heap != gcvNULL);
648 gcmkASSERT(node != gcvNULL);
649 gcmkASSERT(node->bytes >= bytes);
651 if (heap->prev != gcvNULL)
653 /* Unlink the heap from the linked list. */
654 heap->prev->next = heap->next;
655 if (heap->next != gcvNULL)
657 heap->next->prev = heap->prev;
660 /* Move the heap to the front of the list. */
661 heap->next = Heap->heap;
662 heap->prev = gcvNULL;
663 Heap->heap = heap;
664 heap->next->prev = heap;
667 /* Check if there is enough free space left after usage for another free
668 ** node. */
669 if (node->bytes - bytes >= gcmSIZEOF(gcskNODE))
671 /* Allocated used space from the back of the free list. */
672 used = (gcskNODE_PTR) ((gctUINT8_PTR) node + node->bytes - bytes);
674 /* Adjust the number of free bytes. */
675 node->bytes -= bytes;
676 gcmkASSERT(node->bytes >= gcmSIZEOF(gcskNODE));
678 else
680 /* Remove this free list from the chain. */
681 if (prevFree == gcvNULL)
683 heap->freeList = node->next;
685 else
687 prevFree->next = node->next;
690 /* Consume the entire free node. */
691 used = (gcskNODE_PTR) node;
692 bytes = node->bytes;
695 /* Mark node as used. */
696 used->bytes = bytes;
697 used->next = gcdIN_USE;
698 #if gcmIS_DEBUG(gcdDEBUG_CODE)
699 used->timeStamp = ++Heap->timeStamp;
700 #endif
702 #if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
703 /* Update profile counters. */
704 Heap->allocCount += 1;
705 Heap->allocBytes += bytes;
706 Heap->allocBytesMax = gcmMAX(Heap->allocBytes, Heap->allocBytesMax);
707 Heap->allocBytesTotal += bytes;
708 #endif
710 /* Release the mutex. */
711 gcmkVERIFY_OK(
712 gckOS_ReleaseMutex(Heap->os, Heap->mutex));
714 /* Return pointer to memory. */
715 *Memory = used + 1;
717 /* Success. */
718 gcmkFOOTER_ARG("*Memory=0x%x", *Memory);
719 return gcvSTATUS_OK;
721 OnError:
722 if (acquired)
724 /* Release the mutex. */
725 gcmkVERIFY_OK(
726 gckOS_ReleaseMutex(Heap->os, Heap->mutex));
729 if (memory != gcvNULL)
731 /* Free the heap memory. */
732 gckOS_FreeMemory(Heap->os, memory);
735 /* Return the status. */
736 gcmkFOOTER();
737 return status;
740 /*******************************************************************************
742 ** gckHEAP_Free
744 ** Free allocated memory from the heap.
746 ** INPUT:
748 ** gckHEAP Heap
749 ** Pointer to a gckHEAP object.
751 ** IN gctPOINTER Memory
752 ** Pointer to memory to free.
754 ** OUTPUT:
756 ** NOTHING.
758 gceSTATUS
759 gckHEAP_Free(
760 IN gckHEAP Heap,
761 IN gctPOINTER Memory
764 gcskNODE_PTR node;
765 gceSTATUS status;
767 gcmkHEADER_ARG("Heap=0x%x Memory=0x%x", Heap, Memory);
769 /* Verify the arguments. */
770 gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
771 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
773 /* Acquire the mutex. */
774 gcmkONERROR(
775 gckOS_AcquireMutex(Heap->os, Heap->mutex, gcvINFINITE));
777 /* Pointer to structure. */
778 node = (gcskNODE_PTR) Memory - 1;
780 /* Mark the node as freed. */
781 node->next = gcvNULL;
783 #if VIVANTE_PROFILER || gcmIS_DEBUG(gcdDEBUG_CODE)
784 /* Update profile counters. */
785 Heap->allocBytes -= node->bytes;
786 #endif
788 /* Release the mutex. */
789 gcmkVERIFY_OK(
790 gckOS_ReleaseMutex(Heap->os, Heap->mutex));
792 /* Success. */
793 gcmkFOOTER_NO();
794 return gcvSTATUS_OK;
796 OnError:
797 /* Return the status. */
798 gcmkFOOTER();
799 return status;
802 #if VIVANTE_PROFILER
803 gceSTATUS
804 gckHEAP_ProfileStart(
805 IN gckHEAP Heap
808 gcmkHEADER_ARG("Heap=0x%x", Heap);
810 /* Verify the arguments. */
811 gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
813 /* Zero the counters. */
814 Heap->allocCount = 0;
815 Heap->allocBytes = 0;
816 Heap->allocBytesMax = 0;
817 Heap->allocBytesTotal = 0;
818 Heap->heapCount = 0;
819 Heap->heapCountMax = 0;
820 Heap->heapMemory = 0;
821 Heap->heapMemoryMax = 0;
823 /* Success. */
824 gcmkFOOTER_NO();
825 return gcvSTATUS_OK;
828 gceSTATUS
829 gckHEAP_ProfileEnd(
830 IN gckHEAP Heap,
831 IN gctCONST_STRING Title
834 gcmkHEADER_ARG("Heap=0x%x Title=0x%x", Heap, Title);
836 /* Verify the arguments. */
837 gcmkVERIFY_OBJECT(Heap, gcvOBJ_HEAP);
838 gcmkVERIFY_ARGUMENT(Title != gcvNULL);
840 gcmkPRINT("");
841 gcmkPRINT("=====[ HEAP - %s ]=====", Title);
842 gcmkPRINT("Number of allocations : %12u", Heap->allocCount);
843 gcmkPRINT("Number of bytes allocated : %12llu", Heap->allocBytes);
844 gcmkPRINT("Maximum allocation size : %12llu", Heap->allocBytesMax);
845 gcmkPRINT("Total number of bytes allocated : %12llu", Heap->allocBytesTotal);
846 gcmkPRINT("Number of heaps : %12u", Heap->heapCount);
847 gcmkPRINT("Heap memory in bytes : %12llu", Heap->heapMemory);
848 gcmkPRINT("Maximum number of heaps : %12u", Heap->heapCountMax);
849 gcmkPRINT("Maximum heap memory in bytes : %12llu", Heap->heapMemoryMax);
850 gcmkPRINT("==============================================");
852 /* Success. */
853 gcmkFOOTER_NO();
854 return gcvSTATUS_OK;
856 #endif /* VIVANTE_PROFILER */
858 /*******************************************************************************
859 ***** Test Code ****************************************************************
860 *******************************************************************************/