*partial commit* - Added debut name to VFS_SelectNode
[tpg/acess2.git] / Kernel / heap.c
1 /*
2  * AcessOS Microkernel Version
3  * heap.c
4  */
5 #include <acess.h>
6 #include <mm_virt.h>
7 #include <heap_int.h>
8
9 #define WARNINGS        1
10 #define DEBUG_TRACE     0
11 #define VERBOSE_DUMP    0
12
13 // === CONSTANTS ===
14 #define HEAP_INIT_SIZE  0x8000  // 32 KiB
15 #define MIN_SIZE        (sizeof(void*))*8       // 8 Machine Words
16 #define POW2_SIZES      0
17 #define COMPACT_HEAP    0       // Use 4 byte header?
18 #define FIRST_FIT       0
19
20 //#define       MAGIC_FOOT      0x2ACE5505
21 //#define       MAGIC_FREE      0xACE55000
22 //#define       MAGIC_USED      0x862B0505      // MAGIC_FOOT ^ MAGIC_FREE
23 #define MAGIC_FOOT      0x544F4F46      // 'FOOT'
24 #define MAGIC_FREE      0x45455246      // 'FREE'
25 #define MAGIC_USED      0x44455355      // 'USED'
26
27 // === PROTOTYPES ===
28 void    Heap_Install(void);
29 void    *Heap_Extend(int Bytes);
30 void    *Heap_Merge(tHeapHead *Head);
31 //void  *Heap_Allocate(const char *File, int Line, size_t Bytes);
32 //void  *Heap_AllocateZero(const char *File, int Line, size_t Bytes);
33 //void  *Heap_Reallocate(const char *File, int Line, void *Ptr, size_t Bytes);
34 //void  Heap_Deallocate(void *Ptr);
35 void    Heap_Dump(void);
36 void    Heap_Stats(void);
37
38 // === GLOBALS ===
39 tMutex  glHeap;
40 void    *gHeapStart;
41 void    *gHeapEnd;
42
43 // === CODE ===
44 void Heap_Install(void)
45 {
46         gHeapStart      = (void*)MM_KHEAP_BASE;
47         gHeapEnd        = (void*)MM_KHEAP_BASE;
48         Heap_Extend(HEAP_INIT_SIZE);
49 }
50
51 /**
52  * \fn void *Heap_Extend(int Bytes)
53  * \brief Extend the size of the heap
54  */
55 void *Heap_Extend(int Bytes)
56 {
57         Uint    i;
58         tHeapHead       *head = gHeapEnd;
59         tHeapFoot       *foot;
60         
61         // Bounds Check
62         if( (tVAddr)gHeapEnd == MM_KHEAP_MAX )
63                 return NULL;
64         
65         // Bounds Check
66         if( (tVAddr)gHeapEnd + ((Bytes+0xFFF)&~0xFFF) > MM_KHEAP_MAX ) {
67                 Bytes = MM_KHEAP_MAX - (tVAddr)gHeapEnd;
68                 return NULL;
69         }
70         
71         // Heap expands in pages
72         for( i = 0; i < (Bytes+0xFFF) >> 12; i ++ )
73         {
74                 if( !MM_Allocate( (tVAddr)gHeapEnd+(i<<12) ) )
75                 {
76                         Warning("OOM - Heap_Extend");
77                         return NULL;
78                 }
79         }
80         
81         // Increas heap end
82         gHeapEnd = (Uint8*)gHeapEnd + (i << 12);
83         
84         // Create Block
85         head->Size = (Bytes+0xFFF)&~0xFFF;
86         head->Magic = MAGIC_FREE;
87         foot = (void*)( (Uint)gHeapEnd - sizeof(tHeapFoot) );
88         foot->Head = head;
89         foot->Magic = MAGIC_FOOT;
90         
91         return Heap_Merge(head);        // Merge with previous block
92 }
93
94 /**
95  * \fn void *Heap_Merge(tHeapHead *Head)
96  * \brief Merges two ajacent heap blocks
97  */
98 void *Heap_Merge(tHeapHead *Head)
99 {
100         tHeapFoot       *foot;
101         tHeapFoot       *thisFoot;
102         tHeapHead       *head;
103         
104         //Log("Heap_Merge: (Head=%p)", Head);
105         
106         thisFoot = (void*)( (Uint)Head + Head->Size - sizeof(tHeapFoot) );
107         if((Uint)thisFoot > (Uint)gHeapEnd)     return NULL;
108         
109         // Merge Left (Down)
110         foot = (void*)( (Uint)Head - sizeof(tHeapFoot) );
111         if( ((Uint)foot < (Uint)gHeapEnd && (Uint)foot > (Uint)gHeapStart)
112         && foot->Head->Magic == MAGIC_FREE) {
113                 foot->Head->Size += Head->Size; // Increase size
114                 thisFoot->Head = foot->Head;    // Change backlink
115                 Head->Magic = 0;        // Clear old head
116                 Head->Size = 0;
117                 Head = foot->Head;      // Save new head address
118                 foot->Head = NULL;      // Clear central footer
119                 foot->Magic = 0;
120         }
121         
122         // Merge Right (Upwards)
123         head = (void*)( (Uint)Head + Head->Size );
124         if((Uint)head < (Uint)gHeapEnd && head->Magic == MAGIC_FREE)
125         {
126                 Head->Size += head->Size;
127                 foot = (void*)( (Uint)Head + Head->Size - sizeof(tHeapFoot) );
128                 foot->Head = Head;      // Update Backlink
129                 thisFoot->Head = NULL;  // Clear old footer
130                 thisFoot->Magic = 0;
131                 head->Size = 0;         // Clear old header
132                 head->Magic = 0;
133         }
134         
135         // Return new address
136         return Head;
137 }
138
139 /**
140  * \brief Allocate memory from the heap
141  * \param File  Allocating source file
142  * \param Line  Source line
143  * \param Bytes Size of region to allocate
144  */
145 void *Heap_Allocate(const char *File, int Line, size_t __Bytes)
146 {
147         tHeapHead       *head, *newhead;
148         tHeapFoot       *foot, *newfoot;
149         tHeapHead       *best = NULL;
150         Uint    bestSize = 0;   // Speed hack
151         size_t  Bytes;
152
153         if( __Bytes == 0 ) {
154                 //return NULL;  // TODO: Return a known un-mapped range.
155                 return INVLPTR;
156         }
157         
158         // Get required size
159         #if POW2_SIZES
160         Bytes = __Bytes + sizeof(tHeapHead) + sizeof(tHeapFoot);
161         Bytes = 1UUL << LOG2(__Bytes);
162         #else
163         Bytes = (__Bytes + sizeof(tHeapHead) + sizeof(tHeapFoot) + MIN_SIZE-1) & ~(MIN_SIZE-1);
164         #endif
165         
166         // Lock Heap
167         Mutex_Acquire(&glHeap);
168         
169         // Traverse Heap
170         for( head = gHeapStart;
171                 (Uint)head < (Uint)gHeapEnd;
172                 head = (void*)((Uint)head + head->Size)
173                 )
174         {
175                 // Alignment Check
176                 #if POW2_SIZES
177                 if( head->Size != 1UUL << LOG2(head->Size) ) {
178                 #else
179                 if( head->Size & (MIN_SIZE-1) ) {
180                 #endif
181                         Mutex_Release(&glHeap); // Release spinlock
182                         #if WARNINGS
183                         Log_Warning("Heap", "Size of heap address %p is invalid not aligned (0x%x)", head, head->Size);
184                         Heap_Dump();
185                         #endif
186                         return NULL;
187                 }
188                 
189                 // Check if allocated
190                 if(head->Magic == MAGIC_USED)   continue;
191                 // Error check
192                 if(head->Magic != MAGIC_FREE)   {
193                         Mutex_Release(&glHeap); // Release spinlock
194                         #if WARNINGS
195                         Log_Warning("Heap", "Magic of heap address %p is invalid (0x%x)", head, head->Magic);
196                         Heap_Dump();
197                         #endif
198                         return NULL;
199                 }
200                 
201                 // Size check
202                 if(head->Size < Bytes)  continue;
203                 
204                 // Perfect fit
205                 if(head->Size == Bytes) {
206                         head->Magic = MAGIC_USED;
207                         head->File = File;
208                         head->Line = Line;
209                         Mutex_Release(&glHeap); // Release spinlock
210                         #if DEBUG_TRACE
211                         Log("[Heap   ] Malloc'd %p (%i bytes), returning to %p", head->Data, head->Size,  __builtin_return_address(0));
212                         #endif
213                         return head->Data;
214                 }
215                 
216                 // Break out of loop
217                 #if FIRST_FIT
218                 best = head;
219                 bestSize = head->Size;
220                 break;
221                 #else
222                 // or check if the block is the best size
223                 if(bestSize > head->Size) {
224                         best = head;
225                         bestSize = head->Size;
226                 }
227                 #endif
228         }
229         
230         // If no block large enough is found, create one
231         if(!best)
232         {
233                 best = Heap_Extend( Bytes );
234                 // Check for errors
235                 if(!best) {
236                         Mutex_Release(&glHeap); // Release spinlock
237                         return NULL;
238                 }
239                 // Check size
240                 if(best->Size == Bytes) {
241                         best->Magic = MAGIC_USED;       // Mark block as used
242                         best->File = File;
243                         best->Line = Line;
244                         Mutex_Release(&glHeap); // Release spinlock
245                         #if DEBUG_TRACE
246                         Log("[Heap   ] Malloc'd %p (%i bytes), returning to %p", best->Data, best->Size, __builtin_return_address(0));
247                         #endif
248                         return best->Data;
249                 }
250         }
251         
252         // Split Block
253         newhead = (void*)( (Uint)best + Bytes );
254         newfoot = (void*)( (Uint)best + Bytes - sizeof(tHeapFoot) );
255         foot = (void*)( (Uint)best + best->Size - sizeof(tHeapFoot) );
256         
257         newfoot->Head = best;   // Create new footer
258         newfoot->Magic = MAGIC_FOOT;
259         newhead->Size = best->Size - Bytes;     // Create new header
260         newhead->Magic = MAGIC_FREE;
261         foot->Head = newhead;   // Update backlink in old footer
262         best->Size = Bytes;             // Update size in old header
263         best->ValidSize = __Bytes;
264         best->Magic = MAGIC_USED;       // Mark block as used
265         best->File = File;
266         best->Line = Line;
267         
268         Mutex_Release(&glHeap); // Release spinlock
269         #if DEBUG_TRACE
270         Log_Debug("Heap", "newhead(%p)->Size = 0x%x", newhead, newhead->Size);
271         Log_Debug("Heap", "Malloc'd %p (0x%x bytes), returning to %s:%i",
272                 best->Data, best->Size, File, Line);
273         #endif
274         return best->Data;
275 }
276
277 /**
278  * \fn void Heap_Deallocate(void *Ptr)
279  * \brief Free an allocated memory block
280  */
281 void Heap_Deallocate(void *Ptr)
282 {
283         tHeapHead       *head;
284         tHeapFoot       *foot;
285         
286         #if DEBUG_TRACE
287         Log_Log("Heap", "free: Ptr = %p", Ptr);
288         Log_Log("Heap", "free: Returns to %p", __builtin_return_address(0));
289         #endif
290         
291         // INVLPTR is returned from Heap_Allocate when the allocation
292         // size is zero.
293         if( Ptr == INVLPTR )    return;
294         
295         // Alignment Check
296         if( (Uint)Ptr & (sizeof(Uint)-1) ) {
297                 Log_Warning("Heap", "free - Passed a non-aligned address (%p)", Ptr);
298                 return;
299         }
300         
301         // Sanity check
302         if((Uint)Ptr < (Uint)gHeapStart || (Uint)Ptr > (Uint)gHeapEnd)
303         {
304                 Log_Warning("Heap", "free - Passed a non-heap address (%p < %p < %p)\n",
305                         gHeapStart, Ptr, gHeapEnd);
306                 return;
307         }
308         
309         // Check memory block - Header
310         head = (void*)( (Uint)Ptr - sizeof(tHeapHead) );
311         if(head->Magic == MAGIC_FREE) {
312                 Log_Warning("Heap", "free - Passed a freed block (%p) by %p", head, __builtin_return_address(0));
313                 return;
314         }
315         if(head->Magic != MAGIC_USED) {
316                 Log_Warning("Heap", "free - Magic value is invalid (%p, 0x%x)", head, head->Magic);
317                 Log_Notice("Heap", "Allocated %s:%i", head->File, head->Line);
318                 return;
319         }
320         
321         // Check memory block - Footer
322         foot = (void*)( (Uint)head + head->Size - sizeof(tHeapFoot) );
323         if(foot->Head != head) {
324                 Log_Warning("Heap", "free - Footer backlink is incorrect (%p, 0x%x)", head, foot->Head);
325                 Log_Notice("Heap", "Allocated %s:%i", head->File, head->Line);
326                 return;
327         }
328         if(foot->Magic != MAGIC_FOOT) {
329                 Log_Warning("Heap", "free - Footer magic is invalid (%p, %p = 0x%x)", head, &foot->Magic, foot->Magic);
330                 Log_Notice("Heap", "Allocated %s:%i", head->File, head->Line);
331                 return;
332         }
333         
334         // Lock
335         Mutex_Acquire( &glHeap );
336         
337         // Mark as free
338         head->Magic = MAGIC_FREE;
339         //head->File = NULL;
340         //head->Line = 0;
341         head->ValidSize = 0;
342         // Merge blocks
343         Heap_Merge( head );
344         
345         // Release
346         Mutex_Release( &glHeap );
347 }
348
349 /**
350  * \brief Increase/Decrease the size of an allocation
351  * \param File  Calling File
352  * \param Line  Calling Line
353  * \param __ptr Old memory
354  * \param __size        New Size
355  */
356 void *Heap_Reallocate(const char *File, int Line, void *__ptr, size_t __size)
357 {
358         tHeapHead       *head = (void*)( (Uint)__ptr-sizeof(tHeapHead) );
359         tHeapHead       *nextHead;
360         tHeapFoot       *foot;
361         Uint    newSize = (__size + sizeof(tHeapFoot)+sizeof(tHeapHead)+MIN_SIZE-1)&~(MIN_SIZE-1);
362         
363         // Check for reallocating NULL
364         if(__ptr == NULL)       return Heap_Allocate(File, Line, __size);
365         
366         // Check if resize is needed
367         if(newSize <= head->Size)       return __ptr;
368         
369         // Check if next block is free
370         nextHead = (void*)( (Uint)head + head->Size );
371         
372         // Extend into next block
373         if(nextHead->Magic == MAGIC_FREE && nextHead->Size+head->Size >= newSize)
374         {
375                 Uint    size = nextHead->Size + head->Size;
376                 foot = (void*)( (Uint)nextHead + nextHead->Size - sizeof(tHeapFoot) );
377                 // Exact Fit
378                 if(size == newSize) {
379                         head->Size = newSize;
380                         head->ValidSize = __size;
381                         head->File = File;
382                         head->Line = Line;
383                         foot->Head = head;
384                         nextHead->Magic = 0;
385                         nextHead->Size = 0;
386                         return __ptr;
387                 }
388                 // Create a new heap block
389                 nextHead = (void*)( (Uint)head + newSize );
390                 nextHead->Size = size - newSize;
391                 nextHead->Magic = MAGIC_FREE;
392                 foot->Head = nextHead;  // Edit 2nd footer
393                 head->Size = newSize;   // Edit first header
394                 head->File = File;
395                 head->Line = Line;
396                 head->ValidSize = __size;
397                 // Create new footer
398                 foot = (void*)( (Uint)head + newSize - sizeof(tHeapFoot) );
399                 foot->Head = head;
400                 foot->Magic = MAGIC_FOOT;
401                 return __ptr;
402         }
403         
404         // Extend downwards?
405         foot = (void*)( (Uint)head - sizeof(tHeapFoot) );
406         nextHead = foot->Head;
407         if(nextHead->Magic == MAGIC_FREE && nextHead->Size+head->Size >= newSize)
408         {
409                 Uint    size = nextHead->Size + head->Size;
410                 // Inexact fit, split things up
411                 if(size > newSize)
412                 {
413                         // TODO
414                         Warning("[Heap   ] TODO: Space efficient realloc when new size is smaller");
415                 }
416                 
417                 // Exact fit
418                 if(size >= newSize)
419                 {
420                         Uint    oldDataSize;
421                         // Set 1st (new/lower) header
422                         nextHead->Magic = MAGIC_USED;
423                         nextHead->Size = newSize;
424                         nextHead->File = File;
425                         nextHead->Line = Line;
426                         nextHead->ValidSize = __size;
427                         // Get 2nd (old) footer
428                         foot = (void*)( (Uint)nextHead + newSize );
429                         foot->Head = nextHead;
430                         // Save old data size
431                         oldDataSize = head->Size - sizeof(tHeapFoot) - sizeof(tHeapHead);
432                         // Clear old header
433                         head->Size = 0;
434                         head->Magic = 0;
435                         // Copy data
436                         memcpy(nextHead->Data, __ptr, oldDataSize);
437                         // Return
438                         return nextHead->Data;
439                 }
440                 // On to the expensive then
441         }
442         
443         // Well, darn
444         nextHead = Heap_Allocate( File, Line, __size );
445         nextHead -= 1;
446         nextHead->File = File;
447         nextHead->Line = Line;
448         nextHead->ValidSize = __size;
449         
450         memcpy(
451                 nextHead->Data,
452                 __ptr,
453                 head->Size - sizeof(tHeapFoot) - sizeof(tHeapHead)
454                 );
455         
456         free(__ptr);
457         
458         return nextHead->Data;
459 }
460
461 /**
462  * \fn void *Heap_AllocateZero(const char *File, int Line, size_t Bytes)
463  * \brief Allocate and Zero a buffer in memory
464  * \param File  Allocating file
465  * \param Line  Line of allocation
466  * \param Bytes Size of the allocation
467  */
468 void *Heap_AllocateZero(const char *File, int Line, size_t Bytes)
469 {
470         void    *ret = Heap_Allocate(File, Line, Bytes);
471         if(ret == NULL) return NULL;
472         
473         memset( ret, 0, Bytes );
474         
475         return ret;
476 }
477
478 /**
479  * \fn int Heap_IsHeapAddr(void *Ptr)
480  * \brief Checks if an address is a heap pointer
481  */
482 int Heap_IsHeapAddr(void *Ptr)
483 {
484         tHeapHead       *head;
485         if((Uint)Ptr < (Uint)gHeapStart)        return 0;
486         if((Uint)Ptr > (Uint)gHeapEnd)  return 0;
487         if((Uint)Ptr & (sizeof(Uint)-1))        return 0;
488         
489         head = (void*)( (Uint)Ptr - sizeof(tHeapHead) );
490         if(head->Magic != MAGIC_USED && head->Magic != MAGIC_FREE)
491                 return 0;
492         
493         return 1;
494 }
495
496 /**
497  */
498 void Heap_Validate(void)
499 {
500         Heap_Dump();
501 }
502
503 #if WARNINGS
504 void Heap_Dump(void)
505 {
506         tHeapHead       *head, *badHead;
507         tHeapFoot       *foot = NULL;
508         
509         head = gHeapStart;
510         while( (Uint)head < (Uint)gHeapEnd )
511         {               
512                 foot = (void*)( (Uint)head + head->Size - sizeof(tHeapFoot) );
513                 #if VERBOSE_DUMP
514                 Log_Log("Heap", "%p (0x%llx): 0x%08lx (%i) %4C",
515                         head, MM_GetPhysAddr((Uint)head), head->Size, head->ValidSize, &head->Magic);
516                 Log_Log("Heap", "%p %4C", foot->Head, &foot->Magic);
517                 if(head->File) {
518                         Log_Log("Heap", "%sowned by %s:%i",
519                                 (head->Magic==MAGIC_FREE?"was ":""), head->File, head->Line);
520                 }
521                 #endif
522                 
523                 // Sanity Check Header
524                 if(head->Size == 0) {
525                         Log_Warning("Heap", "HALTED - Size is zero");
526                         break;
527                 }
528                 if(head->Size & (MIN_SIZE-1)) {
529                         Log_Warning("Heap", "HALTED - Size is malaligned");
530                         break;
531                 }
532                 if(head->Magic != MAGIC_FREE && head->Magic != MAGIC_USED) {
533                         Log_Warning("Heap", "HALTED - Head Magic is Bad");
534                         break;
535                 }
536                 
537                 // Check footer
538                 if(foot->Magic != MAGIC_FOOT) {
539                         Log_Warning("Heap", "HALTED - Foot Magic is Bad");
540                         break;
541                 }
542                 if(head != foot->Head) {
543                         Log_Warning("Heap", "HALTED - Footer backlink is invalid");
544                         break;
545                 }
546                 
547                 #if VERBOSE_DUMP
548                 Log_Log("Heap", "");
549                 #endif
550                 
551                 // All OK? Go to next
552                 head = foot->NextHead;
553         }
554         
555         // If the heap is valid, ok!
556         if( (tVAddr)head == (tVAddr)gHeapEnd )
557                 return ;
558         
559         // Check for a bad return
560         if( (tVAddr)head >= (tVAddr)gHeapEnd )
561                 return ;
562
563         #if !VERBOSE_DUMP
564         Log_Log("Heap", "%p (0x%llx): 0x%08lx (%i) %4C",
565                 head, MM_GetPhysAddr((Uint)head), head->Size, head->ValidSize, &head->Magic);
566         Log_Log("Heap", "%p %4C", foot->Head, &foot->Magic);
567         if(head->File) {
568                 Log_Log("Heap", "%sowned by %s:%i",
569                         (head->Magic==MAGIC_FREE?"was ":""), head->File, head->Line);
570         }
571         Log_Log("Heap", "");
572         #endif
573         
574         
575         badHead = head;
576         
577         // Work backwards
578         foot = (void*)( (tVAddr)gHeapEnd - sizeof(tHeapFoot) );
579         Log_Log("Heap", "==== Going Backwards ==== (from %p)", foot);
580         head = foot->Head;
581         while( (tVAddr)head >= (tVAddr)badHead )
582         {
583                 Log_Log("Heap", "%p (0x%llx): 0x%08lx %i %4C",
584                         head, MM_GetPhysAddr((Uint)head), head->Size, head->ValidSize, &head->Magic);
585                 Log_Log("Heap", "%p %4C", foot->Head, &foot->Magic);
586                 if(head->File)
587                         Log_Log("Heap", "%sowned by %s:%i",
588                                 (head->Magic!=MAGIC_USED?"was ":""),
589                                 head->File, head->Line);
590                 Log_Log("Heap", "");
591                 
592                 // Sanity Check Header
593                 if(head->Size == 0) {
594                         Log_Warning("Heap", "HALTED - Size is zero");
595                         break;
596                 }
597                 if(head->Size & (MIN_SIZE-1)) {
598                         Log_Warning("Heap", " - Size is malaligned (&0x%x)", ~(MIN_SIZE-1));
599                         break ;
600                 }
601                 if(head->Magic != MAGIC_FREE && head->Magic != MAGIC_USED) {
602                         Log_Warning("Heap", "HALTED - Head Magic is Bad");
603                         break;
604                 }
605                 
606                 // Check footer
607                 if(foot->Magic != MAGIC_FOOT) {
608                         Log_Warning("Heap", "HALTED - Foot Magic is Bad");
609                         break;
610                 }
611                 if(head != foot->Head) {
612                         Log_Warning("Heap", "HALTED - Footer backlink is invalid");
613                         break;
614                 }
615                 
616                 if(head == badHead)     break;
617                 
618                 foot = (void*)( (tVAddr)head - sizeof(tHeapFoot) );
619                 head = foot->Head;
620                 Log_Debug("Heap", "head=%p", head);
621         }
622         
623         Panic("Heap_Dump - Heap is corrupted, kernel panic!");
624 }
625 #endif
626
627 #if 1
628 void Heap_Stats(void)
629 {
630         tHeapHead       *head;
631          int    nBlocks = 0;
632          int    nFree = 0;
633          int    totalBytes = 0;
634          int    freeBytes = 0;
635          int    maxAlloc=0, minAlloc=-1;
636          int    avgAlloc, frag, overhead;
637         
638         for(head = gHeapStart;
639                 (Uint)head < (Uint)gHeapEnd;
640                 head = (void*)( (Uint)head + head->Size )
641                 )
642         {       
643                 nBlocks ++;
644                 totalBytes += head->Size;
645                 if( head->Magic == MAGIC_FREE )
646                 {
647                         nFree ++;
648                         freeBytes += head->Size;
649                 }
650                 else if( head->Magic == MAGIC_USED) {
651                         if(maxAlloc < head->Size)       maxAlloc = head->Size;
652                         if(minAlloc == -1 || minAlloc > head->Size)
653                                 minAlloc = head->Size;
654                 }
655                 else {
656                         Log_Warning("Heap", "Magic on %p invalid, skipping remainder of heap", head);
657                         break;
658                 }
659                 
660                 // Print the block info?
661                 #if 1
662                 Log_Debug("Heap", "%p - 0x%x (%i) Owned by %s:%i",
663                         head, head->Size, head->ValidSize, head->File, head->Line);
664                 #endif
665         }
666
667         Log_Log("Heap", "%i blocks (0x%x bytes)", nBlocks, totalBytes);
668         Log_Log("Heap", "%i free blocks (0x%x bytes)", nFree, freeBytes);
669         frag = (nFree-1)*10000/nBlocks;
670         Log_Log("Heap", "%i.%02i%% Heap Fragmentation", frag/100, frag%100);
671         avgAlloc = (totalBytes-freeBytes)/(nBlocks-nFree);
672         overhead = (sizeof(tHeapFoot)+sizeof(tHeapHead))*10000/avgAlloc;
673         Log_Log("Heap", "Average allocation: %i bytes, Average Overhead: %i.%02i%%",
674                 avgAlloc, overhead/100, overhead%100
675                 );
676         Log_Log("Heap", "Smallest Block: %i bytes, Largest: %i bytes", 
677                 minAlloc, maxAlloc);
678         
679         // Scan and get distribution
680         #if 1
681         {
682                 struct {
683                         Uint    Size;
684                         Uint    Count;
685                 }       sizeCounts[nBlocks];
686                  int    i;
687                 
688                 memset(sizeCounts, 0, nBlocks*sizeof(sizeCounts[0]));
689                 
690                 for(head = gHeapStart;
691                         (Uint)head < (Uint)gHeapEnd;
692                         head = (void*)( (Uint)head + head->Size )
693                         )
694                 {
695                         for( i = 0; i < nBlocks; i ++ ) {
696                                 if( sizeCounts[i].Size == 0 )
697                                         break;
698                                 if( sizeCounts[i].Size == head->Size )
699                                         break;
700                         }
701                         // Should never reach this part (in a non-concurrent case)
702                         if( i == nBlocks )      continue;
703                         sizeCounts[i].Size = head->Size;
704                         sizeCounts[i].Count ++;
705                         #if 1
706                         //Log("Heap_Stats: %i %p - 0x%x bytes (%s) (%i)", nBlocks, head,
707                         //      head->Size, (head->Magic==MAGIC_FREE?"FREE":"used"), i
708                         //      );
709                         //Log("Heap_Stats: sizeCounts[%i] = {Size:0x%x, Count: %i}", i,
710                         //      sizeCounts[i].Size, sizeCounts[i].Count);
711                         #endif
712                 }
713                 
714                 for( i = 0; i < nBlocks && sizeCounts[i].Count; i ++ )
715                 {
716                         Log("Heap_Stats: 0x%x - %i blocks",
717                                 sizeCounts[i].Size, sizeCounts[i].Count
718                                 );
719                 }
720         }
721         #endif
722 }
723 #endif
724
725 // === EXPORTS ===
726 EXPORT(Heap_Allocate);
727 EXPORT(Heap_AllocateZero);
728 EXPORT(Heap_Reallocate);
729 EXPORT(Heap_Deallocate);
730 EXPORT(Heap_IsHeapAddr);

UCC git Repository :: git.ucc.asn.au