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

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