modified: makefile
[GalaxyCodeBases.git] / BGI / soap_src / soap_builder / MemManager.c
blob1351062efe8cf399b8d15259bdb035da5ffe4b8a
1 /*
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.
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #ifndef _WIN32
29 #include <mm_malloc.h>
30 #endif
31 #include "MiscUtilities.h"
32 #include "MemManager.h"
34 MMMaster mmMaster;
36 void *MMMalloc(const unsigned int memSize) {
38 void *address;
40 address = MEMALIGN(memSize, MAX_ALIGN);
41 if (address == NULL) {
42 fprintf(stderr, "MMMalloc() : cannot allocate memory!\n");
43 exit(1);
45 return address;
49 void MMFree(void *address) {
51 FREEALIGN(address);
55 void MMMasterInitialize(const unsigned int maxNumberOfPools, const unsigned int maxNumberOfBulks,
56 const int traceUnitByteAllocation, FILE* unitByteTraceFile) {
58 unsigned int i;
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;
72 } else {
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;
80 } else {
81 mmMaster.mmPool = NULL;
84 mmMaster.traceUnitByteAllocation = traceUnitByteAllocation;
85 mmMaster.unitByteTraceFile = unitByteTraceFile;
89 void MMMasterFreeAll() {
91 unsigned int i;
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() {
121 unsigned int i;
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() {
147 unsigned int i;
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;
179 } else {
180 return mmMaster.maxTotalByteAllocated;
185 unsigned int MMMasterMaxTotalByteDispatched() {
187 unsigned int currentTotalByteDispatched ;
189 currentTotalByteDispatched = MMMasterCurrentTotalByteDispatched();
191 if (currentTotalByteDispatched > mmMaster.maxTotalByteDispatched) {
192 return currentTotalByteDispatched;
193 } else {
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) {
225 unsigned int i;
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) {
257 void *temp = NULL;
259 #ifdef DEBUG
260 if (memSize == 0) {
261 fprintf(stderr, "MMUnitAllocate() : memSize = 0!\n");
262 exit(1);
264 #endif
266 temp = MEMALIGN(memSize, MAX_ALIGN);
267 if (temp == NULL) {
268 fprintf(stderr, "MMUnitAllocate() : cannot allocate memory!\n");
269 exit(1);
272 mmMaster.currentUnitByteAllocated += memSize;
273 if (mmMaster.traceUnitByteAllocation) {
274 fprintf(mmMaster.unitByteTraceFile, "MMUnitAllocate : %u\n", memSize);
277 return temp;
281 void *MMUnitReallocate(void *address, const unsigned int newMemSize, const unsigned int oldMemSize) {
283 void *temp;
285 #ifdef DEBUG
286 if (newMemSize == 0) {
287 fprintf(stderr, "MMUnitReallocate() : newMemSize = 0!\n");
288 exit(1);
290 if (oldMemSize == 0) {
291 fprintf(stderr, "MMUnitReallocate() : oldMemSize = 0!\n");
292 exit(1);
294 #endif
296 if (mmMaster.traceUnitByteAllocation) {
297 fprintf(mmMaster.unitByteTraceFile, "MMUnitReallocate\n");
300 temp = MMUnitAllocate(newMemSize);
301 if (temp == NULL) {
302 fprintf(stderr, "MMUnitReallocate() : cannot allocate memory!\n");
303 exit(1);
305 memcpy(temp, address, min(newMemSize, oldMemSize));
307 MMUnitFree(address, oldMemSize);
309 return temp;
313 void MMUnitFree(void *address, const unsigned int memSize) {
315 #ifdef DEBUG
316 if (address == NULL) {
317 fprintf(stderr, "MMUnitFree() : address = NULL!\n");
318 exit(1);
320 if (mmMaster.currentUnitByteAllocated < memSize) {
321 fprintf(stderr, "MMUnitFree() : currentUnitByteAllocated < memSize!\n");
322 exit(1);
324 #endif
326 FREEALIGN(address);
328 #ifdef RECORD_GRAND_TOTAL
329 MMMasterSetMaxTotalByteAllocated();
330 MMMasterSetMaxTotalByteDispatched();
331 #endif
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;
353 } else {
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) {
368 MMPool *mmPool;
369 unsigned int i;
371 #ifdef DEBUG
372 if (poolSize < sizeof(MMPool)) {
373 fprintf(stderr, "MMPoolCreate() : poolSize < MMPool!\n");
374 exit(1);
376 #endif
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
380 exit(1);
383 mmPool = MEMALIGN(poolSize, MAX_ALIGN);
384 if (mmPool == NULL) {
385 fprintf(stderr, "MMPoolCreate() : cannot allocate memory!\n");
386 exit(1);
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;
400 return mmPool;
404 fprintf(stderr, "MMPoolCreate() : number of pools > maxNumberOfPools!\n");
405 exit(1);
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");
418 exit(1);
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;
444 } else {
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;
454 } else {
455 return 0;
460 MMPool *MMPoolFree(MMPool *mmPool) {
462 MMPool *dummyMMPool;
463 unsigned int i;
464 void *temp1, *temp2;
466 #ifdef DEBUG
467 if (mmPool == NULL) {
468 fprintf(stderr, "MMPoolFree(): mmPool = NULL!\n");
469 exit(1);
471 #endif
473 #ifdef RECORD_GRAND_TOTAL
474 MMMasterSetMaxTotalByteAllocated();
475 MMMasterSetMaxTotalByteDispatched();
476 #endif
478 dummyMMPool = MEMALIGN(sizeof(MMPool), MAX_ALIGN);
479 if (dummyMMPool == NULL) {
480 fprintf(stderr, "MMPoolFree() : cannot allocate memory!\n");
481 exit(1);
484 // Free spillover memory
485 temp1 = mmPool->firstSpillOverAddress;
486 while (temp1 != NULL) {
487 temp2 = *((void**)temp1);
488 FREEALIGN(temp1);
489 temp1 = temp2;
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;
507 FREEALIGN(mmPool);
508 return dummyMMPool;
512 fprintf(stderr, "MMPoolFree() : cannot locate pool in master!\n");
513 exit(1);
517 void MMPoolReset(MMPool *mmPool) {
519 void *temp1, *temp2;
521 #ifdef DEBUG
522 if (mmPool == NULL) {
523 fprintf(stderr, "MMPoolReset(): mmPool = NULL!\n");
524 exit(1);
526 #endif
528 #ifdef RECORD_GRAND_TOTAL
529 MMMasterSetMaxTotalByteAllocated();
530 MMMasterSetMaxTotalByteDispatched();
531 #endif
533 // Free spillover memory
534 temp1 = mmPool->firstSpillOverAddress;
535 while (temp1 != NULL) {
536 temp2 = *((void**)temp1);
537 FREEALIGN(temp1);
538 temp1 = temp2;
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) {
552 unsigned int i;
553 MMPool *temp;
555 #ifdef DEBUG
556 if (mmPool == NULL) {
557 fprintf(stderr, "MMPoolDestory(): mmPool = NULL!\n");
558 exit(1);
560 #endif
562 if (MMPoolIsActive(mmPool)) {
563 temp = MMPoolFree(mmPool);
564 } else {
565 temp = mmPool;
568 // Update master directory
569 for (i=0; i<mmMaster.maxNumberOfPools; i++) {
570 if (mmMaster.mmPool[i] == temp) {
571 mmMaster.mmPool[i] = NULL;
572 FREEALIGN(temp);
573 temp = NULL;
577 if (temp != NULL) {
578 fprintf(stderr, "MMPoolDestory() : cannot locate pool in master!\n");
579 exit(1);
584 void *MMPoolDispatch(MMPool *mmPool, const unsigned int memSize) {
586 void **temp;
587 unsigned int totalPoolMemoryUsed, nextPoolMemoryOffset;
588 unsigned int align, skipForAlign;
590 if (mmPool == NULL) {
591 return MMUnitAllocate(memSize);
593 if (memSize == 0) {
594 fprintf(stderr, "MMPoolDispatch(): memSize = 0!\n");
595 exit(1);
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) {
605 align = MAX_ALIGN;
607 if (align < MIN_ALIGN) {
608 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;
615 return temp;
616 } else {
617 // Spillover
618 // Allocate for linked list pointer as well
619 temp = MEMALIGN(memSize + MAX_ALIGN, MAX_ALIGN); // spillover memory is always aligned to MAX_ALIGN
620 if (temp == NULL) {
621 fprintf(stderr, "MMPoolDispatch(): cannot allocate memory!\n");
622 exit(1);
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");
641 exit(1);
643 if (memSize == 0) {
644 fprintf(stderr, "MMPoolDispatchOffset(): memSize = 0!\n");
645 exit(1);
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) {
655 align = MAX_ALIGN;
657 if (align < MIN_ALIGN) {
658 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");
664 exit(1);
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) {
693 void **temp;
694 unsigned int totalPoolMemoryUsed, nextTempMemoryOffset;
695 unsigned int alignedMemSize;
696 void **pointerToLastSpilloverAddress;
698 if (mmPool == NULL) {
699 return MMUnitAllocate(memSize);
701 if (memSize == 0) {
702 fprintf(stderr, "MMTempDispatch(): memSize = 0!\n");
703 exit(1);
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;
715 return temp;
716 } else {
717 // Spillover
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);
727 if (temp == NULL) {
728 fprintf(stderr, "MMTempDispatch(): cannot allocate memory!\n");
729 exit(1);
731 *pointerToLastSpilloverAddress = temp;
732 *temp = NULL;
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) {
742 void **temp;
743 unsigned int alignedMemSize;
744 void **pointerToLastButOneSpillover;
745 void *spilloverPointerAddress;
747 if (mmPool == NULL) {
748 MMUnitFree(address, memSize);
749 } else {
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;
760 } else {
761 #ifdef RECORD_GRAND_TOTAL
762 MMMasterSetMaxTotalByteAllocated();
763 MMMasterSetMaxTotalByteDispatched();
764 #endif
765 // Spillover
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");
776 exit(1);
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) {
801 unsigned int i;
802 MMBulk *mmBulk;
804 #ifdef DEBUG
805 if (itemSize == 0) {
806 fprintf(stderr, "MMBulkCreate() : itemSize = 0!\n");
807 exit(1);
809 if (itemPerAllocationInPowerOf2 >= BITS_IN_WORD) {
810 fprintf(stderr, "MMBulkCreate() : itemPerAllocationInPowerOf2 >= BITS_IN_WORD!\n");
811 exit(1);
813 #endif
815 if (mmPool == NULL) {
816 mmBulk = MMUnitAllocate(sizeof(MMBulk));
817 } else {
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);
831 } else {
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");
839 exit(1);
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;
848 return mmBulk;
852 fprintf(stderr, "MMBulkCreate() : number of bulks > maxNumberOfBulk!\n");
853 exit(1);
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) {
895 unsigned int i;
897 #ifdef RECORD_GRAND_TOTAL
898 MMMasterSetMaxTotalByteAllocated();
899 MMMasterSetMaxTotalByteDispatched();
900 #endif
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) {
918 unsigned int i;
919 MMBulk *temp;
921 #ifdef DEBUG
922 if (mmBulk == NULL) {
923 fprintf(stderr, "MMBulkDestory(): mmBulk = NULL!\n");
924 exit(1);
926 #endif
928 if (MMBulkIsActive(mmBulk)) {
929 MMBulkFree(mmBulk);
932 temp = 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));
941 temp = NULL;
945 if (temp != NULL) {
946 fprintf(stderr, "MMBulkDestory() : cannot locate bulk in master!\n");
947 exit(1);
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");
957 exit(1);
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");
963 exit(1);
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) {
975 #ifdef DEBUG
976 if (index >= (((mmBulk->currentDirectoryEntry+1) << mmBulk->itemPerAllocationInPowerOf2) | mmBulk->nextUnusedItem)) {
977 fprintf(stderr, "MMBulkAddress() : index out of range!\n");
978 exit(1);
980 #endif
982 return &(mmBulk->directory[index >> mmBulk->itemPerAllocationInPowerOf2][(index & mmBulk->indexMask) * mmBulk->itemSize]);
985 MMPool *MMBulkFindPoolUsed(const MMBulk *mmBulk) {
987 unsigned int i;
988 void *temp;
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);
1006 return NULL;
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) {
1019 unsigned int i;
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) {
1040 unsigned int i;
1041 MMBulk *mmBulk;
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");
1061 exit(1);
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");
1074 exit(1);
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;
1088 return mmBulk;
1092 fprintf(stderr, "MMBulkLoad() : number of bulks > maxNumberOfBulk!\n");
1093 exit(1);