3 MemManager.c Memory Manager
5 This module provides memory management functions.
7 Copyright (C) 2004, Wong Chi Kwong.
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29 #include <mm_malloc.h>
31 #include "MiscUtilities.h"
32 #include "MemManager.h"
36 void *MMMalloc(const unsigned int memSize
) {
40 address
= MEMALIGN(memSize
, MAX_ALIGN
);
41 if (address
== NULL
) {
42 fprintf(stderr
, "MMMalloc() : cannot allocate memory!\n");
49 void MMFree(void *address
) {
55 void MMMasterInitialize(const unsigned int maxNumberOfPools
, const unsigned int maxNumberOfBulks
,
56 const int traceUnitByteAllocation
, FILE* unitByteTraceFile
) {
60 mmMaster
.maxTotalByteAllocated
= 0;
61 mmMaster
.maxTotalByteDispatched
= 0;
62 mmMaster
.currentUnitByteAllocated
= 0;
63 mmMaster
.maxUnitByteAllocated
= 0;
65 mmMaster
.maxNumberOfBulks
= maxNumberOfBulks
;
66 mmMaster
.maxNumberOfPools
= maxNumberOfPools
;
67 if (maxNumberOfBulks
> 0) {
68 mmMaster
.mmBulk
= MEMALIGN(sizeof(MMBulk
*) * maxNumberOfBulks
, MAX_ALIGN
);
69 for (i
=0; i
<maxNumberOfBulks
; i
++) {
70 mmMaster
.mmBulk
[i
] = NULL
;
73 mmMaster
.mmBulk
= NULL
;
75 if (maxNumberOfPools
> 0) {
76 mmMaster
.mmPool
= MEMALIGN(sizeof(MMPool
*) * maxNumberOfPools
, MAX_ALIGN
);
77 for (i
=0; i
<maxNumberOfPools
; i
++) {
78 mmMaster
.mmPool
[i
] = NULL
;
81 mmMaster
.mmPool
= NULL
;
84 mmMaster
.traceUnitByteAllocation
= traceUnitByteAllocation
;
85 mmMaster
.unitByteTraceFile
= unitByteTraceFile
;
89 void MMMasterFreeAll() {
93 for (i
=0; i
< mmMaster
.maxNumberOfBulks
; i
++) {
94 if (mmMaster
.mmBulk
[i
] != NULL
) {
95 if (MMBulkIsActive(mmMaster
.mmBulk
[i
])) {
96 MMBulkFree(mmMaster
.mmBulk
[i
]);
98 if (MMBulkFindPoolUsed(mmMaster
.mmBulk
[i
]) == NULL
) {
99 MMUnitFree(mmMaster
.mmBulk
[i
], sizeof(MMBulk
));
101 mmMaster
.mmBulk
[i
] = NULL
;
104 FREEALIGN(mmMaster
.mmBulk
);
106 for (i
=0; i
< mmMaster
.maxNumberOfPools
; i
++) {
107 if (mmMaster
.mmPool
[i
] != NULL
) {
108 if (MMPoolIsActive(mmMaster
.mmPool
[i
])) {
109 MMPoolFree(mmMaster
.mmPool
[i
]);
111 FREEALIGN(mmMaster
.mmPool
[i
]);
112 mmMaster
.mmPool
[i
] = NULL
;
115 FREEALIGN(mmMaster
.mmPool
);
119 unsigned int MMMasterCurrentTotalByteAllocated() {
122 unsigned int currentTotalByteAllocated
;
124 // unit memory allocated
125 currentTotalByteAllocated
= mmMaster
.currentUnitByteAllocated
;
127 // pool and temp memory allocated
128 for (i
=0; i
< mmMaster
.maxNumberOfPools
; i
++) {
129 if (mmMaster
.mmPool
[i
] != NULL
&& MMPoolIsActive(mmMaster
.mmPool
[i
])) {
130 currentTotalByteAllocated
+= MMPoolCurrentTotalByteAllocated(mmMaster
.mmPool
[i
]);
134 // bulk memory allocated
135 for (i
=0; i
< mmMaster
.maxNumberOfBulks
; i
++) {
136 if (mmMaster
.mmBulk
[i
] != NULL
&& MMBulkIsActive(mmMaster
.mmBulk
[i
])) {
137 currentTotalByteAllocated
+= MMBulkByteAllocated(mmMaster
.mmBulk
[i
]);
141 return currentTotalByteAllocated
;
145 unsigned int MMMasterCurrentTotalByteDispatched() {
148 unsigned int currentTotalByteDispatched
;
150 // unit memory dispatched
151 currentTotalByteDispatched
= mmMaster
.currentUnitByteAllocated
;
153 // pool and temp memory dispatched
154 for (i
=0; i
< mmMaster
.maxNumberOfPools
; i
++) {
155 if (mmMaster
.mmPool
[i
] != NULL
&& MMPoolIsActive(mmMaster
.mmPool
[i
])) {
156 currentTotalByteDispatched
+= MMPoolCurrentTotalByteDispatched(mmMaster
.mmPool
[i
]);
160 // bulk memory dispatched
161 for (i
=0; i
< mmMaster
.maxNumberOfBulks
; i
++) {
162 if (mmMaster
.mmBulk
[i
] != NULL
&& MMBulkIsActive(mmMaster
.mmBulk
[i
])) {
163 currentTotalByteDispatched
+= MMBulkByteDispatched(mmMaster
.mmBulk
[i
]);
167 return currentTotalByteDispatched
;
171 unsigned int MMMasterMaxTotalByteAllocated() {
173 unsigned int currentTotalByteAllocated
;
175 currentTotalByteAllocated
= MMMasterCurrentTotalByteAllocated();
177 if (currentTotalByteAllocated
> mmMaster
.maxTotalByteAllocated
) {
178 return currentTotalByteAllocated
;
180 return mmMaster
.maxTotalByteAllocated
;
185 unsigned int MMMasterMaxTotalByteDispatched() {
187 unsigned int currentTotalByteDispatched
;
189 currentTotalByteDispatched
= MMMasterCurrentTotalByteDispatched();
191 if (currentTotalByteDispatched
> mmMaster
.maxTotalByteDispatched
) {
192 return currentTotalByteDispatched
;
194 return mmMaster
.maxTotalByteDispatched
;
199 void MMMasterSetMaxTotalByteAllocated() {
201 unsigned int currentTotalByteAllocated
;
203 currentTotalByteAllocated
= MMMasterCurrentTotalByteAllocated();
205 if (currentTotalByteAllocated
> mmMaster
.maxTotalByteAllocated
) {
206 mmMaster
.maxTotalByteAllocated
= currentTotalByteAllocated
;
211 void MMMasterSetMaxTotalByteDispatched() {
213 unsigned int currentTotalByteDispatched
;
215 currentTotalByteDispatched
= MMMasterCurrentTotalByteDispatched();
217 if (currentTotalByteDispatched
> mmMaster
.maxTotalByteDispatched
) {
218 mmMaster
.maxTotalByteDispatched
= currentTotalByteDispatched
;
223 void MMMasterPrintReport(FILE *output
, const unsigned int withUnitDetails
, const unsigned int withPoolDetails
, const unsigned int withBulkDetails
) {
227 fprintf(output
, "Maximum amount of memory allocated: %u\n", MMMasterMaxTotalByteAllocated());
228 fprintf(output
, "Maximum amount of memory dispatched: %u\n", MMMasterMaxTotalByteDispatched());
230 if (withUnitDetails
) {
231 fprintf(output
, "\n");
232 MMUnitPrintReport(output
);
235 if (withPoolDetails
) {
236 for (i
=0; i
<mmMaster
.maxNumberOfPools
; i
++) {
237 if (mmMaster
.mmPool
[i
] != NULL
) {
238 fprintf(output
, "\nPool number %u\n", i
);
239 MMPoolPrintReport(mmMaster
.mmPool
[i
], output
);
244 if (withBulkDetails
) {
245 for (i
=0; i
<mmMaster
.maxNumberOfBulks
; i
++) {
246 if (mmMaster
.mmBulk
[i
] != NULL
) {
247 fprintf(output
, "\nBulk number %u\n", i
);
248 MMBulkPrintReport(mmMaster
.mmBulk
[i
], output
);
255 void *MMUnitAllocate(const unsigned int memSize
) {
261 fprintf(stderr
, "MMUnitAllocate() : memSize = 0!\n");
266 temp
= MEMALIGN(memSize
, MAX_ALIGN
);
268 fprintf(stderr
, "MMUnitAllocate() : cannot allocate memory!\n");
272 mmMaster
.currentUnitByteAllocated
+= memSize
;
273 if (mmMaster
.traceUnitByteAllocation
) {
274 fprintf(mmMaster
.unitByteTraceFile
, "MMUnitAllocate : %u\n", memSize
);
281 void *MMUnitReallocate(void *address
, const unsigned int newMemSize
, const unsigned int oldMemSize
) {
286 if (newMemSize
== 0) {
287 fprintf(stderr
, "MMUnitReallocate() : newMemSize = 0!\n");
290 if (oldMemSize
== 0) {
291 fprintf(stderr
, "MMUnitReallocate() : oldMemSize = 0!\n");
296 if (mmMaster
.traceUnitByteAllocation
) {
297 fprintf(mmMaster
.unitByteTraceFile
, "MMUnitReallocate\n");
300 temp
= MMUnitAllocate(newMemSize
);
302 fprintf(stderr
, "MMUnitReallocate() : cannot allocate memory!\n");
305 memcpy(temp
, address
, min(newMemSize
, oldMemSize
));
307 MMUnitFree(address
, oldMemSize
);
313 void MMUnitFree(void *address
, const unsigned int memSize
) {
316 if (address
== NULL
) {
317 fprintf(stderr
, "MMUnitFree() : address = NULL!\n");
320 if (mmMaster
.currentUnitByteAllocated
< memSize
) {
321 fprintf(stderr
, "MMUnitFree() : currentUnitByteAllocated < memSize!\n");
328 #ifdef RECORD_GRAND_TOTAL
329 MMMasterSetMaxTotalByteAllocated();
330 MMMasterSetMaxTotalByteDispatched();
333 if (mmMaster
.currentUnitByteAllocated
> mmMaster
.maxUnitByteAllocated
) {
334 mmMaster
.maxUnitByteAllocated
= mmMaster
.currentUnitByteAllocated
;
336 mmMaster
.currentUnitByteAllocated
-= memSize
;
337 if (mmMaster
.traceUnitByteAllocation
) {
338 fprintf(mmMaster
.unitByteTraceFile
, "MMUnitFree : %u\n", memSize
);
343 unsigned int MMUnitCurrentByteAllocated() {
345 return mmMaster
.currentUnitByteAllocated
;
349 unsigned int MMUnitMaxByteAllocated() {
351 if (mmMaster
.currentUnitByteAllocated
> mmMaster
.maxUnitByteAllocated
) {
352 return mmMaster
.currentUnitByteAllocated
;
354 return mmMaster
.maxUnitByteAllocated
;
359 void MMUnitPrintReport(FILE *output
) {
361 fprintf(output
, "Maximum amount of unit memory allocated: %u\n", MMUnitMaxByteAllocated());
362 fprintf(output
, "Amount of memory unit memory currently allocated: %u\n", MMUnitCurrentByteAllocated());
366 MMPool
*MMPoolCreate(const unsigned int poolSize
) {
372 if (poolSize
< sizeof(MMPool
)) {
373 fprintf(stderr
, "MMPoolCreate() : poolSize < MMPool!\n");
378 if (poolSize
/ MAX_ALIGN
* MAX_ALIGN
!= poolSize
) {
379 fprintf(stderr
, "MMPoolCreate() : poolSize must be multiple of MAX_ALIGN (%d)!\n", MAX_ALIGN
); // Otherwise temp memory is not properly aligned
383 mmPool
= MEMALIGN(poolSize
, MAX_ALIGN
);
384 if (mmPool
== NULL
) {
385 fprintf(stderr
, "MMPoolCreate() : cannot allocate memory!\n");
389 mmPool
->poolSize
= poolSize
;
390 mmPool
->poolByteDispatched
= sizeof(MMPool
);
391 mmPool
->poolByteSpillover
= 0;
392 mmPool
->firstSpillOverAddress
= NULL
;
393 mmPool
->currentTempByteDispatched
= 0;
394 mmPool
->currentTempByteSpillover
= 0;
395 mmPool
->maxTotalByteDispatched
= 0;
397 for (i
=0; i
<mmMaster
.maxNumberOfPools
; i
++) {
398 if (mmMaster
.mmPool
[i
] == NULL
) {
399 mmMaster
.mmPool
[i
] = mmPool
;
404 fprintf(stderr
, "MMPoolCreate() : number of pools > maxNumberOfPools!\n");
409 unsigned int MMPoolIsActive(const MMPool
*mmPool
) {
411 return ((mmPool
->firstSpillOverAddress
) != (void*)mmPool
);
414 void MMPoolSetInactive(MMPool
*mmPool
) {
416 if (mmPool
->firstSpillOverAddress
!= NULL
) {
417 fprintf(stderr
, "MMPoolSetInactive() : spillover memory not freed yet!\n");
421 mmPool
->firstSpillOverAddress
= (void*)mmPool
;
424 unsigned int MMPoolCurrentTotalByteAllocated(const MMPool
*mmPool
) {
426 return mmPool
->poolSize
+ mmPool
->poolByteSpillover
+ mmPool
->currentTempByteSpillover
;
430 unsigned int MMPoolCurrentTotalByteDispatched(const MMPool
*mmPool
) {
432 return mmPool
->poolByteDispatched
+ mmPool
->currentTempByteDispatched
;
436 unsigned int MMPoolMaxTotalByteDispatched(const MMPool
*mmPool
) {
438 unsigned int currentTotalByteDispatched
;
440 currentTotalByteDispatched
= MMPoolCurrentTotalByteDispatched(mmPool
);
442 if (currentTotalByteDispatched
> mmPool
->maxTotalByteDispatched
) {
443 return currentTotalByteDispatched
;
445 return mmPool
->maxTotalByteDispatched
;
450 unsigned int MMPoolByteAvailable(const MMPool
*mmPool
) {
452 if (mmPool
->poolSize
> mmPool
->poolByteDispatched
+ MAX_ALIGN
) {
453 return (mmPool
->poolSize
- mmPool
->poolByteDispatched
+ MAX_ALIGN
- 1) / MAX_ALIGN
* MAX_ALIGN
;
460 MMPool
*MMPoolFree(MMPool
*mmPool
) {
467 if (mmPool
== NULL
) {
468 fprintf(stderr
, "MMPoolFree(): mmPool = NULL!\n");
473 #ifdef RECORD_GRAND_TOTAL
474 MMMasterSetMaxTotalByteAllocated();
475 MMMasterSetMaxTotalByteDispatched();
478 dummyMMPool
= MEMALIGN(sizeof(MMPool
), MAX_ALIGN
);
479 if (dummyMMPool
== NULL
) {
480 fprintf(stderr
, "MMPoolFree() : cannot allocate memory!\n");
484 // Free spillover memory
485 temp1
= mmPool
->firstSpillOverAddress
;
486 while (temp1
!= NULL
) {
487 temp2
= *((void**)temp1
);
491 mmPool
->firstSpillOverAddress
= NULL
;
493 dummyMMPool
->poolByteDispatched
= mmPool
->poolByteDispatched
;
494 dummyMMPool
->poolByteSpillover
= mmPool
->poolByteSpillover
;
495 dummyMMPool
->currentTempByteDispatched
= mmPool
->currentTempByteDispatched
;
496 dummyMMPool
->currentTempByteSpillover
= mmPool
->currentTempByteSpillover
;
497 dummyMMPool
->firstSpillOverAddress
= mmPool
->firstSpillOverAddress
;
498 dummyMMPool
->maxTotalByteDispatched
= mmPool
->maxTotalByteDispatched
;
499 dummyMMPool
->poolSize
= mmPool
->poolSize
;
501 MMPoolSetInactive(dummyMMPool
);
503 // Update master directory
504 for (i
=0; i
<mmMaster
.maxNumberOfPools
; i
++) {
505 if (mmMaster
.mmPool
[i
] == mmPool
) {
506 mmMaster
.mmPool
[i
] = dummyMMPool
;
512 fprintf(stderr
, "MMPoolFree() : cannot locate pool in master!\n");
517 void MMPoolReset(MMPool
*mmPool
) {
522 if (mmPool
== NULL
) {
523 fprintf(stderr
, "MMPoolReset(): mmPool = NULL!\n");
528 #ifdef RECORD_GRAND_TOTAL
529 MMMasterSetMaxTotalByteAllocated();
530 MMMasterSetMaxTotalByteDispatched();
533 // Free spillover memory
534 temp1
= mmPool
->firstSpillOverAddress
;
535 while (temp1
!= NULL
) {
536 temp2
= *((void**)temp1
);
541 mmPool
->poolByteDispatched
= sizeof(MMPool
);
542 mmPool
->poolByteSpillover
= 0;
543 mmPool
->currentTempByteDispatched
= 0;
544 mmPool
->currentTempByteSpillover
= 0;
545 mmPool
->firstSpillOverAddress
= NULL
;
546 mmPool
->maxTotalByteDispatched
= 0;
550 void MMPoolDestory(MMPool
*mmPool
) {
556 if (mmPool
== NULL
) {
557 fprintf(stderr
, "MMPoolDestory(): mmPool = NULL!\n");
562 if (MMPoolIsActive(mmPool
)) {
563 temp
= MMPoolFree(mmPool
);
568 // Update master directory
569 for (i
=0; i
<mmMaster
.maxNumberOfPools
; i
++) {
570 if (mmMaster
.mmPool
[i
] == temp
) {
571 mmMaster
.mmPool
[i
] = NULL
;
578 fprintf(stderr
, "MMPoolDestory() : cannot locate pool in master!\n");
584 void *MMPoolDispatch(MMPool
*mmPool
, const unsigned int memSize
) {
587 unsigned int totalPoolMemoryUsed
, nextPoolMemoryOffset
;
588 unsigned int align
, skipForAlign
;
590 if (mmPool
== NULL
) {
591 return MMUnitAllocate(memSize
);
594 fprintf(stderr
, "MMPoolDispatch(): memSize = 0!\n");
598 totalPoolMemoryUsed
= mmPool
->poolByteDispatched
- mmPool
->poolByteSpillover
+
599 mmPool
->currentTempByteDispatched
- mmPool
->currentTempByteSpillover
;
600 nextPoolMemoryOffset
= mmPool
->poolByteDispatched
- mmPool
->poolByteSpillover
;
602 // Calculate the number of byte to skip in order to align the memory dispatched
603 align
= 1 << (BITS_IN_WORD
- leadingZero(memSize
- 1));
604 if (align
> MAX_ALIGN
) {
607 if (align
< MIN_ALIGN
) {
610 skipForAlign
= nextAlignedBoundary(nextPoolMemoryOffset
, align
) - nextPoolMemoryOffset
;
612 if (totalPoolMemoryUsed
+ memSize
+ skipForAlign
<= mmPool
->poolSize
) {
613 temp
= (void**)(((char*)mmPool
) + nextPoolMemoryOffset
+ skipForAlign
);
614 mmPool
->poolByteDispatched
+= memSize
+ skipForAlign
;
618 // Allocate for linked list pointer as well
619 temp
= MEMALIGN(memSize
+ MAX_ALIGN
, MAX_ALIGN
); // spillover memory is always aligned to MAX_ALIGN
621 fprintf(stderr
, "MMPoolDispatch(): cannot allocate memory!\n");
624 // Add spillover memory to linked list
625 *temp
= mmPool
->firstSpillOverAddress
;
626 mmPool
->firstSpillOverAddress
= temp
;
627 mmPool
->poolByteSpillover
+= memSize
+ MAX_ALIGN
;
628 mmPool
->poolByteDispatched
+= memSize
+ MAX_ALIGN
;
629 return (char*)temp
+ MAX_ALIGN
;
634 unsigned int MMPoolDispatchOffset(MMPool
*mmPool
, const unsigned int memSize
) {
636 unsigned int totalPoolMemoryUsed
, nextPoolMemoryOffset
;
637 unsigned int align
, skipForAlign
;
639 if (mmPool
== NULL
) {
640 fprintf(stderr
, "MMPoolDispatchOffset(): mmPool == NULL!\n");
644 fprintf(stderr
, "MMPoolDispatchOffset(): memSize = 0!\n");
648 totalPoolMemoryUsed
= mmPool
->poolByteDispatched
- mmPool
->poolByteSpillover
+
649 mmPool
->currentTempByteDispatched
- mmPool
->currentTempByteSpillover
;
650 nextPoolMemoryOffset
= mmPool
->poolByteDispatched
- mmPool
->poolByteSpillover
;
652 // Calculate the number of byte to skip in order to align the memory dispatched
653 align
= 1 << (BITS_IN_WORD
- leadingZero(memSize
- 1));
654 if (align
> MAX_ALIGN
) {
657 if (align
< MIN_ALIGN
) {
660 skipForAlign
= nextAlignedBoundary(nextPoolMemoryOffset
, align
) - nextPoolMemoryOffset
;
662 if (totalPoolMemoryUsed
+ memSize
+ skipForAlign
> mmPool
->poolSize
) {
663 fprintf(stderr
, "MMPoolDispatchOffset(): Not enough memory in memory pool!\n");
667 mmPool
->poolByteDispatched
+= memSize
+ skipForAlign
;
669 return nextPoolMemoryOffset
+ skipForAlign
;
673 void MMPoolReturn(MMPool
*mmPool
, void *address
, const unsigned int memSize
) {
675 if (mmPool
== NULL
) {
676 MMUnitFree(address
, memSize
);
681 void MMPoolPrintReport(MMPool
*mmPool
, FILE *output
) {
683 fprintf(output
, "Pool Size : %u\n", mmPool
->poolSize
);
684 fprintf(output
, " Dispatched : %u\n", mmPool
->poolByteDispatched
);
685 fprintf(output
, " - Spillover : %u\n", mmPool
->poolByteSpillover
);
686 fprintf(output
, "Maximum amount of memory dispatched including temp memory : %u\n",
687 MMPoolMaxTotalByteDispatched(mmPool
));
691 void *MMTempDispatch(MMPool
*mmPool
, const unsigned int memSize
) {
694 unsigned int totalPoolMemoryUsed
, nextTempMemoryOffset
;
695 unsigned int alignedMemSize
;
696 void **pointerToLastSpilloverAddress
;
698 if (mmPool
== NULL
) {
699 return MMUnitAllocate(memSize
);
702 fprintf(stderr
, "MMTempDispatch(): memSize = 0!\n");
706 alignedMemSize
= nextAlignedBoundary(memSize
, MAX_ALIGN
); // temp memory is always aligned to MAX_ALIGN
708 totalPoolMemoryUsed
= mmPool
->poolByteDispatched
- mmPool
->poolByteSpillover
+
709 mmPool
->currentTempByteDispatched
- mmPool
->currentTempByteSpillover
;
710 nextTempMemoryOffset
= mmPool
->currentTempByteDispatched
- mmPool
->currentTempByteSpillover
;
712 if (totalPoolMemoryUsed
+ alignedMemSize
<= mmPool
->poolSize
) {
713 temp
= (void**)(((char*)mmPool
) + mmPool
->poolSize
- nextTempMemoryOffset
- alignedMemSize
);
714 mmPool
->currentTempByteDispatched
+= alignedMemSize
;
718 // Locate the last spillover memory
719 pointerToLastSpilloverAddress
= &(mmPool
->firstSpillOverAddress
);
720 temp
= (void**)(*pointerToLastSpilloverAddress
);
721 while (temp
!= NULL
) {
722 pointerToLastSpilloverAddress
= temp
;
723 temp
= (void**)*pointerToLastSpilloverAddress
;
725 // Allocate for linked list pointer as well
726 temp
= MEMALIGN(memSize
+ MAX_ALIGN
, MAX_ALIGN
);
728 fprintf(stderr
, "MMTempDispatch(): cannot allocate memory!\n");
731 *pointerToLastSpilloverAddress
= temp
;
733 mmPool
->currentTempByteDispatched
+= memSize
+ MAX_ALIGN
;
734 mmPool
->currentTempByteSpillover
+= memSize
+ MAX_ALIGN
;
735 return (char*)temp
+ MAX_ALIGN
;
740 void MMTempReturn(MMPool
*mmPool
, void *address
, const unsigned int memSize
) {
743 unsigned int alignedMemSize
;
744 void **pointerToLastButOneSpillover
;
745 void *spilloverPointerAddress
;
747 if (mmPool
== NULL
) {
748 MMUnitFree(address
, memSize
);
751 alignedMemSize
= nextAlignedBoundary(memSize
, MAX_ALIGN
);
753 if (address
>= (void*)mmPool
&& address
<= (void*)((char*)mmPool
+ mmPool
->poolSize
)) {
754 // No need to record the global level max memory dispatched/allocated
755 // because memory pool is allocated as a whole and fluctuation across pools should not be counted
756 if (mmPool
->poolByteDispatched
+ mmPool
->currentTempByteDispatched
> mmPool
->maxTotalByteDispatched
) {
757 mmPool
->maxTotalByteDispatched
= mmPool
->poolByteDispatched
+ mmPool
->currentTempByteDispatched
;
759 mmPool
->currentTempByteDispatched
-= alignedMemSize
;
761 #ifdef RECORD_GRAND_TOTAL
762 MMMasterSetMaxTotalByteAllocated();
763 MMMasterSetMaxTotalByteDispatched();
766 spilloverPointerAddress
= (void*)((char*)address
- MAX_ALIGN
); // MAX_ALIGN no. of bytes preceding temp address
767 // Locate the last spillover memory
768 pointerToLastButOneSpillover
= &(mmPool
->firstSpillOverAddress
);
769 temp
= (void**)(*pointerToLastButOneSpillover
);
770 while (*temp
!= NULL
) {
771 pointerToLastButOneSpillover
= temp
;
772 temp
= (void**)*pointerToLastButOneSpillover
;
774 if (*pointerToLastButOneSpillover
!= spilloverPointerAddress
) {
775 fprintf(stderr
, "MMTempReturn(): address != lastSpilloverAddress! Last allocated temp memory must be freed first\n");
778 FREEALIGN(spilloverPointerAddress
);
779 *pointerToLastButOneSpillover
= NULL
;
781 if (mmPool
->poolByteDispatched
+ mmPool
->currentTempByteDispatched
> mmPool
->maxTotalByteDispatched
) {
782 mmPool
->maxTotalByteDispatched
= mmPool
->poolByteDispatched
+ mmPool
->currentTempByteDispatched
;
784 mmPool
->currentTempByteDispatched
-= memSize
+ MAX_ALIGN
;
785 mmPool
->currentTempByteSpillover
-= memSize
+ MAX_ALIGN
;
792 void MMTempPrintReport(MMPool
*mmPool
, FILE *output
) {
794 MMPoolPrintReport(mmPool
, output
);
798 MMBulk
*MMBulkCreate(MMPool
*mmPool
, const unsigned int itemSize
, const unsigned int itemPerAllocationInPowerOf2
,
799 const unsigned int boundaryCushionSize
, const unsigned int directorySize
) {
806 fprintf(stderr
, "MMBulkCreate() : itemSize = 0!\n");
809 if (itemPerAllocationInPowerOf2
>= BITS_IN_WORD
) {
810 fprintf(stderr
, "MMBulkCreate() : itemPerAllocationInPowerOf2 >= BITS_IN_WORD!\n");
815 if (mmPool
== NULL
) {
816 mmBulk
= MMUnitAllocate(sizeof(MMBulk
));
818 mmBulk
= MMPoolDispatch(mmPool
, sizeof(MMBulk
));
821 mmBulk
->itemSize
= itemSize
;
822 mmBulk
->itemPerAllocationInPowerOf2
= itemPerAllocationInPowerOf2
;
823 mmBulk
->boundaryCushionSize
= boundaryCushionSize
;
824 mmBulk
->indexMask
= truncateLeft(ALL_ONE_MASK
, BITS_IN_WORD
- itemPerAllocationInPowerOf2
);
825 mmBulk
->currentDirectoryEntry
= 0;
826 mmBulk
->nextUnusedItem
= 0;
827 mmBulk
->directorySize
= directorySize
;
829 if (mmPool
== NULL
) {
830 mmBulk
->directory
= MMUnitAllocate(sizeof(unsigned char*) * directorySize
);
832 mmBulk
->directory
= MMPoolDispatch(mmPool
, sizeof(unsigned char*) * directorySize
);
835 //Allocate memory for the first directory entry
836 mmBulk
->directory
[0] = MEMALIGN(boundaryCushionSize
* 2 + (itemSize
<< itemPerAllocationInPowerOf2
), MAX_ALIGN
);
837 if (mmBulk
->directory
[0] == NULL
) {
838 fprintf(stderr
, "MMBulkCreate() : cannot allocate memory!\n");
842 //Advance the address by boundaryCushionSize
843 mmBulk
->directory
[0] += boundaryCushionSize
;
845 for (i
=0; i
<mmMaster
.maxNumberOfBulks
; i
++) {
846 if (mmMaster
.mmBulk
[i
] == NULL
) {
847 mmMaster
.mmBulk
[i
] = mmBulk
;
852 fprintf(stderr
, "MMBulkCreate() : number of bulks > maxNumberOfBulk!\n");
857 unsigned int MMBulkIsActive(const MMBulk
*mmBulk
) {
859 return (mmBulk
->directory
!= (void*)mmBulk
);
863 void MMBulkSetInactive(MMBulk
*mmBulk
) {
865 if (mmBulk
->directory
!= NULL
) {
867 mmBulk
->directory
= (void*)mmBulk
;
871 unsigned int MMBulkByteAllocated(const MMBulk
*mmBulk
) {
873 return (mmBulk
->currentDirectoryEntry
+ 1) *
874 (mmBulk
->boundaryCushionSize
* 2 + (mmBulk
->itemSize
<< mmBulk
->itemPerAllocationInPowerOf2
));
878 unsigned int MMBulkByteDispatched(const MMBulk
*mmBulk
) {
880 return (mmBulk
->currentDirectoryEntry
) *
881 (mmBulk
->boundaryCushionSize
* 2 + (mmBulk
->itemSize
<< mmBulk
->itemPerAllocationInPowerOf2
)) +
882 mmBulk
->boundaryCushionSize
* 2 +
883 mmBulk
->itemSize
* mmBulk
->nextUnusedItem
;
887 unsigned int MMBulkUnitDispatched(const MMBulk
*mmBulk
) {
889 return mmBulk
->currentDirectoryEntry
* (1 << mmBulk
->itemPerAllocationInPowerOf2
) + mmBulk
->nextUnusedItem
;
893 void MMBulkFree(MMBulk
*mmBulk
) {
897 #ifdef RECORD_GRAND_TOTAL
898 MMMasterSetMaxTotalByteAllocated();
899 MMMasterSetMaxTotalByteDispatched();
902 for (i
=0; i
<=mmBulk
->currentDirectoryEntry
; i
++) {
903 FREEALIGN(mmBulk
->directory
[i
] - mmBulk
->boundaryCushionSize
);
906 if (MMBulkFindPoolUsed(mmBulk
) == NULL
) {
907 MMUnitFree(mmBulk
->directory
, sizeof(unsigned char*) * mmBulk
->directorySize
);
910 mmBulk
->directory
= NULL
;
912 MMBulkSetInactive(mmBulk
);
916 void MMBulkDestory(MMBulk
*mmBulk
) {
922 if (mmBulk
== NULL
) {
923 fprintf(stderr
, "MMBulkDestory(): mmBulk = NULL!\n");
928 if (MMBulkIsActive(mmBulk
)) {
934 // Update master directory
935 for (i
=0; i
<mmMaster
.maxNumberOfBulks
; i
++) {
936 if (mmMaster
.mmBulk
[i
] == temp
) {
937 mmMaster
.mmBulk
[i
] = NULL
;
938 if (MMBulkFindPoolUsed(temp
) == NULL
) {
939 MMUnitFree(temp
, sizeof(MMBulk
));
946 fprintf(stderr
, "MMBulkDestory() : cannot locate bulk in master!\n");
951 unsigned int MMBulkDispatch(MMBulk
*mmBulk
) {
953 if (mmBulk
->nextUnusedItem
>> mmBulk
->itemPerAllocationInPowerOf2
) {
954 mmBulk
->currentDirectoryEntry
++;
955 if (mmBulk
->currentDirectoryEntry
>= mmBulk
->directorySize
) {
956 fprintf(stderr
, "MMBulkDispatch() : memory directory size overflow!\n");
959 //Allocate memory for the next directory entry
960 mmBulk
->directory
[mmBulk
->currentDirectoryEntry
] = MEMALIGN(mmBulk
->boundaryCushionSize
* 2 + (mmBulk
->itemSize
<< mmBulk
->itemPerAllocationInPowerOf2
), MAX_ALIGN
);
961 if (mmBulk
->directory
[mmBulk
->currentDirectoryEntry
] == NULL
) {
962 fprintf(stderr
, "MMBulkDispatch() : cannot allocate memory!\n");
965 //Advance the address by boundaryCushionSize
966 mmBulk
->directory
[mmBulk
->currentDirectoryEntry
] += mmBulk
->boundaryCushionSize
;
967 mmBulk
->nextUnusedItem
= 0;
969 return ((mmBulk
->currentDirectoryEntry
<< mmBulk
->itemPerAllocationInPowerOf2
) | mmBulk
->nextUnusedItem
++);
973 void *MMBulkAddress(const MMBulk
*mmBulk
, const unsigned int index
) {
976 if (index
>= (((mmBulk
->currentDirectoryEntry
+1) << mmBulk
->itemPerAllocationInPowerOf2
) | mmBulk
->nextUnusedItem
)) {
977 fprintf(stderr
, "MMBulkAddress() : index out of range!\n");
982 return &(mmBulk
->directory
[index
>> mmBulk
->itemPerAllocationInPowerOf2
][(index
& mmBulk
->indexMask
) * mmBulk
->itemSize
]);
985 MMPool
*MMBulkFindPoolUsed(const MMBulk
*mmBulk
) {
990 for (i
=0; i
<mmMaster
.maxNumberOfPools
; i
++) {
991 if (mmMaster
.mmPool
[i
] != NULL
) {
992 if ((void*)mmBulk
>= (void*)mmMaster
.mmPool
[i
] &&
993 (void*)mmBulk
<= (void*)((char*)mmMaster
.mmPool
[i
] + mmMaster
.mmPool
[i
]->poolSize
)) {
994 return mmMaster
.mmPool
[i
];
996 temp
= mmMaster
.mmPool
[i
]->firstSpillOverAddress
;
997 while (temp
!= NULL
) {
998 if ((void*)((char*)temp
+ sizeof(void*)) == (void*)mmBulk
) {
999 return mmMaster
.mmPool
[i
];
1001 temp
= *((void**)temp
);
1010 void MMBulkPrintReport(MMBulk
*mmBulk
, FILE *output
){
1012 fprintf(output
, "Memory allocated : %u\n", MMBulkByteAllocated(mmBulk
));
1013 fprintf(output
, "Memory dispatched : %u\n", MMBulkByteDispatched(mmBulk
));
1017 void MMBulkSave(MMBulk
*mmBulk
, FILE *output
) {
1021 fwrite(&mmBulk
->itemSize
, sizeof(unsigned int), 1, output
);
1022 fwrite(&mmBulk
->itemPerAllocationInPowerOf2
, sizeof(unsigned int), 1, output
);
1023 fwrite(&mmBulk
->boundaryCushionSize
, sizeof(unsigned int), 1, output
);
1024 fwrite(&mmBulk
->currentDirectoryEntry
, sizeof(unsigned int), 1, output
);
1025 fwrite(&mmBulk
->nextUnusedItem
, sizeof(unsigned int), 1, output
);
1026 fwrite(&mmBulk
->directorySize
, sizeof(unsigned int), 1, output
);
1028 for (i
=0; i
<mmBulk
->currentDirectoryEntry
; i
++) {
1029 fwrite(mmBulk
->directory
[i
], mmBulk
->itemSize
<< mmBulk
->itemPerAllocationInPowerOf2
, 1, output
);
1032 if (mmBulk
->nextUnusedItem
> 0) {
1033 fwrite(mmBulk
->directory
[i
], mmBulk
->itemSize
* mmBulk
->nextUnusedItem
, 1, output
);
1038 MMBulk
*MMBulkLoad(MMPool
*mmPool
, FILE *input
) {
1043 mmBulk
= MMPoolDispatch(mmPool
, sizeof(MMBulk
));
1045 fread(&mmBulk
->itemSize
, sizeof(unsigned int), 1, input
);
1046 fread(&mmBulk
->itemPerAllocationInPowerOf2
, sizeof(unsigned int), 1, input
);
1047 fread(&mmBulk
->boundaryCushionSize
, sizeof(unsigned int), 1, input
);
1048 fread(&mmBulk
->currentDirectoryEntry
, sizeof(unsigned int), 1, input
);
1049 fread(&mmBulk
->nextUnusedItem
, sizeof(unsigned int), 1, input
);
1050 fread(&mmBulk
->directorySize
, sizeof(unsigned int), 1, input
);
1052 mmBulk
->indexMask
= truncateLeft(ALL_ONE_MASK
, BITS_IN_WORD
- mmBulk
->itemPerAllocationInPowerOf2
);
1054 mmBulk
->directory
= MMPoolDispatch(mmPool
, sizeof(unsigned char*) * mmBulk
->directorySize
);
1056 for (i
=0; i
<mmBulk
->currentDirectoryEntry
; i
++) {
1057 mmBulk
->directory
[i
] = MEMALIGN(mmBulk
->boundaryCushionSize
* 2 +
1058 (mmBulk
->itemSize
<< mmBulk
->itemPerAllocationInPowerOf2
), MAX_ALIGN
);
1059 if (mmBulk
->directory
[i
] == NULL
) {
1060 fprintf(stderr
, "MMBulkLoad() : cannot allocate memory!\n");
1064 //Advance the address by boundaryCushionSize
1065 mmBulk
->directory
[i
] += mmBulk
->boundaryCushionSize
;
1067 fread(mmBulk
->directory
[i
], mmBulk
->itemSize
<< mmBulk
->itemPerAllocationInPowerOf2
, 1, input
);
1070 mmBulk
->directory
[i
] = MEMALIGN(mmBulk
->boundaryCushionSize
* 2 +
1071 (mmBulk
->itemSize
<< mmBulk
->itemPerAllocationInPowerOf2
), MAX_ALIGN
);
1072 if (mmBulk
->directory
[i
] == NULL
) {
1073 fprintf(stderr
, "MMBulkLoad() : cannot allocate memory!\n");
1077 //Advance the address by boundaryCushionSize
1078 mmBulk
->directory
[i
] += mmBulk
->boundaryCushionSize
;
1080 if (mmBulk
->nextUnusedItem
> 0) {
1081 fread(mmBulk
->directory
[i
], mmBulk
->itemSize
* mmBulk
->nextUnusedItem
, 1, input
);
1085 for (i
=0; i
<mmMaster
.maxNumberOfBulks
; i
++) {
1086 if (mmMaster
.mmBulk
[i
] == NULL
) {
1087 mmMaster
.mmBulk
[i
] = mmBulk
;
1092 fprintf(stderr
, "MMBulkLoad() : number of bulks > maxNumberOfBulk!\n");